Files
flixcooks-website/.agents/brain.md
T

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_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.
  • Site settings (legal pages): Flat-file data/site.json via load_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 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

  • 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: CapitoliumPreloader on homepage; once per session via sessionStorage('flixcooks_preloader_seen').

3. Antigravity Agent Configuration

  • Workspace Rules: .agents/rules/ with always_on: true and glob: "*" in frontmatter.
  • Custom Skills: .agents/skills/ (e.g. close_feature.json for Git merge workflow).

4. GitHub Actions & CI/CD

  • 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).

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

  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

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

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()