Dev #9
+126
-29
@@ -1,41 +1,138 @@
|
|||||||
# FlixCooks Project Brain
|
# FlixCooks Project Brain
|
||||||
|
|
||||||
This document summarizes the architectural knowledge, conventions, and learnings accumulated during our session.
|
This document summarizes architectural knowledge, conventions, and learnings for humans and AI agents working on this repo.
|
||||||
|
|
||||||
## 1. Project Architecture & Stack
|
## 1. Project Architecture & Stack
|
||||||
- **Backend:** Vanilla PHP. The project intentionally avoids heavy frameworks.
|
- **Backend:** Vanilla PHP. No heavy frameworks.
|
||||||
- **Database:** Flat-file JSON database (`data/recipes.json`). Data is loaded and saved via utility functions in `helpers.php`.
|
- **Database:** PostgreSQL (optional) via `DATABASE_URL` in `.env`, with automatic seed from and backup to `data/recipes.json`. All data access lives in `helpers.php`; connection logic in `config.php`.
|
||||||
- **Admin Panel (`admin.php`):** Acts as a lightweight CMS. It uses simple textareas where each line maps to an array element (e.g., for `ingredients`, `steps`, `step_videos`, `step_timers`). This keeps the JSON structure clean and parsing straightforward.
|
- **Site settings (legal pages):** Flat-file `data/site.json` via `load_site_settings()` / `save_site_settings()` — not in Postgres.
|
||||||
- **Frontend:** Server-rendered PHP templates (`index.php`, `recipe.php`) with Vanilla JavaScript and Vanilla CSS. No Tailwind or heavy component libraries.
|
- **Admin Panel (`admin.php`):** Lightweight CMS. Textareas use one line per array element (`ingredients`, `steps`, `step_videos`, `step_timers`).
|
||||||
|
- **Frontend:** Server-rendered PHP (`index.php`, `recipe.php`, …), Vanilla JS/CSS. Firebase compat SDKs in `partials/head.php` for auth, Firestore (newsletter/bookmarks where used).
|
||||||
|
- **Config:** `config.php` loads `.env`, exposes `get_firebase_config()`, `get_db_connection()`. Never commit `.env` (see `.gitignore`).
|
||||||
|
|
||||||
## 2. Design & Aesthetics
|
## 2. Design & Aesthetics
|
||||||
- **CSS:** Highly customized CSS with modern design tokens (e.g., `var(--ease-out-expo)`, `var(--surface-1)`).
|
- **CSS:** Custom properties (`var(--ease-out-expo)`, `var(--surface-1)`), glassmorphism, `FloemaLayoutGrid`.
|
||||||
- **Animations:** Employs sophisticated micro-animations, glassmorphism (`backdrop-filter: blur`), and dynamic layouts (e.g., `clip-path` for overlays).
|
- **Lenis:** Call `lenis.stop()` when opening fullscreen overlays (e.g. Cooking Mode); `lenis.start()` on close.
|
||||||
- **Smooth Scrolling:** Uses **Lenis** (`LenisSmoothScroll`).
|
- **Preloader:** `CapitoliumPreloader` on homepage; once per session via `sessionStorage('flixcooks_preloader_seen')`.
|
||||||
- *Crucial Rule:* Whenever a fullscreen overlay (like the Cooking Mode) is opened, `lenis.stop()` must be called to prevent background scrolling. When closed, call `lenis.start()`.
|
|
||||||
- **Preloader:** A custom `CapitoliumPreloader` runs on the homepage. It is cached in `sessionStorage('flixcooks_preloader_seen')` so it only fires once per browsing session.
|
|
||||||
|
|
||||||
## 3. Antigravity Agent Configuration
|
## 3. Antigravity Agent Configuration
|
||||||
- **Workspace Rules:** Best placed in `.agents/rules/` (e.g., `AGENT.md`). To ensure they are always active, the frontmatter must include:
|
- **Workspace Rules:** `.agents/rules/` with `always_on: true` and `glob: "*"` in frontmatter.
|
||||||
```yaml
|
- **Custom Skills:** `.agents/skills/` (e.g. `close_feature.json` for Git merge workflow).
|
||||||
always_on: true
|
|
||||||
glob: "*"
|
|
||||||
```
|
|
||||||
- **Custom Skills:** Can be defined as JSON files in `.agents/skills/`. We successfully created `close_feature.json` to automate the Git workflow of checking out `main`, merging a feature branch, verifying functionality, and deleting the branch.
|
|
||||||
|
|
||||||
## 4. GitHub Actions & CI/CD
|
## 4. GitHub Actions & CI/CD
|
||||||
- **Gemini Code Review Automation:** We integrated `petarzarkov/gemini-code-review-action` to automatically review PRs.
|
- **Gemini PR review:** `petarzarkov/gemini-code-review-action`; secrets via `env:` not `with:`; pin action versions; use full model names (e.g. `gemini-2.0-flash-lite`).
|
||||||
- **Secrets:** Must be passed using `env:` instead of `with:` (e.g., `GEMINI_API_KEY`, `GITHUB_TOKEN`), otherwise the action fails with unexpected input errors. NEVER hardcode API keys in workflow files.
|
|
||||||
- **Model Naming:** Google's `v1beta` API is very strict. `gemini-1.5-flash` often fails. You must use the fully-qualified name like `gemini-1.5-flash-latest` or `gemini-2.0-flash-lite`.
|
|
||||||
- **Pinning Versions:** Always pin GitHub Actions to a specific version tag (e.g., `@v1.0.4`) rather than `@latest` to prevent unexpected breaking changes.
|
|
||||||
|
|
||||||
## 5. Completed Milestones
|
---
|
||||||
- **Phase 3 (Nutrition):** Implemented. Recipes now store `calories`, `protein`, `carbs`, and `fat`. Admin panel handles inputs, and the UI displays them beautifully.
|
|
||||||
- **Phase 4 (Interactive Cooking Mode):** Implemented. Recipes now support step-by-step looping background videos and interactive timers (`step_videos`, `step_timers`). The UI utilizes a fullscreen overlay slider with Vanilla JS logic.
|
|
||||||
- **Phase 6 (Firestore Database Migration):** Migrated recipes database from `data/recipes.json` to Firebase Firestore.
|
|
||||||
- *Zero-Dependency REST API Read:* Server-side read requests in `helpers.php` use native PHP cURL to query the Firestore REST API `/documents/recipes`. Complex Firestore nested type maps are dynamically parsed into clean standard associative arrays using custom decoders.
|
|
||||||
- *Dynamic Local Fallback:* In case of rate limits, network failures, or missing `.env` config, all lookup functions automatically fail back to the local `recipes.json` flat-file, guaranteeing 100% database availability and site resilience.
|
|
||||||
- *Browser-Driven Seeding & Auto-Sync:* Admin seeding and real-time updates are executed client-side in `admin.php` via the authenticated Firebase Client SDK, keeping the local file and Cloud Firestore perfectly in sync without server-side OAuth2 keys.
|
|
||||||
|
|
||||||
## 6. Next Steps
|
## 5. PostgreSQL — Schema & Data Flow
|
||||||
According to `TODO.md`, the next major feature block is completing the database seeding (by clicking "Seed Firestore" on `admin.php` in the browser) and verifying all recipe updates reflect in real-time. Afterwards, we can proceed to **Phase 5 (PWA & Offline Support)**.
|
|
||||||
|
### Table `recipes` (only app table today)
|
||||||
|
Created by `init_db()` in `helpers.php` if missing:
|
||||||
|
|
||||||
|
| Column | Type | Role |
|
||||||
|
|-------------|-------------|------|
|
||||||
|
| `slug` | `VARCHAR(255)` PRIMARY KEY | Stable recipe ID (URLs: `recipe.php?slug=…`) |
|
||||||
|
| `data` | `JSONB` NOT NULL | **Entire recipe document** (title, i18n, ingredients, steps, nutrition, …) |
|
||||||
|
| `created_at`| `TIMESTAMP` | Auto on insert |
|
||||||
|
| `updated_at`| `TIMESTAMP` | Set on `ON CONFLICT` update in `save_recipes()` |
|
||||||
|
|
||||||
|
**Design choice:** Document-in-a-row (JSONB), not normalized columns. PHP already works with JSON arrays; avoids schema migrations for every new recipe field. PostgreSQL can still query inside JSON (`data->'i18n'->'en'->>'title'`).
|
||||||
|
|
||||||
|
### Runtime flow
|
||||||
|
1. `get_db_connection()` in `config.php` parses `DATABASE_URL` → PDO `pgsql:` DSN.
|
||||||
|
2. If no URL or connection fails → `load_recipes_local()` reads `data/recipes.json` only.
|
||||||
|
3. If connected → `init_db()` once per request (static flag): `CREATE TABLE IF NOT EXISTS`, then if `COUNT(*) = 0` → seed all rows from `data/recipes.json`.
|
||||||
|
4. `load_recipes()` / `load_recipe_by_slug()` decode `data` JSONB to PHP arrays.
|
||||||
|
5. `save_recipes()` (admin): upsert all recipes in Postgres **and** write `data/recipes.json` as backup.
|
||||||
|
|
||||||
|
### `config.php` functions
|
||||||
|
- `load_env()` — parses `.env` into `getenv()` / `$_ENV` / `$_SERVER`.
|
||||||
|
- `get_firebase_config()` — returns Firebase web config array from `FIREBASE_*` env vars. **Required** by `partials/head.php` and `admin.php`. Was accidentally removed in postgres commit `e7f35d7`; restored (undefined function caused HTTP 500).
|
||||||
|
- `get_db_connection()` — returns `PDO` or `null`; logs failures, does not throw.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. Local Development — Docker Postgres
|
||||||
|
|
||||||
|
### Files
|
||||||
|
- `docker-compose.dev.yml` — Postgres 16 Alpine, container `flixcooks-postgres-dev`, port `5432`.
|
||||||
|
- `.env.example` — template including local `DATABASE_URL`.
|
||||||
|
- `scripts/db-check.php` — CLI: connect, `init_db()`, print recipe count + sample slugs/titles.
|
||||||
|
|
||||||
|
### Docker credentials (dev only)
|
||||||
|
```
|
||||||
|
POSTGRES_USER=flixcooks
|
||||||
|
POSTGRES_PASSWORD=flixcooks_dev
|
||||||
|
POSTGRES_DB=flixcooks_dev
|
||||||
|
DATABASE_URL="postgresql://flixcooks:flixcooks_dev@127.0.0.1:5432/flixcooks_dev"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.dev.yml up -d # start
|
||||||
|
docker compose -f docker-compose.dev.yml ps # health
|
||||||
|
docker compose -f docker-compose.dev.yml down # stop (data kept)
|
||||||
|
docker compose -f docker-compose.dev.yml down -v # stop + wipe volume → re-seed on next hit
|
||||||
|
|
||||||
|
docker exec -it flixcooks-postgres-dev psql -U flixcooks -d flixcooks_dev
|
||||||
|
# psql: \dt , \d recipes , SELECT slug FROM recipes; , \q
|
||||||
|
```
|
||||||
|
|
||||||
|
### PHP requirements (WSL/Linux)
|
||||||
|
- Extension **`php-pgsql`** (or `php8.5-pgsql`) required; without it: log `could not find driver`, fallback to JSON.
|
||||||
|
- Install interactively: `sudo apt install php8.5-pgsql` (sudo in non-interactive agent shells may timeout).
|
||||||
|
- Verify: `php -m | grep pgsql` → expect `pdo_pgsql`, `pgsql`.
|
||||||
|
|
||||||
|
### App server
|
||||||
|
```bash
|
||||||
|
php -S localhost:8000
|
||||||
|
php scripts/db-check.php # after .env + pgsql OK
|
||||||
|
```
|
||||||
|
|
||||||
|
### `.env` rules for agents
|
||||||
|
- Copy from `.env.example`; never commit `.env`.
|
||||||
|
- **Local:** use `127.0.0.1` Docker URL above.
|
||||||
|
- **Railway production:** `postgres.railway.internal` only works **inside** Railway network — not from local WSL. For local access to hosted DB use Railway **public** proxy URL from dashboard, or prefer Docker for dev.
|
||||||
|
- **Firebase:** `FIREBASE_API_KEY`, `FIREBASE_AUTH_DOMAIN`, `FIREBASE_PROJECT_ID`, `FIREBASE_STORAGE_BUCKET`, `FIREBASE_MESSAGING_SENDER_ID`, `FIREBASE_APP_ID` — empty values break client `firebase.initializeApp()` in browser.
|
||||||
|
- Omit `DATABASE_URL` entirely to force JSON-only mode (UI work without Postgres).
|
||||||
|
|
||||||
|
### Environment separation (important)
|
||||||
|
- One database per environment (local Docker / staging / production).
|
||||||
|
- Never point a dev branch `.env` at production Postgres.
|
||||||
|
- Export/import between envs: `pg_dump` / `psql` when needed; document URLs in platform secrets (Railway variables), not in repo.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Troubleshooting (known issues)
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|--------|--------|-----|
|
||||||
|
| HTTP 500, `Call to undefined function get_firebase_config()` | Function missing from `config.php` | Ensure `get_firebase_config()` exists in `config.php` |
|
||||||
|
| Log: `could not find driver` | `php-pgsql` not installed | `sudo apt install php8.5-pgsql` |
|
||||||
|
| Log: connection failed, host `postgres.railway.internal` | Internal Railway hostname from local machine | Use Docker local URL or Railway public URL |
|
||||||
|
| Site loads, no recipes from DB | `DATABASE_URL` unset or DB empty and seed file missing | Set URL, ensure `data/recipes.json` exists, hit site or run `db-check.php` |
|
||||||
|
| Recipes work without Docker | Expected fallback | `load_recipes_local()` uses JSON when `get_db_connection()` is null |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Completed Milestones
|
||||||
|
- **Phase 3 (Nutrition):** `calories`, `protein`, `carbs`, `fat` on recipes; admin + UI.
|
||||||
|
- **Phase 4 (Cooking Mode):** `step_videos`, `step_timers`; fullscreen overlay.
|
||||||
|
- **Phase 6 (Postgres):** `recipes` JSONB table; seed from JSON; admin dual-write.
|
||||||
|
- **Local dev Postgres:** `docker-compose.dev.yml`, README section, `scripts/db-check.php`, `.env.example` with `DATABASE_URL`.
|
||||||
|
- **Bugfix (May 2026):** Restored `get_firebase_config()` after postgres migration regression.
|
||||||
|
- **Local profile data:** Favorites/goals via `assets/fc-local.js` (`localStorage`). Newsletter may use `mailto:` or Firestore depending on page.
|
||||||
|
|
||||||
|
## 9. Next Steps
|
||||||
|
See `.agents/TODO.md` (e.g. PWA & offline support). README `Local Postgres (Docker)` and `Postgres in diesem Projekt` sections mirror setup for humans.
|
||||||
|
|
||||||
|
## 10. Key file map (data layer)
|
||||||
|
| File | Purpose |
|
||||||
|
|------|---------|
|
||||||
|
| `config.php` | `.env`, Firebase config, PDO |
|
||||||
|
| `helpers.php` | `init_db`, `load_recipes`, `save_recipes`, site settings |
|
||||||
|
| `data/recipes.json` | Seed + fallback + admin backup |
|
||||||
|
| `data/site.json` | Imprint/privacy settings |
|
||||||
|
| `docker-compose.dev.yml` | Local Postgres |
|
||||||
|
| `scripts/db-check.php` | Connection + seed smoke test |
|
||||||
|
| `partials/head.php` | Firebase init via `get_firebase_config()` |
|
||||||
|
|||||||
+5
-8
@@ -1,9 +1,6 @@
|
|||||||
# FlixCooks Firebase Configuration
|
# FlixCooks – lokale Entwicklung (.env wird nicht committed)
|
||||||
# Replace these placeholder values with your actual Firebase project settings.
|
# Kopieren: cp .env.example .env
|
||||||
|
|
||||||
FIREBASE_API_KEY="AIzaSyYourApiKeyHere"
|
# --- Postgres (docker-compose.dev.yml) ---
|
||||||
FIREBASE_AUTH_DOMAIN="flixcooks-your-project-id.firebaseapp.com"
|
# Nur setzen, wenn du die lokale DB testen willst. Ohne DATABASE_URL → Fallback auf data/recipes.json
|
||||||
FIREBASE_PROJECT_ID="flixcooks-your-project-id"
|
DATABASE_URL="postgresql://flixcooks:flixcooks_dev@127.0.0.1:5432/flixcooks_dev"
|
||||||
FIREBASE_STORAGE_BUCKET="flixcooks-your-project-id.appspot.com"
|
|
||||||
FIREBASE_MESSAGING_SENDER_ID="123456789012"
|
|
||||||
FIREBASE_APP_ID="1:123456789012:web:abcdef123456"
|
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ The project is architected to remain extremely lightweight and fast, intentional
|
|||||||
- `index.php`: The atmospheric landing page showcasing featured recipe selections, introducing the brand, and housing the **Sleek Swipe Discovery Carousel**.
|
- `index.php`: The atmospheric landing page showcasing featured recipe selections, introducing the brand, and housing the **Sleek Swipe Discovery Carousel**.
|
||||||
- `recipe.php`: The immersive recipe detail page, featuring floating macro-nutrition widgets, interactive ingredients lists, and the fullscreen **Step-by-Step Cooking Mode**.
|
- `recipe.php`: The immersive recipe detail page, featuring floating macro-nutrition widgets, interactive ingredients lists, and the fullscreen **Step-by-Step Cooking Mode**.
|
||||||
- `admin.php`: A custom, lightweight CMS/admin dashboard allowing full CRUD capabilities over the recipe database, dynamic ingredient line parsing, cooking timers, and video URL associations.
|
- `admin.php`: A custom, lightweight CMS/admin dashboard allowing full CRUD capabilities over the recipe database, dynamic ingredient line parsing, cooking timers, and video URL associations.
|
||||||
- `login.php` & `register.php`: Fully responsive, glassmorphic auth portals powered by Firebase.
|
- `login.php`: Local profile page for dietary goals and saved favorites (browser storage).
|
||||||
- **Support & Layouts**:
|
- **Support & Layouts**:
|
||||||
- `partials/`: Contains modular templates (`head.php`, `header.php`, `footer.php`) to maintain a clean DRY structure.
|
- `partials/`: Contains modular templates (`head.php`, `header.php`, `footer.php`) to maintain a clean DRY structure.
|
||||||
- `helpers.php`: Core PHP utilities containing data formatting helpers and the data access layer for the flat-file database.
|
- `helpers.php`: Core PHP utilities containing data formatting helpers and the data access layer for the flat-file database.
|
||||||
- `config.php`: Environment-independent configuration loader which reads runtime secrets from `.env`.
|
- `config.php`: Environment-independent configuration loader which reads runtime secrets from `.env`.
|
||||||
- `api/`: Lightweight, stateless backend endpoints supporting AJAX operations (e.g., newsletter subscriptions, bookmarks, recommendation queries).
|
- `assets/fc-local.js`: Browser-side storage for favorites and dietary goals.
|
||||||
- `data/`: Houses `recipes.json`, our flat-file recipe database.
|
- `data/`: Houses `recipes.json`, our flat-file recipe database.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -36,13 +36,9 @@ FlixCooks uses a modern, carefully curated vanilla tech-stack focused on lightni
|
|||||||
|
|
||||||
### ⚙️ Backend & Data
|
### ⚙️ Backend & Data
|
||||||
- **Engine**: Vanilla PHP.
|
- **Engine**: Vanilla PHP.
|
||||||
- **Database**: Flat-file JSON database (`data/recipes.json`), allowing lightning-quick load times and simple structural schemas without heavy overhead.
|
- **Database**: PostgreSQL (production/staging) with automatic seed from `data/recipes.json`. Without `DATABASE_URL`, the app falls back to the JSON file.
|
||||||
- **Environment**: Custom `.env` variable parser integrated into PHP bootstrap.
|
- **Environment**: Custom `.env` variable parser integrated into PHP bootstrap.
|
||||||
|
|
||||||
### 🔒 Integrations & Cloud Services
|
|
||||||
- **Firebase Authentication**: Client and server-side synchronized user sessions for profile management.
|
|
||||||
- **Firebase Firestore**: Real-time database managing newsletter subscribers and user bookmarks/favorites lists.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Local Development Setup
|
## 🚀 Local Development Setup
|
||||||
@@ -51,7 +47,8 @@ Follow these simple steps to spin up the local development environment.
|
|||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
Make sure you have the following installed on your local machine:
|
Make sure you have the following installed on your local machine:
|
||||||
- **PHP** (v7.4 or higher recommended)
|
- **PHP** (8.x recommended) with the **pgsql** extension (`php-pgsql` on Linux/WSL)
|
||||||
|
- **Docker** (for local Postgres via `docker-compose.dev.yml`)
|
||||||
- A modern web browser
|
- A modern web browser
|
||||||
|
|
||||||
### 1. Set Up Environment Variables
|
### 1. Set Up Environment Variables
|
||||||
@@ -59,14 +56,59 @@ Make sure you have the following installed on your local machine:
|
|||||||
```bash
|
```bash
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
```
|
```
|
||||||
2. Open `.env` and fill in your actual **Firebase project settings** (API keys, project identifier, authentication domain, etc.):
|
2. Open `.env` and optionally set **local Postgres** (see [Local Postgres (Docker)](#local-postgres-docker) below).
|
||||||
```env
|
|
||||||
FIREBASE_API_KEY="AIzaSyYourApiKeyHere"
|
|
||||||
FIREBASE_AUTH_DOMAIN="flixcooks-your-project-id.firebaseapp.com"
|
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Start the Development Server
|
### 2. Local Postgres (Docker)
|
||||||
|
|
||||||
|
Für DB-Integration auf einem Dev-Branch – getrennt von Production.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Container starten
|
||||||
|
docker compose -f docker-compose.dev.yml up -d
|
||||||
|
|
||||||
|
# Warten bis healthy (einmalig prüfen)
|
||||||
|
docker compose -f docker-compose.dev.yml ps
|
||||||
|
```
|
||||||
|
|
||||||
|
In `.env` (Werte passen zu `docker-compose.dev.yml`):
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="postgresql://flixcooks:flixcooks_dev@127.0.0.1:5432/flixcooks_dev"
|
||||||
|
```
|
||||||
|
|
||||||
|
**PHP-Extension (WSL/Ubuntu, einmalig):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install php-pgsql
|
||||||
|
# oder passend zur Version: sudo apt install php8.5-pgsql
|
||||||
|
```
|
||||||
|
|
||||||
|
**Datenbank-Shell (zum Lernen / Inspizieren):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it flixcooks-postgres-dev psql -U flixcooks -d flixcooks_dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Nützliche SQL-Befehle in `psql`:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
\dt -- alle Tabellen
|
||||||
|
\d recipes -- Spalten der Tabelle recipes
|
||||||
|
SELECT slug, created_at FROM recipes;
|
||||||
|
SELECT slug, data->>'title' AS title FROM recipes, jsonb_to_record(data) AS x(title text); -- optional
|
||||||
|
\q -- beenden
|
||||||
|
```
|
||||||
|
|
||||||
|
**DB komplett leeren und neu seeden** (lädt wieder aus `data/recipes.json` beim nächsten Seitenaufruf):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose -f docker-compose.dev.yml down -v
|
||||||
|
docker compose -f docker-compose.dev.yml up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Details zum Schema und Ablauf: Abschnitt unten in dieser README und `helpers.php` → `init_db()`.
|
||||||
|
|
||||||
|
### 3. Start the Development Server
|
||||||
|
|
||||||
#### Option A: PHP Built-in Web Server (Recommended & Easiest)
|
#### Option A: PHP Built-in Web Server (Recommended & Easiest)
|
||||||
You do not need to install complex local servers like Apache or Nginx. Simply run the following command in the root folder of the project:
|
You do not need to install complex local servers like Apache or Nginx. Simply run the following command in the root folder of the project:
|
||||||
@@ -78,7 +120,7 @@ Then, open your browser and navigate to:
|
|||||||
http://localhost:8000
|
http://localhost:8000
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Option B: Local Apache Environments (XAMPP / MAMP / WAMP)
|
#### Option B: Local Apache (XAMPP / MAMP / WAMP)
|
||||||
If you prefer running a full local stack:
|
If you prefer running a full local stack:
|
||||||
1. Move or link the project directory inside your local server's document root (e.g., `htdocs` or `www`).
|
1. Move or link the project directory inside your local server's document root (e.g., `htdocs` or `www`).
|
||||||
2. Ensure URL rewriting is enabled (the included `.htaccess` file handles caching and custom redirections).
|
2. Ensure URL rewriting is enabled (the included `.htaccess` file handles caching and custom redirections).
|
||||||
@@ -86,6 +128,32 @@ If you prefer running a full local stack:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## 🗄️ Postgres in diesem Projekt (Kurzüberblick)
|
||||||
|
|
||||||
|
FlixCooks nutzt **eine Tabelle** – kein klassisches „eine Spalte pro Rezeptfeld“-Schema:
|
||||||
|
|
||||||
|
| Spalte | Typ | Bedeutung |
|
||||||
|
|-------------|------------|-----------|
|
||||||
|
| `slug` | `VARCHAR` | Eindeutige ID des Rezepts (URL: `/recipe.php?slug=...`) |
|
||||||
|
| `data` | `JSONB` | **Gesamtes** Rezept als JSON (Titel, Zutaten, Schritte, i18n, …) |
|
||||||
|
| `created_at`| `TIMESTAMP`| Erstellzeit |
|
||||||
|
| `updated_at`| `TIMESTAMP`| Letzte Änderung (wird beim Update gesetzt) |
|
||||||
|
|
||||||
|
**Warum JSONB?** Das Rezept ist in PHP/JSON ohnehin ein Objekt. Statt 20+ SQL-Spalten zu pflegen, speichert ihr ein Dokument pro Zeile. PostgreSQL kann in `JSONB` trotzdem indexieren und abfragen (`data->>'title'`), wenn ihr später filtern wollt.
|
||||||
|
|
||||||
|
**Ablauf beim ersten Aufruf mit leerer DB:**
|
||||||
|
|
||||||
|
1. `config.php` liest `DATABASE_URL` → PDO-Verbindung.
|
||||||
|
2. `init_db()` in `helpers.php` erstellt `recipes`, falls nicht vorhanden.
|
||||||
|
3. Ist die Tabelle leer → Import aus `data/recipes.json`.
|
||||||
|
4. `load_recipes()` liest alle Zeilen, dekodiert `data` zurück zu PHP-Arrays.
|
||||||
|
|
||||||
|
**Admin speichern:** `save_recipes()` schreibt nach Postgres **und** aktualisiert `data/recipes.json` als Backup.
|
||||||
|
|
||||||
|
Für **Staging/Production** setzt du `DATABASE_URL` in der jeweiligen Hosting-Umgebung – nie Production-Daten in der lokalen Dev-DB mischen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 📈 Development Tracking & Progress
|
## 📈 Development Tracking & Progress
|
||||||
All current development tasks, features, and roadmaps are actively tracked and updated in the project’s [.agents/TODO.md](file:///.agents/TODO.md) file.
|
All current development tasks, features, and roadmaps are actively tracked and updated in the project’s [.agents/TODO.md](file:///.agents/TODO.md) file.
|
||||||
Architectural learnings, conventions, and configuration updates are maintained in the central knowledge base: [.agents/brain.md](file:///.agents/brain.md).
|
Architectural learnings, conventions, and configuration updates are maintained in the central knowledge base: [.agents/brain.md](file:///.agents/brain.md).
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
# Lokale Postgres-Instanz für Entwicklung (dev branch).
|
||||||
|
# Start: docker compose -f docker-compose.dev.yml up -d
|
||||||
|
# Stop: docker compose -f docker-compose.dev.yml down
|
||||||
|
# Reset: docker compose -f docker-compose.dev.yml down -v (löscht alle Daten!)
|
||||||
|
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: flixcooks-postgres-dev
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "5432:5432"
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: flixcooks
|
||||||
|
POSTGRES_PASSWORD: flixcooks_dev
|
||||||
|
POSTGRES_DB: flixcooks_dev
|
||||||
|
volumes:
|
||||||
|
- flixcooks_pg_dev:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U flixcooks -d flixcooks_dev"]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
flixcooks_pg_dev:
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Kurzer Verbindungstest zur lokalen Postgres-Instanz.
|
||||||
|
* Aufruf (im Projektroot):
|
||||||
|
* php scripts/db-check.php
|
||||||
|
*/
|
||||||
|
require_once dirname(__DIR__) . '/config.php';
|
||||||
|
require_once dirname(__DIR__) . '/helpers.php';
|
||||||
|
|
||||||
|
if (!extension_loaded('pdo_pgsql')) {
|
||||||
|
fwrite(STDERR, "PHP-Extension pdo_pgsql fehlt. z. B.: sudo apt install php-pgsql\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$url = getenv('DATABASE_URL');
|
||||||
|
if (!$url) {
|
||||||
|
fwrite(STDERR, "DATABASE_URL ist nicht gesetzt. In .env eintragen (siehe .env.example).\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdo = get_db_connection();
|
||||||
|
if (!$pdo) {
|
||||||
|
fwrite(STDERR, "Keine DB-Verbindung zu: {$url}\n");
|
||||||
|
fwrite(STDERR, "Prüfe: Docker läuft? docker compose -f docker-compose.dev.yml ps\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_db();
|
||||||
|
|
||||||
|
$count = (int) $pdo->query('SELECT COUNT(*) FROM recipes')->fetchColumn();
|
||||||
|
echo "Verbindung OK. Rezepte in DB: {$count}\n";
|
||||||
|
|
||||||
|
if ($count > 0) {
|
||||||
|
$stmt = $pdo->query("SELECT slug, data->'i18n'->'en'->>'title' AS title FROM recipes LIMIT 5");
|
||||||
|
echo "\nBeispiel-Zeilen:\n";
|
||||||
|
while ($row = $stmt->fetch()) {
|
||||||
|
echo " - {$row['slug']}: {$row['title']}\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user