AI Coding Starter Kit

Next.js-Vorlage mit einem durchgängigen KI-Workflow für 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

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

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

/init Einmalig pro Projekt. Interviewt dich zu Problem, Zielgruppe, MVP-Umfang, Alternativen, Rahmenbedingungen, Erfolgsmetriken und Nicht-Zielen. Klärt verbindlich 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 keine Spec-Dateien.
/write-spec 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 /refine). Füllt neben User Stories und Acceptance Criteria auch Out of Scope, Produkt-Entscheidungen und Offene Fragen.
/refine Öffnet eine bestehende Spec. Fragt zuerst „Was bringt dich zurück zu dieser Spec?" und wählt danach den Pfad: 1) Scope hat sich geändert, 2) die Umsetzung hat eine Lücke aufgedeckt, 3) das Feature gehört grundsätzlich hinterfragt — bis hin zum Aufsplitten in zwei Specs. Schließt erledigte Offene Fragen mit Datum.
/architecture Übersetzt die Spec in ein Design, das auch ohne Technikhintergrund lesbar ist: Komponentenbaum, Datenmodell in Worten, begründete Tech-Entscheidungen, Paketliste. Schreibt bewusst keinen Code — kein SQL, kein TypeScript. Trifft hier die Datenbank-Entscheidung, die die Vorlage offenlässt.
/frontend Klärt Designfragen mit dir (oder liest docs/design-system.md), 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.
/backend 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 /architecture, nicht hierher.
/qa 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".
/deploy 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 ./scripts/update.sh. Setzt Status, Tag und Deployment-Notiz.
/help 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.

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.

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/**
src/app/**/page.tsx
src/app/**/layout.tsx
src/hooks/**
shadcn-Pflicht, Tailwind-v4-Eigenheiten, semantische Tokens, Server Components, Loading/Error/Empty, Formulare
backend.md src/app/api/**
src/lib/**
src/server/**
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*
.env*, next.config.*
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.

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.

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:

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.

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
docker compose up -d --build     # Erststart
./scripts/update.sh              # neuen Stand ausrollen

Was update.sh macht

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.

./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.

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

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

S
Description
No description provided
Readme
499 KiB
Languages
TypeScript 64.1%
CSS 16.7%
Shell 12.9%
Dockerfile 4.7%
JavaScript 1.6%