7.8 KiB
7.8 KiB
FlixCooks Project Brain
This document summarizes architectural knowledge, conventions, and learnings for humans and AI agents working on this repo.
1. Project Architecture & Stack
- Backend: Vanilla PHP. No heavy frameworks.
- Database: PostgreSQL (optional) via
DATABASE_URLin.env, with automatic seed from and backup todata/recipes.json. All data access lives inhelpers.php; connection logic inconfig.php. - Site settings (legal pages): Flat-file
data/site.jsonviaload_site_settings()/save_site_settings()— not in Postgres. - 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 inpartials/head.phpfor auth, Firestore (newsletter/bookmarks where used). - Config:
config.phploads.env, exposesget_firebase_config(),get_db_connection(). Never commit.env(see.gitignore).
2. Design & Aesthetics
- CSS: Custom properties (
var(--ease-out-expo),var(--surface-1)), glassmorphism,FloemaLayoutGrid. - Lenis: Call
lenis.stop()when opening fullscreen overlays (e.g. Cooking Mode);lenis.start()on close. - Preloader:
CapitoliumPreloaderon homepage; once per session viasessionStorage('flixcooks_preloader_seen').
3. Antigravity Agent Configuration
- Workspace Rules:
.agents/rules/withalways_on: trueandglob: "*"in frontmatter. - Custom Skills:
.agents/skills/(e.g.close_feature.jsonfor Git merge workflow).
4. GitHub Actions & CI/CD
- Gemini PR review:
petarzarkov/gemini-code-review-action; secrets viaenv:notwith:; pin action versions; use full model names (e.g.gemini-2.0-flash-lite).
5. PostgreSQL — Schema & Data Flow
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
get_db_connection()inconfig.phpparsesDATABASE_URL→ PDOpgsql:DSN.- If no URL or connection fails →
load_recipes_local()readsdata/recipes.jsononly. - If connected →
init_db()once per request (static flag):CREATE TABLE IF NOT EXISTS, then ifCOUNT(*) = 0→ seed all rows fromdata/recipes.json. load_recipes()/load_recipe_by_slug()decodedataJSONB to PHP arrays.save_recipes()(admin): upsert all recipes in Postgres and writedata/recipes.jsonas backup.
config.php functions
load_env()— parses.envintogetenv()/$_ENV/$_SERVER.get_firebase_config()— returns Firebase web config array fromFIREBASE_*env vars. Required bypartials/head.phpandadmin.php. Was accidentally removed in postgres commite7f35d7; restored (undefined function caused HTTP 500).get_db_connection()— returnsPDOornull; logs failures, does not throw.
6. Local Development — Docker Postgres
Files
docker-compose.dev.yml— Postgres 16 Alpine, containerflixcooks-postgres-dev, port5432..env.example— template including localDATABASE_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
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(orphp8.5-pgsql) required; without it: logcould 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→ expectpdo_pgsql,pgsql.
App server
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.1Docker URL above. - Railway production:
postgres.railway.internalonly 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 clientfirebase.initializeApp()in browser. - Omit
DATABASE_URLentirely 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
.envat production Postgres. - Export/import between envs:
pg_dump/psqlwhen 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,faton recipes; admin + UI. - Phase 4 (Cooking Mode):
step_videos,step_timers; fullscreen overlay. - Phase 6 (Postgres):
recipesJSONB table; seed from JSON; admin dual-write. - Local dev Postgres:
docker-compose.dev.yml, README section,scripts/db-check.php,.env.examplewithDATABASE_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 usemailto: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() |