325 lines
13 KiB
Markdown
325 lines
13 KiB
Markdown
---
|
||||
|
|
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.
|