Enhance project documentation with updated architecture, PostgreSQL integration, and local development setup. Refine admin panel and GitHub Actions details. Remove Firebase configuration from .env.example and clarify database fallback mechanisms.
This commit is contained in:
+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