Files
code-vorlage/README.md
T

585 lines
23 KiB
Markdown

# AI Coding Starter Kit
Next.js-Vorlage mit einem durchgängigen KI-Workflow für [Claude Code](https://docs.anthropic.com/en/docs/claude-code).
Neun Skills führen von der Idee bis zum laufenden Deployment. Jede Phase schreibt ihr
Ergebnis in die Feature-Spec — der Projektstand liegt in Dateien, nicht im Chatverlauf.
Genau das macht die Vorlage fürs Vibe-Coden brauchbar: Du musst dich nicht erinnern,
wo du stehst. `/help` liest es aus den Dateien ab, und nach einem Kontextverlust
liest sich jede Skill selbst wieder ein.
---
## Inhalt
- [Schnellstart](#schnellstart)
- [Der Workflow im Überblick](#der-workflow-im-überblick)
- [Die neun Skills](#die-neun-skills)
- [Die drei Sub-Agents](#die-drei-sub-agents)
- [Die vier Rules](#die-vier-rules)
- [Kontext-Ebenen](#kontext-ebenen)
- [Das Feature-System](#das-feature-system)
- [Tech-Stack](#tech-stack)
- [Authentifizierung: Passkeys](#authentifizierung-passkeys)
- [Tests](#tests)
- [Deployment](#deployment)
- [Kommandos](#kommandos)
- [Dateibaum](#dateibaum)
- [Stolperfallen](#stolperfallen)
- [Anpassen](#anpassen)
---
## Schnellstart
```bash
git clone <repo-url> mein-projekt
cd mein-projekt
npm install
cp .env.example .env
npx playwright install chromium # einmalig pro Rechner, für E2E-Tests
npm run dev
```
Dann in Claude Code:
```
/init Ich will eine Aufgabenverwaltung für kleine Teams bauen
```
---
## Der Workflow im Überblick
```mermaid
flowchart LR
subgraph P["Planung — inline mit dir im Gespräch"]
direction LR
INIT["/init<br/><i>PRD + Feature-Map</i>"]
SPEC["/write-spec<br/><i>User Stories, AC</i>"]
ARCH["/architecture<br/><i>Tech Design</i>"]
end
subgraph B["Bauen — delegiert an Sub-Agents"]
direction LR
FE["/frontend<br/><i>UI</i>"]
BE["/backend<br/><i>API + Daten</i>"]
QA["/qa<br/><i>Tests + Audit</i>"]
end
DEP["/deploy<br/><i>Docker-Stack</i>"]
INIT --> SPEC --> ARCH --> FE
FE -->|"braucht Server"| BE --> QA
FE -->|"nur Frontend"| QA
QA -->|"keine Critical/High"| DEP
QA -.->|"Bugs gefunden"| FE
QA -.->|"Bugs gefunden"| BE
REF["/refine PROJ-X"] -.->|"Spec überarbeiten"| SPEC
HELP["/help"] -.->|"Wo stehe ich?"| P
```
Übergaben sind **immer** von dir ausgelöst. Keine Skill springt selbstständig weiter,
jede endet mit einem Freigabe-Checkpoint.
### Das Grill-Me-Prinzip
`/init`, `/write-spec` und `/refine` interviewen nach denselben Regeln:
- Eine Frage pro Runde, niemals eine Liste
- Immer mit einer Empfehlung — du bestätigst oder korrigierst
- Dem Gespräch folgen statt einem Skript
- Erst im Code nachsehen, dann fragen
- Kein Fragenlimit: Schluss ist, wenn es verstanden ist
---
## Die neun Skills
| # | Skill | Argument | Liest | Schreibt | Ausführung |
|---|-------|----------|-------|----------|------------|
| 1 | **`/init`** | Beschreibung der Idee | PRD, INDEX | `docs/PRD.md`, `features/INDEX.md`, ggf. `docs/design-system.md` | inline |
| 2 | **`/write-spec`** | Feature-Name oder `PROJ-X` | PRD, INDEX, Code | `features/PROJ-X-name.md`, INDEX, PRD | inline |
| 3 | **`/refine`** | `PROJ-X` | Spec, INDEX, PRD | Spec, INDEX, PRD | inline |
| 4 | **`/architecture`** | `PROJ-X` | Spec, PRD, Code | Tech Design + Entscheidungslog in der Spec | inline |
| 5 | **`/frontend`** | `PROJ-X` | Spec, `components/ui/`, Design-System | Komponenten, Seiten, Spec-Notizen | → Sub-Agent |
| 6 | **`/backend`** | `PROJ-X` | Spec, `app/api/`, `lib/` | Route Handler, Schema, Tests, `.env.example` | → Sub-Agent |
| 7 | **`/qa`** | `PROJ-X` | Spec, INDEX, Git-Log | QA-Abschnitt in der Spec, Unit- und E2E-Tests | → Sub-Agent |
| 8 | **`/deploy`** | `PROJ-X` | Spec (QA-Teil), INDEX | Deployment-Abschnitt, Git-Tag | inline |
| 9 | **`/help`** | optionale Frage | PRD, INDEX, Specs, Code | nichts | inline |
### Was jede Skill konkret tut
<table>
<tr><td width="140"><b><code>/init</code></b></td><td>
Einmalig pro Projekt. Interviewt dich zu Problem, Zielgruppe, MVP-Umfang, Alternativen,
Rahmenbedingungen, Erfolgsmetriken und Nicht-Zielen. Klärt <b>verbindlich</b> drei Dinge,
bevor die Feature-Map entsteht: Braucht es dauerhafte Speicherung? Braucht es Nutzerkonten
(dann wird „Auth-Grundlage" automatisch PROJ-1)? Gibt es ein Design-System? Legt danach
PRD und priorisierte Feature-Map an — aber <i>keine</i> Spec-Dateien.
</td></tr>
<tr><td><b><code>/write-spec</code></b></td><td>
Macht aus einer Feature-Idee eine testbare Spec. Drei Einstiege: Feature steht schon als
„Roadmap" im INDEX, Feature fehlt dort noch (wird ergänzt), oder es hat bereits eine Spec
(verweist auf <code>/refine</code>). Füllt neben User Stories und Acceptance Criteria auch
Out of Scope, Produkt-Entscheidungen und Offene Fragen.
</td></tr>
<tr><td><b><code>/refine</code></b></td><td>
Öffnet eine bestehende Spec. Fragt zuerst „Was bringt dich zurück zu dieser Spec?" und
wählt danach den Pfad: <b>1)</b> Scope hat sich geändert, <b>2)</b> die Umsetzung hat eine
Lücke aufgedeckt, <b>3)</b> das Feature gehört grundsätzlich hinterfragt — bis hin zum
Aufsplitten in zwei Specs. Schließt erledigte Offene Fragen mit Datum.
</td></tr>
<tr><td><b><code>/architecture</code></b></td><td>
Übersetzt die Spec in ein Design, das auch ohne Technikhintergrund lesbar ist:
Komponentenbaum, Datenmodell in Worten, begründete Tech-Entscheidungen, Paketliste.
<b>Schreibt bewusst keinen Code</b> — kein SQL, kein TypeScript. Trifft hier die
Datenbank-Entscheidung, die die Vorlage offenlässt.
</td></tr>
<tr><td><b><code>/frontend</code></b></td><td>
Klärt Designfragen mit dir (oder liest <code>docs/design-system.md</code>), setzt den Status
auf „In Progress" und übergibt an den Frontend-Sub-Agent. Präsentiert dessen Bericht,
holt dein Urteil im Browser ein und iteriert im selben Sub-Agent-Kontext weiter.
</td></tr>
<tr><td><b><code>/backend</code></b></td><td>
Klärt Rechte, Nebenläufigkeit, Validierung und Rate-Limiting, dann Übergabe an den
Backend-Sub-Agent. Stoppt, wenn im Tech Design noch kein Daten-Layer steht — die
Entscheidung gehört zu <code>/architecture</code>, nicht hierher.
</td></tr>
<tr><td><b><code>/qa</code></b></td><td>
Setzt „In Review", übergibt an den QA-Sub-Agent, schreibt dessen Ergebnis als
QA-Abschnitt in die Spec und priorisiert die Bugs mit dir. Setzt bei sauberem Lauf
„Approved", sonst bleibt „In Review".
</td></tr>
<tr><td><b><code>/deploy</code></b></td><td>
Blockiert ohne QA-Abschnitt oder bei offenen Critical/High-Bugs. Fährt Lint, Typecheck,
Test und Build als Pre-Flight, führt beim ersten Mal durch die Servereinrichtung und
danach durch <code>./scripts/update.sh</code>. Setzt Status, Tag und Deployment-Notiz.
</td></tr>
<tr><td><b><code>/help</code></b></td><td>
Liest PRD, INDEX und Spec-Abschnitte und sagt dir, wo das Projekt steht und was als
Nächstes dran ist — mit dem exakten Kommando. Widersprechen sich Dateien und
Status-Spalte, gewinnen die Dateien und es sagt dir das.
</td></tr>
</table>
---
## Die drei Sub-Agents
`/frontend`, `/backend` und `/qa` führen Interview und Review mit dir im Hauptgespräch
und geben die eigentliche Dateiarbeit ab. Der Sub-Agent arbeitet in eigenem Kontext und
liefert einen kompakten Bericht zurück statt der vollen Erzählung.
```mermaid
sequenceDiagram
actor Du
participant S as Skill<br/>(Hauptgespräch)
participant A as Sub-Agent<br/>(eigener Kontext)
participant F as Dateien
Du->>S: /frontend PROJ-3
S->>F: Spec + INDEX lesen
S->>Du: Designfragen, je eine mit Empfehlung
Du-->>S: Antworten
S->>F: Status → In Progress
S->>A: Auftrag: Spec, Designentscheidungen,<br/>Komponentenliste
A->>F: Komponenten schreiben,<br/>lint / typecheck / build
A-->>S: Bericht: Dateien, Abweichungen,<br/>offene Fragen
S->>Du: Bericht + "Schau es dir an"
Du-->>S: Feedback
S->>A: Nachbesserung (gleicher Kontext)
S->>F: Spec-Notizen + Status
S->>Du: Handoff → /backend oder /qa
```
| Agent | Datei | Werkzeuge | Aufgabe | Hard Rule |
|-------|-------|-----------|---------|-----------|
| **Frontend Developer** | `.claude/agents/frontend-dev.md` | Read, Write, Edit, Bash, Glob, Grep | UI umsetzen | shadcn vor Eigenbau; Lint, Typecheck und Build müssen grün sein |
| **Backend Developer** | `.claude/agents/backend-dev.md` | Read, Write, Edit, Bash, Glob, Grep | Routen, Daten, Auth | **Stoppt und meldet zurück**, wenn der Daten-Layer noch nicht entschieden ist |
| **QA Engineer** | `.claude/agents/qa-engineer.md` | Read, Write, Edit, Bash, Glob, Grep | Testen, Security-Audit | **Behebt niemals selbst einen Bug** — nur finden, dokumentieren, priorisieren |
Keiner der drei fasst `features/INDEX.md` an. Tracking gehört der aufrufenden Skill —
so kann es keine zwei Wahrheiten über den Status geben.
---
## Die vier Rules
Rules laden sich automatisch, sobald passende Dateien bearbeitet werden. Du musst sie
nie manuell erwähnen.
| Datei | Greift bei | Inhalt |
|-------|-----------|--------|
| **`general.md`** | immer aktiv | Feature-Tracking, Status-Flow, Commit-Format, „erst lesen, dann ändern", Write-then-Verify, Human-in-the-Loop, Sprachregel |
| **`frontend.md`** | `src/components/**`<br/>`src/app/**/page.tsx`<br/>`src/app/**/layout.tsx`<br/>`src/hooks/**` | shadcn-Pflicht, Tailwind-v4-Eigenheiten, semantische Tokens, Server Components, Loading/Error/Empty, Formulare |
| **`backend.md`** | `src/app/api/**`<br/>`src/lib/**`<br/>`src/server/**`<br/>`drizzle/**`, `prisma/**` | Kein vorgewählter Daten-Layer, Zod-Validierung, Statuscodes, Ownership im Query statt danach, Indizes, Migrationen, Secrets |
| **`security.md`** | API-Routen, `src/lib/auth*`<br/>`.env*`, `next.config.*`<br/>`Dockerfile`, `compose.yaml` | Passkey-Standard, Autorisierung pro Ressource, Secrets, Security-Header, genehmigungspflichtige Änderungen |
---
## Kontext-Ebenen
Nicht alles wird gleichzeitig geladen — das ist der Grund, warum lange Sessions nicht
zerfasern.
```mermaid
flowchart TB
subgraph AUTO["Automatisch"]
CM["<b>CLAUDE.md</b><br/>jede Session"]
RU["<b>.claude/rules/</b><br/>sobald passende Dateien<br/>bearbeitet werden"]
end
subgraph DEMAND["Auf Abruf"]
SK["<b>.claude/skills/</b><br/>beim /kommando"]
AG["<b>.claude/agents/</b><br/>wenn eine Skill delegiert"]
SP["<b>features/PROJ-X.md</b><br/>wenn die Skill sie liest"]
DOC["<b>docs/DEPLOYMENT.md</b><br/>nur wenn referenziert"]
end
CM --> SK
RU --> SK
SK --> AG
SK --> SP
AG --> SP
```
**Zustand liegt in Dateien, nicht im Gespräch.** Wird der Kontext komprimiert, liest die
Skill Spec und `git diff` neu ein und macht weiter — ohne Arbeit zu wiederholen oder
doppelt zu bauen.
---
## Das Feature-System
Alles läuft über `features/INDEX.md` und eine Spec-Datei pro Feature
(`features/PROJ-X-name.md`). Ein Feature = eine testbare, deploybare Einheit.
```mermaid
stateDiagram-v2
[*] --> Roadmap: /init
Roadmap --> Planned: /write-spec
Planned --> Architected: /architecture
Architected --> InProgress: /frontend<br/>/backend
InProgress --> InReview: /qa startet
InReview --> Approved: keine Critical/High
InReview --> InProgress: Bugs beheben
Approved --> Deployed: /deploy
Deployed --> [*]
Planned --> Planned: /refine
Architected --> Architected: /refine
```
### Aufbau einer Spec
Eine Spec wächst über die Phasen hinweg. Vorlage:
`.claude/skills/write-spec/template.md`
| Abschnitt | Gefüllt von | Wozu |
|-----------|-------------|------|
| Abhängigkeiten | `/write-spec` | Welche PROJ-X vorher fertig sein müssen |
| User Stories | `/write-spec` | Als [Rolle] möchte ich [Aktion], um [Ziel] |
| **Out of Scope** | `/write-spec` | Was bewusst *nicht* gebaut wird — sonst baut es der nächste Durchlauf nach |
| Acceptance Criteria | `/write-spec` | Angenommen / Wenn / Dann, direkt abtestbar |
| Edge Cases | `/write-spec` | Nebenläufigkeit, Netzfehler, leere Eingabe, Rechtegrenzen |
| **Offene Fragen** | `/write-spec` | `- [ ]`, geschlossen in `/refine` mit Datum |
| **Entscheidungslog** | `/write-spec` + `/architecture` | Produkt- und Tech-Entscheidungen mit Begründung |
| Tech Design | `/architecture` | Komponentenbaum, Datenmodell, Abhängigkeiten |
| QA Test Results | `/qa` | Kriterium für Kriterium, Bugs, Security, Urteil |
| Deployment | `/deploy` | URL, Datum, Commit |
Out of Scope und Entscheidungslog sind das Gedächtnis der Vorlage.
### Format der Acceptance Criteria
```
- [ ] Angenommen der Nutzer ist angemeldet, wenn er ein leeres Formular abschickt,
dann erscheint pro Pflichtfeld eine Validierungsmeldung
```
**Sprache:** PRD, Specs und Acceptance Criteria auf Deutsch. Code, Kommentare,
Commit-Messages und die Skill-Anweisungen selbst auf Englisch.
---
## Tech-Stack
| Ebene | Wahl | Anmerkung |
|-------|------|-----------|
| Framework | Next.js 16, App Router | React 19, Server Components als Standard |
| Sprache | TypeScript `strict` | `@/*` → `src/*` |
| Styling | Tailwind CSS v4 | CSS-first, **keine `tailwind.config.ts`** |
| Komponenten | shadcn/ui, Stil `new-york` | 6 vorinstalliert, Rest per CLI |
| Icons | lucide-react | |
| Formulare | react-hook-form + Zod | Zod-Schema gilt auch serverseitig |
| Toasts | sonner | in `layout.tsx` gemountet |
| Theming | next-themes | Dark Mode über `.dark` |
| Auth | Better Auth + Passkey-Plugin | nur wenn das Projekt Anmeldung braucht |
| Daten-Layer | **pro Projekt entschieden** | Vorlage bringt keinen mit |
| Tests | Vitest + Playwright | strikt getrennte Scopes |
| Betrieb | Docker Compose, selbst gehostet | App-Container, Proxy extern |
### Bewusst nicht enthalten
- **Keine Datenbank, kein ORM.** `/architecture` entscheidet pro Projekt. Einzige
Auflage: muss im Compose-Stack selbst hostbar sein.
- **Kein Supabase, kein Vercel.** Nicht vergessen, sondern absichtlich ausgebaut.
In `CLAUDE.md` steht das explizit, damit es nicht durch die Hintertür zurückkommt.
- **Keine Content-Security-Policy vorkonfiguriert.** Geraten bricht sie Apps; pro
Projekt mit `Report-Only` anfangen.
- **Kein Error-Tracking vorinstalliert.** Sentry-Anleitung in `docs/DEPLOYMENT.md`.
### UI-Komponenten
Sechs sind vorinstalliert:
| Komponente | Wofür |
|------------|-------|
| `button` | Aktionen, Varianten über CVA |
| `card` | Container mit Header/Content/Footer |
| `input` | Textfelder |
| `label` | Beschriftungen, barrierefrei verknüpft |
| `form` | react-hook-form-Anbindung inkl. Fehlermeldungen |
| `sonner` | Toaster, bereits in `layout.tsx` gemountet |
Alles Weitere ist ein Kommando entfernt:
```bash
npx shadcn@latest add dialog table tabs --yes
```
**Tailwind v4 ist CSS-first: es gibt keine `tailwind.config.ts`.** Theme-Tokens leben
in `src/app/globals.css` unter `@theme inline`. Wer aus Gewohnheit eine Config-Datei
anlegt, wundert sich, warum nichts greift.
Nutze semantische Tokens (`bg-background`, `text-muted-foreground`) statt roher
Palettenwerte (`bg-slate-900`) — sonst bricht der Dark Mode.
---
## Authentifizierung: Passkeys
Sobald ein Projekt Anmeldung braucht, ist der Stack festgelegt: **Better Auth mit
Passkey-Plugin**. Passkey ist der primäre Weg und wird zuerst angeboten; ein
Passwort-Flow ist nur der Fallback für Geräte ohne WebAuthn.
`/init` legt dafür automatisch „Auth-Grundlage" als **PROJ-1, P0** an. Jedes Feature,
das angemeldete Nutzer braucht, hängt davon ab.
Verbindlich, sobald Auth im Spiel ist:
- Passkey-Registrierung wird bei der Anmeldung angeboten, nicht in den Einstellungen versteckt
- Bestehende Passwort-Nutzer werden nach dem Login zum Passkey eingeladen
- Passwort-Fallback ist rate-limited und verrät nie, ob ein Konto existiert
- Produktion braucht HTTPS — localhost ist die einzige Ausnahme
> **Die eine Sache, die dich sonst Stunden kostet:** Die WebAuthn-Relying-Party-ID
> wird aus dem Hostnamen in `NEXT_PUBLIC_APP_URL` abgeleitet. Stimmt der nicht exakt
> mit der ausgelieferten Domain überein, scheitern *alle* Passkeys — ohne verwertbare
> Fehlermeldung.
`/qa` prüft aktiv, dass der Passkey-Weg der primäre ist. Ein aufgeweichter oder
fehlender Passkey-Flow gilt als **High**-Befund.
---
## Tests
| Art | Ort | Kommando | Geschrieben von |
|-----|-----|----------|-----------------|
| Unit / Integration (Vitest) | neben der Quelle: `useThing.test.ts` neben `useThing.ts` | `npm test` | `/backend`, `/qa` |
| E2E (Playwright) | `tests/PROJ-X-name.spec.ts` | `npm run test:e2e` | `/qa` |
Die Läufe sind strikt getrennt: Vitest scannt ausschließlich `src/`, Playwright
ausschließlich `tests/`. Zwei Smoke-Tests liegen als Muster bei und belegen, dass die
Trennung greift.
`/qa` schreibt für jedes bestandene Acceptance Criterion einen E2E-Test — daraus wächst
die Regressions-Suite von selbst.
**Port belegt?** `E2E_PORT=3177 npm run test:e2e`. Ohne das testet Playwright
stillschweigend gegen einen fremden Server, der zufällig auf :3000 läuft.
---
## Deployment
Selbst gehostet über Docker Compose. Der Stack veröffentlicht die App auf Loopback;
ein Reverse Proxy auf dem Host terminiert TLS.
```mermaid
flowchart LR
U["Nutzer"] -->|HTTPS| P["Reverse Proxy<br/><i>nginx / Caddy</i><br/>auf dem Host"]
P -->|"127.0.0.1:3000"| C["app-Container<br/><i>Next.js standalone</i>"]
C --> H["/api/health"]
subgraph SRV["Server"]
P
subgraph CMP["docker compose"]
C
H
DB[("Datenbank<br/><i>optional, pro Projekt</i>")]
end
end
C -.->|"nur wenn gewählt"| DB
G["git repo"] -->|"./scripts/update.sh"| CMP
style DB stroke-dasharray: 5 5
```
```bash
docker compose up -d --build # Erststart
./scripts/update.sh # neuen Stand ausrollen
```
### Was `update.sh` macht
```mermaid
flowchart TD
A["Start"] --> B{"Arbeitsverzeichnis<br/>sauber?"}
B -->|nein| X["Abbruch"]
B -->|ja| C["git fetch + fast-forward"]
C --> D{"Neuer Commit<br/>oder --force?"}
D -->|nein| Y["Nichts zu tun"]
D -->|ja| E["docker compose build"]
E --> F["docker compose up -d"]
F --> G{"Healthcheck<br/>innerhalb 120s?"}
G -->|ja| H["Alte Images aufräumen<br/>✓ Deployed"]
G -->|nein| I["Letzte 50 Logzeilen ausgeben"]
I --> J["git reset auf Vorgänger-Commit"]
J --> K["Neu bauen + starten"]
K --> L["✓ Rollback"]
```
Ein kaputtes Deployment heilt sich selbst, statt die Seite liegen zu lassen.
```bash
./scripts/update.sh --force # neu bauen ohne neuen Commit
./scripts/update.sh --branch dev # anderen Branch ausrollen
```
Der Reverse Proxy muss `X-Forwarded-Proto` und `X-Forwarded-Host` durchreichen, sonst
brechen Redirects und WebAuthn-Origin-Prüfungen. Fertige nginx- und Caddy-Blöcke sowie
die Anleitung zum Nachrüsten einer Datenbank stehen in
[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md).
Security-Header (`X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`, `HSTS`)
sind in `next.config.ts` gesetzt und nach dem Deploy im Browser gegenzuprüfen.
---
## Kommandos
```bash
npm run dev # Dev-Server auf :3000
npm run build # Produktions-Build (standalone)
npm run start # Produktions-Server lokal
npm run lint # ESLint
npm run typecheck # tsc --noEmit
npm test # Vitest
npm run test:watch # Vitest im Watch-Modus
npm run test:e2e # Playwright
npm run test:all # beide Suites
npm run docker:up # Stack bauen und starten
npm run docker:down # Stack stoppen
npm run docker:logs # Logs folgen
```
---
## Dateibaum
```
CLAUDE.md Wird jede Session geladen: Stack, Struktur, Konventionen
README.md Dieses Dokument
.claude/
settings.json Permissions: Deny für Secrets, Allow für Routine
rules/
general.md Immer aktiv: Tracking, Status, Git, Human-in-the-Loop
frontend.md Bei UI-Dateien
backend.md Bei API-, lib- und Schema-Dateien
security.md Bei API-, Auth-, Env- und Deploy-Dateien
skills/
init/SKILL.md /init
write-spec/SKILL.md /write-spec (+ template.md für neue Specs)
refine/SKILL.md /refine
architecture/SKILL.md /architecture
frontend/SKILL.md /frontend
backend/SKILL.md /backend
qa/SKILL.md /qa
deploy/SKILL.md /deploy
help/SKILL.md /help
agents/
frontend-dev.md Sub-Agent für UI
backend-dev.md Sub-Agent für Server
qa-engineer.md Sub-Agent für Tests und Audit
docs/
PRD.md Füllt /init im Interview
DEPLOYMENT.md Docker-Betrieb, Proxy, DB nachrüsten, Troubleshooting
features/
INDEX.md Zentrales Status-Tracking
src/
app/
layout.tsx ThemeProvider + Toaster verdrahtet
page.tsx Startseite mit Workflow-Übersicht
globals.css Tailwind v4: Theme-Tokens in @theme inline
api/health/route.ts Liveness-Probe für Docker und update.sh
components/
theme-provider.tsx
ui/ button, card, input, label, form, sonner
lib/
utils.ts cn()
utils.test.ts Vitest-Muster
test/setup.ts
tests/smoke.spec.ts Playwright-Muster
scripts/update.sh Pull, Rebuild, Restart, Rollback
Dockerfile Dreistufig → standalone, unprivilegierter User
compose.yaml App-Service, Healthcheck, Log-Rotation
.env.example Jede benötigte Variable mit Dummy-Wert
.gitattributes Erzwingt LF — sonst scheitert update.sh auf dem Server
.dockerignore .gitignore eslint.config.mjs next.config.ts
playwright.config.ts postcss.config.mjs vitest.config.mts
components.json tsconfig.json package.json
```
55 Dateien im Repo.
---
## Stolperfallen
Vier Dinge, die nicht offensichtlich sind und je einmal wehtun:
| Fall | Was passiert |
|------|--------------|
| `NEXT_PUBLIC_APP_URL` weicht von der Domain ab | Alle Passkeys scheitern, ohne verwertbare Fehlermeldung |
| Port 3000 ist von einem anderen Projekt belegt | Playwright testet still gegen den fremden Server — `E2E_PORT` setzen |
| Jemand legt eine `tailwind.config.ts` an | Wird in v4 ignoriert; Tokens gehören in `globals.css` |
| Checkout auf Windows ohne `.gitattributes` | `update.sh` bekommt CRLF und stirbt auf dem Server mit `bad interpreter` |
---
## Anpassen
| Was | Wo |
|-----|-----|
| Stack, Konventionen, Kommandos | `CLAUDE.md` |
| Coding-Standards | `.claude/rules/` |
| Workflow-Schritte selbst | `.claude/skills/*/SKILL.md` |
| Aufgabenteilung der Sub-Agents | `.claude/agents/` |
| Permissions | `.claude/settings.json` |
| Spec-Aufbau | `.claude/skills/write-spec/template.md` |
Ein neues Kommando ist ein neuer Ordner unter `.claude/skills/` mit einer `SKILL.md`
und `user-invocable: true` im Frontmatter. Ein neuer Sub-Agent ist eine Markdown-Datei
in `.claude/agents/` mit `name`, `description`, `tools` im Frontmatter.
---
## Lizenz
MIT