---
name: Coolify React CMS Stack
overview: "Empfohlener Standard-Stack: Next.js (React) + Payload CMS (self-hosted) + PostgreSQL, alles als Docker-Images über GitHub → Coolify. Cursor/MCP für die Entwicklung, GitHub Actions für Qualitätssicherung vor dem Deploy."
todos:
  - id: scaffold-monorepo
    content: "Greenfield-Monorepo anlegen: apps/web (Next standalone), apps/cms (Payload), packages/shared-types"
    status: pending
  - id: docker-coolify
    content: "Dockerfiles, docker-compose.yml, docs/COOLIFY.md (3 Services: Postgres, CMS, Web) nach FlixCooks-Muster"
    status: pending
  - id: cms-content-model
    content: Payload Collections + Webhooks für On-Demand Revalidation; Env-Beispiele in .env.example
    status: pending
  - id: github-ci
    content: "GitHub Actions: lint, typecheck, build, docker build smoke; branch protection auf main"
    status: pending
  - id: mcp-agents
    content: .cursor/mcp.json + .agents/brain.md mit Stack-, Env- und Deploy-Regeln für KI
    status: pending
  - id: animation-baseline
    content: "GSAP/Lenis/Framer-Baseline-Komponenten und Regel: Overlays stoppen Lenis"
    status: pending
isProject: false
---

# Tech-Stack & Workflow: React-Sites, CMS, Docker, Coolify

## Empfehlung (Default)

Du bist unsicher bei CMS und Frontend – hier ist ein **bewährtes Default**, das zu deinen Vorgaben passt (React, Animationen, Docker, Coolify, KI/MCP, CI):

| Schicht | Technologie | Warum |
|---------|-------------|--------|
| **Frontend** | [Next.js 15](https://nextjs.org) (App Router, TypeScript) | SEO/SSR/ISR, React-Ökosystem, `output: 'standalone'` für ein schlankes Production-Docker-Image |
| **Animationen** | GSAP (+ ScrollTrigger), Framer Motion, Lenis | GSAP für Scroll/Timeline-Premium-Feel; Framer für UI-Micro-Interactions; Lenis kennst du bereits aus FlixCooks |
| **CMS** | [Payload CMS 3](https://payloadcms.com) (eigener Container) | TypeScript, Postgres-native, Admin-UI out of the box, Docker-freundlich, passt zu Coolify wie dein aktuelles Postgres-Setup |
| **Datenbank** | PostgreSQL 16 (Coolify Database Service) | Eine Instanz, getrennte DBs/User für CMS vs. App optional |
| **Runtime / Deploy** | Docker + [Coolify](https://coolify.io) | Git-Webhook → Build → Traefik/HTTPS; du hast das Muster schon in [docs/COOLIFY.md](docs/COOLIFY.md) |
| **Lokale Dev** | `docker compose` (Web + CMS + Postgres) | Parität zu Production, wie [docker-compose.yml](docker-compose.yml) bei FlixCooks |
| **KI-Entwicklung** | Cursor + MCP-Server | Repo-Kontext, GitHub, Docs, optional DB |
| **CI** | GitHub Actions | Lint, Types, Build, Docker-Smoke, optional E2E; PR-Review wie [.github/workflows/gemini-pr-review.yml](.github/workflows/gemini-pr-review.yml) |

**Alternative Frontend:** Vite + React SPA + nginx-Image – maximal frei für reine Animation-Landingpages, aber schlechteres SEO und kein ISR ohne Extra-Aufwand. **Alternative CMS (weniger Ops):** Sanity/Contentful (Cloud) – nur Frontend-Container auf Coolify. **Alternative CMS (kein Backend):** Tina/Decap + Markdown im Repo – gut für Blogs, schwächer für Redakteur:innen ohne Git.

---

## Zielarchitektur auf Coolify

```mermaid
flowchart TB
  subgraph dev [Entwicklung]
    Cursor[Cursor + MCP]
    LocalCompose[docker compose]
    Cursor --> LocalCompose
  end

  subgraph github [GitHub]
    Repo[Monorepo]
    GHA[GitHub Actions CI]
    Repo --> GHA
  end

  subgraph coolify [Coolify Server]
    PG[(PostgreSQL)]
    CMS[Payload CMS Container]
    WEB[Next.js Container]
    Traefik[Traefik HTTPS]
    PG --> CMS
    CMS -->|REST/GraphQL| WEB
    Traefik --> WEB
    Traefik --> CMS
  end

  dev -->|push main| Repo
  GHA -->|grüner Build| Repo
  Repo -->|Webhook Deploy| coolify
```

**Drei Coolify-Ressourcen** (analog zu deinem FlixCooks-Setup: Postgres + App):

1. **PostgreSQL** – internal URL, nicht öffentlich
2. **CMS-App** – Dockerfile aus `apps/cms`, Port z. B. 3001, Env: `DATABASE_URL`, `PAYLOAD_SECRET`
3. **Web-App** – Dockerfile aus `apps/web`, Port 3000, Env: `CMS_URL` (internal), `REVALIDATE_SECRET` für On-Demand-ISR

Persistenz: Postgres-Volume (Inhalte), optional Volume für CMS-Uploads (`/app/media`).

---

## Repository-Struktur (Greenfield-Vorlage)

Ein Repo pro „Site-Familie“ oder Monorepo für mehrere Marken:

```
my-site/
├── apps/
│   ├── web/                 # Next.js
│   │   ├── Dockerfile
│   │   ├── src/
│   │   └── next.config.ts   # output: 'standalone'
│   └── cms/                 # Payload
│       ├── Dockerfile
│       └── payload.config.ts
├── packages/
│   └── shared-types/        # optional: gemeinsame TS-Typen CMS ↔ Web
├── docker-compose.yml         # lokaler Prod-Parität-Stack
├── docker-compose.dev.yml     # nur Postgres (wie bei FlixCooks)
├── .github/workflows/
│   ├── ci.yml
│   └── gemini-pr-review.yml   # optional, aus FlixCooks übernehmen
├── .cursor/
│   └── mcp.json               # MCP-Server für das Team
├── .agents/
│   ├── brain.md               # Architektur für KI (Pattern aus FlixCooks)
│   └── rules/AGENT.md
└── docs/
    └── COOLIFY.md
```

---

## Frontend-Stack (React + Animationen)

**Kern:**

- **Next.js App Router** – Seiten in `app/`, Server Components für CMS-Daten, Client Components nur für Animation/Interaktion
- **TypeScript** – strikt; Typen aus Payload generieren (`payload generate:types`)
- **Styling** – CSS Modules oder Tailwind (nur wenn du es willst; FlixCooks bleibt bei Vanilla CSS – für neue React-Sites ist Tailwind optional, nicht Pflicht)

**Animation-Toolkit:**

| Tool | Einsatz |
|------|---------|
| **GSAP + ScrollTrigger** | Hero-Sequences, pinned Sections, komplexe Timelines |
| **Framer Motion** | Hover, Page-Transitions, modale UI |
| **Lenis** | Smooth Scroll (wie FlixCooks: bei Overlays `lenis.stop()`) |
| **(optional) @react-three/fiber** | 3D-Hero nur wenn nötig |

**CMS-Anbindung im Web:**

- **Build-Zeit (SSG):** `generateStaticParams` + Fetch von Payload REST für Marketing-Seiten
- **On-Demand Revalidation:** Payload-Webhook → `POST /api/revalidate?secret=...` in Next.js (Inhalt ändert sich ohne Full-Redeploy)
- **Preview:** Draft-Modus mit Payload Preview-URL + Next `draftMode()`

Env im Web-Container (Coolify):

- `CMS_URL=http://payload-service:3001` (internal hostname)
- `REVALIDATE_SECRET`, `NEXT_PUBLIC_SITE_URL`

---

## CMS-Stack (Payload auf Coolify)

**Warum Payload als Default:** Self-hosted, eine Postgres-URL, Admin unter `/admin`, Collections/Blocks für Seitenmodule, Media-Uploads, Webhooks – alles containerisierbar.

**Coolify Env (CMS):**

- `DATABASE_URL` – internal Postgres URL (gleiches Muster wie [docs/COOLIFY.md](docs/COOLIFY.md) Zeilen 33–43)
- `PAYLOAD_SECRET` – langer Zufallswert (nur Secrets, nie ins Repo)
- `NEXT_PUBLIC_SERVER_URL` – öffentliche CMS-URL (für Admin-Assets)

**Erstes Deployment:** analog FlixCooks `RUN_DB_SEED` – einmalig Migration/Seed, danach Flag entfernen.

**Sicherheit:** CMS-Admin nur über HTTPS; CORS auf Web-Domain beschränken; API-Keys für Preview/Revalidate nur als Secrets.

---

## Docker-Images

### Web (`apps/web/Dockerfile`) – Next standalone

Mehrstufig: `node:22-alpine` → `npm ci` → `npm run build` → Runtime nur `.next/standalone` + `static` + `public`.

- `EXPOSE 3000`
- `HEALTHCHECK` auf `/api/health` (kleine Route: `{ "status": "ok" }`)
- Coolify: Port **3000**, Health Path `/api/health`

### CMS (`apps/cms/Dockerfile`)

Payload-Official-Pattern oder Node-Image mit `npm run build && npm run start`.

- `HEALTHCHECK` auf CMS-Health-Endpoint
- Volume für `/app/media` (Uploads überleben Redeploy)

### Lokales Parität-Compose

Orientierung an deinem bestehenden [docker-compose.yml](docker-compose.yml):

- `postgres` mit `healthcheck`
- `cms` `depends_on: postgres: service_healthy`
- `web` `depends_on: cms` + `DATABASE_URL` nur wenn Web eigene DB braucht (meist nicht – nur CMS nutzt DB)

Entrypoint-Pattern von [docker/entrypoint.sh](docker/entrypoint.sh) übernehmen: **DB warten → Migration → dann Prozess starten**.

---

## Coolify-Workflow (End-to-End)

```mermaid
sequenceDiagram
  participant Dev as Developer
  participant GH as GitHub
  participant GHA as GitHub Actions
  participant CF as Coolify
  participant Web as Next Container
  participant CMS as Payload Container

  Dev->>GH: push feature branch
  Dev->>GH: open PR
  GHA->>GHA: lint typecheck build docker
  GHA-->>Dev: PR checks green
  Dev->>GH: merge to main
  GH->>CF: webhook deploy
  CF->>CF: build CMS image
  CF->>CF: build Web image
  CF->>Web: rolling update
  CMS->>Web: optional revalidate webhook
```

**Coolify-Konfiguration pro App:**

| Setting | Web | CMS |
|---------|-----|-----|
| Build Pack | Dockerfile | Dockerfile |
| Branch | `main` | `main` |
| Port | 3000 | 3001 |
| Health | `/api/health` | `/api/health` oder Payload-Default |
| Secrets | `REVALIDATE_SECRET`, `CMS_URL` | `DATABASE_URL`, `PAYLOAD_SECRET` |

**Checkliste Erstdeploy** (aus [docs/COOLIFY.md](docs/COOLIFY.md) übertragbar):

1. Postgres healthy, internal URL notieren  
2. CMS deployen, Admin anlegen, Collections seeden  
3. Web deployen mit internal `CMS_URL`  
4. Domain + HTTPS (Traefik)  
5. Webhook Payload → Next Revalidate testen  
6. `RUN_DB_SEED` / Migration-Flags wieder aus  

---

## GitHub Actions (CI vor Coolify)

**Workflow `ci.yml`** (bei jedem PR + push auf `main`):

1. **checkout**
2. **Node 22** + Cache (`apps/web`, `apps/cms`)
3. **Parallel jobs oder Matrix:**
   - `npm run lint` (ESLint)
   - `npm run typecheck` (`tsc --noEmit`)
   - `npm run build` (Web + CMS)
4. **Docker build test** (ohne Push):
   - `docker build -f apps/web/Dockerfile apps/web`
   - `docker build -f apps/cms/Dockerfile apps/cms`
5. **(optional) Playwright** gegen `docker compose up` – Smoke: Startseite, eine CMS-Seite, Health endpoints
6. **(optional) PR Review** – bestehendes Gemini-Workflow aus FlixCooks wiederverwenden

**Branch-Schutz:** `main` nur mit grünen Required Checks mergebar.

Coolify deployt **nach** Merge – CI blockiert kaputte Images, Coolify baut das echte Production-Image (oder du pushst zu GHCR – für den Start reicht Coolify-eigener Build).

---

## KI-gestützte Entwicklung mit MCP

**Cursor `mcp.json` (Team-Standard):**

| MCP | Zweck |
|-----|--------|
| **GitHub** | Issues, PRs, Actions-Logs aus dem Chat |
| **Context7** (oder Fetch) | Aktuelle Next.js / Payload / GSAP-Docs |
| **Postgres** (optional, nur Dev) | Content/Debugging – nie Production-Credentials im Repo |
| **Filesystem** | Standard in Cursor |

**Projekt-Wissen für Agenten** (aus FlixCooks übernehmen):

- [.agents/brain.md](.agents/brain.md) – Architektur, Env-Regeln, Coolify-Hosts  
- [.agents/rules/AGENT.md](.agents/rules/AGENT.md) – Commit/PR/TODO-Konventionen  
- `docs/COOLIFY.md` – Deploy-Runbook pro Projekt  

**Typischer KI-Workflow:**

1. Ticket/Issue in GitHub (MCP)  
2. Feature-Branch; Agent ändert `apps/web` + Payload-Collection  
3. `docker compose up` lokal; Agent nutzt Health-URLs  
4. PR → CI grün → Gemini-Review optional  
5. Merge → Coolify  

---

## Entwickler-Alltag (Kurzablauf)

1. `cp .env.example .env` – lokale URLs  
2. `docker compose -f docker-compose.dev.yml up -d` (nur Postgres) **oder** volles `docker compose up`  
3. `npm run dev` in `apps/web` und `apps/cms` (schneller Hot Reload) **oder** alles in Containern  
4. In Payload Inhalte pflegen → Webhook triggert Revalidate  
5. `git push` → PR → CI → merge → Coolify rebuild  

---

## Bezug zu FlixCooks (dieses Repo)

FlixCooks ist heute **Vanilla PHP + Postgres + eingebautes `admin.php`-CMS** – kein React. Das ist ein **paralleler Stack**, kein Widerspruch:

| Aspekt | FlixCooks (aktuell) | Neuer React-Stack |
|--------|---------------------|-------------------|
| Frontend | PHP-Templates | Next.js + React |
| CMS | `admin.php` | Payload (Container) |
| DB | Postgres | Postgres |
| Deploy | [Dockerfile](Dockerfile) + [COOLIFY.md](docs/COOLIFY.md) | gleiches Muster, zwei App-Services |
| Animationen | Lenis, Vanilla CSS | Lenis + GSAP + Framer |

Du kannst FlixCooks auf Coolify weiterbetreiben und **neue Projekte** im Monorepo-Template starten. Eine spätere Migration FlixCooks → Next wäre ein separates Projekt (Content-Export aus Postgres/JSON → Payload-Collections).

---

## Nächste konkrete Schritte (nach Plan-Freigabe)

1. **Greenfield-Repo** aus der Struktur oben scaffolden (oder `create-payload-app` + Next in Monorepo).  
2. **Minimale Collections** in Payload: `pages`, `recipes` (oder `projects`), `siteSettings`, Media.  
3. **Dockerfiles + compose** + `docs/COOLIFY.md` vom FlixCooks-Muster kopieren/adaptieren.  
4. **GitHub Actions `ci.yml`** anlegen.  
5. **Coolify:** Postgres → CMS → Web → Webhook Revalidate testen.  
6. **`.cursor/mcp.json` + `.agents/brain.md`** für das neue Repo.

Wenn du willst, kann im nächsten Schritt ein **konkretes Starter-Repo** (Dateien + minimale Hero-Animation + eine Payload-Collection) direkt in einem neuen Ordner oder Branch angelegt werden.
