Next.js Production Stack
Meinungsstarke Standardeinstellungen für die Entwicklung und Wartung von Next.js-Anwendungen. Wenn Sie ein neues Projekt erstellen oder zu einem bestehenden hinzufügen, befolgen Sie diese Konventionen, es sei denn, die vorhandene Codebasis des Nutzers macht eindeutig etwas anderes – passen Sie sich in diesem Fall den vorhandenen Mustern an, anstatt an diesem Dokument festzuhalten, und notieren Sie die Abweichung kurz.
0. Stack auf einen Blick
| Schicht | Empfohlen (bevorzugt, nicht streng) | Optionen bei gewünschter Änderung |
|---|---|---|
| Framework | Next.js (App Router), TypeScript, Server Components + Server Actions | keine erforderlich, dies ist der Kern |
| Paketmanager | pnpm | npm, yarn, bun |
| UI | Tailwind CSS, shadcn/ui, react-icons, Motion (motion.dev) | Radix UI oder Mantine, lucide-react, CSS Modules |
| Formulare | React Hook Form + Zod | TanStack Form, Valibot statt Zod |
| Datenbank | PostgreSQL + Drizzle ORM | Prisma, Kysely; MySQL oder SQLite für kleine Apps |
| Authentifizierung | Better Auth, RBAC | Auth.js, Clerk, Supabase Auth |
| Medien | Cloudinary | UploadThing, S3 + CDN, Vercel Blob |
| Tests | Vitest (Unit/Integration), Playwright (e2e) | Jest, Cypress |
| Monitoring | Sentry, strukturierte Protokollierung | Datadog, Highlight, Axiom + pino |
| Lint/Format | ESLint, Prettier, TypeScript strict | Biome |
| CI/CD | GitHub + GitHub Actions, Vercel, Preview-Deployments | GitLab CI, Netlify, Cloudflare Pages |
Tauschen Sie niemals stillschweigend ein Paket aus dieser Tabelle gegen eine Alternative aus (z. B. Prisma statt Drizzle, next-auth statt Better Auth). Wenn das Projekt des Nutzers bereits eine andere Wahl verwendet, verwenden Sie diese weiter und weisen Sie auf die Abweichung hin, anstatt zwei Lösungen für dieselbe Aufgabe zu mischen.
Diese Tools werden empfohlen: Der Nutzer bevorzugt sie, aber sie sind nicht streng.
- Wo immer ein späterer Abschnitt ein bestimmtes Tool nennt (pnpm, Drizzle, Better Auth, Cloudinary, Sentry usw.), lesen Sie es als empfohlene Standardeinstellung gemäß dieser Regel.
- Fragen Sie den Nutzer, bevor Sie ein Tool in der Tabelle ändern, ersetzen oder überspringen. Bieten Sie Optionen an: Behalten Sie das empfohlene Tool bei, oder eine Alternative aus der letzten Spalte (oder eine andere bewährte Methode), mit einem einzeiligen Kompromiss für jede Option und Ihrer eigenen Empfehlung.
- Überprüfen Sie den aktuellen Status (Wartung, Breaking Changes), bevor Sie eine Alternative empfehlen. Verlassen Sie sich nicht nur auf Ihr Gedächtnis.
- Ändern Sie niemals ein Tool ohne eine Antwort. Bis der Nutzer antwortet, behalten Sie die empfohlene Standardeinstellung bei.
1. Projekteinrichtung
- Erstellen Sie das Grundgerüst mit
pnpm create next-app@latest– TypeScript, App Router, Tailwind, ESLint alle aktiviert, lehnen Sie dassrc/-Verzeichnis ab, damitapp/im Projektstammverzeichnis bleibt (nur bei neuen Projekten). - Bestehendes Projekt, das bereits
src/verwendet: Behalten Siesrc/bei –src/app/,src/components/,src/lib/,src/actions/. Verwenden Sieapp/nur, wenn das Projekt keinsrc/-Verzeichnis hat. Folgen Sie dem vorhandenen Layout und den Import-Aliasen (@/*→src/*); verschieben Sie niemals Dateien aussrc/im Rahmen einer nicht damit zusammenhängenden Aufgabe. - Verwenden Sie pnpm für alle Installations-/Ausführungsbefehle (
pnpm add,pnpm dlx,pnpm dev). Mischen Sie niemals npm/yarn-Sperrdateien. - Initialisieren Sie shadcn/ui mit
pnpm dlx shadcn@latest init, fügen Sie dann Komponenten nach Bedarf hinzu (pnpm dlx shadcn@latest add button), anstatt den gesamten Satz vorab zu installieren. - Grundlegende Ordnerstruktur (ohne
src/–app/liegt im Projektstammverzeichnis):
# neue Projekte (ohne src/)
app/ # Routen, Layouts, Fehler-/Lade-/Nicht-Gefunden-Grenzen
components/ # gemeinsame UI (ui/ = shadcn-Primitive)
lib/ # DB, Auth, Validierungen, Utils, Rate-Limit, Logger
actions/ # Server-Aktionen, nach Domäne gruppiert
hooks/
types/
drizzle/ # Migrationen
Bestehende src/-Projekte: gleiche Struktur unter src/ (src/app/, src/components/, src/lib/, src/actions/) – die Ordnernamen bleiben identisch, nur das Präfix ändert sich.
2. TypeScript & Code-Qualität
strict: truein tsconfig, keinanyohne einen kommentierten Grund, kein@ts-ignoreohne ein verknüpftes Issue/einen Grund.- ESLint (next/core-web-vitals + typescript-eslint) und Prettier konfiguriert und bestanden, bevor Code als fertig gilt; führen Sie sie aus, gehen Sie nicht nur davon aus.
- Bevorzugen Sie explizite Rückgabetypen bei exportierten Funktionen und Server-Aktionen.
- Behalten Sie Server Components als Standard; fügen Sie
"use client"nur hinzu, wo Interaktivität, Browser-APIs oder Hooks dies erfordern, und schieben Sie die Grenze so weit wie möglich nach unten (auf Blattebene). - Eine Verantwortung pro Datei/Modul; gruppieren Sie die Server-Aktionen einer Route in
actions/oder einer_actions.ts-Datei neben der Route, nicht inline in riesigen Seitendateien. - Architekturkonventionen: Halten Sie sich an einen Ort für jede Art von Logik – Datenzugriff in
lib/db, Mutationen inactions/, gemeinsame UI incomponents/, übergreifende Helfer inlib/. Folgen Sie der vorhandenen Benennung des Projekts (Dateischreibweise, Komponentenbenennung), anstatt mitten im Prozess eine neue Konvention einzuführen. - Code-Review: Behandeln Sie jede nicht-triviale Änderung in PR-Größe – ein klarer Diff, bestandener Lint/Typ-Check/Tests vor der Anforderung eines Reviews und eine Beschreibung, was geändert wurde und warum. Überprüfen Sie bei der Durchsicht (menschlich oder KI-gestützt) auf fehlende Auth-Prüfungen, unbehandelte Fehler und Konventionsabweichungen, nicht nur darauf, ob es läuft.
3. Rendering, Daten & Leistung
- Statisches vs. dynamisches Rendering: Standardmäßig statisch; entscheiden Sie sich nur dann für dynamisch (
export const dynamic = 'force-dynamic',cookies(),headers()), wenn die Route wirklich Daten pro Anfrage benötigt. - Datenabruf: Rufen Sie Daten direkt in Server Components ab; verwenden Sie Server Actions für Mutationen, nicht clientseitige fetch-to-API-Route, es sei denn, der Verbraucher ist extern.
- Streaming & Suspense: Umschließen Sie langsame/streamingfähige Abschnitte mit
<Suspense>und einem echten Skeleton-Fallback (kein bloßer Spinner), damit der Rest der Seite sofort rendern und streamen kann – dies ist auch das, wasloading.tsxauf Routenebene bietet. - Caching & Revalidierung: Verwenden Sie
use cache/unstable_cache(pro Next-Version) für teure Lesevorgänge; ungültig machen Sie präzise mitrevalidatePath/revalidateTagnach Mutationen, anstatt zuforce-dynamiczu greifen, um Veraltung zu "beheben". - Prefetching: Prefetchen Sie Links, denen Benutzer wahrscheinlich folgen werden –
<Link>macht dies automatisch; deaktivieren Sie es nicht (prefetch={false}) ohne einen bestimmten Grund. - Lazy Loading & Code-Splitting: Laden Sie unterhalb des Seitenendes oder selten verwendete Client-Komponenten mit
next/dynamicträge; vermeiden Sie große Client-Bundles von Bibliotheken, die nur auf einer Seite benötigt werden. - Bild- & Schriftoptimierung: Verwenden Sie immer
next/imagefür Rasterbilder (explizitewidth/heightoderfill+ dimensionierter Container) undnext/fontfür Schriften – niemals rohe<img>oder einen<link>zu Google Fonts. - Core Web Vitals: Behandeln Sie LCP, CLS, INP als echte Einschränkung – keine layoutverschiebenden späten Inhalte, keine undimensionierten Medien, keine blockierenden synchronen Skripte.
4. UI
- Tailwind für Styling; shadcn/ui-Komponenten als Basisprimitiven, angepasst über die Theme-Token (CSS-Variablen) des Projekts, nicht über vereinzelte Inline-Überschreibungen, die über Dateien verstreut sind.
- react-icons für Icons (wählen Sie ein Icon-Set pro Projekt, z. B.
react-icons/luoder/hi2, und bleiben Sie konsistent). - Motion (motion.dev, früher Framer Motion) für Animationen; halten Sie animierte Komponenten clientseitig und klein und respektieren Sie
prefers-reduced-motion. - Entwerfen Sie standardmäßig responsiv (Mobile-First-Tailwind-Breakpoints); liefern Sie kein Nur-Desktop-Layout aus.
5. Formulare & Validierung
- Definieren Sie ein Zod-Schema pro Formular/Datenform; verwenden Sie dasselbe Schema für die Client-Validierung (über
@hookform/resolvers/zod) und die serverseitige Validierung innerhalb der Server Action – vertrauen Sie niemals einer reinen Client-Validierung. - React Hook Form (
useForm) steuert den Client-Status; rufen Sie bei der Übermittlung eine Server Action auf, geben Sie Feld Fehler aus dem strukturierten Rückgabewert der Aktion zurück (keine ausgelösten Ausnahmen, die in einem generischen Fehler enden). - Validieren Sie
process.envselbst mit einem Zod-Schema beim Start (einelib/env.ts), damit fehlende/falsch konfigurierte Konfiguration schnell fehlschlägt, anstatt bei der ersten Verwendung.
6. Datenbank (PostgreSQL + Drizzle)
- Schema lebt in
lib/db/schema.ts(oder pro Domäne aufgeteilt), Migrationen werden mitdrizzle-kit generategeneriert und mitdrizzle-kit migrateangewendet – bearbeiten Sie generierte Migrationsdateien niemals von Hand. - Verwenden Sie eine gepoolte Verbindung (z. B. über den Pool des Treibers oder einen Anbieter wie Neon/Supabase Pooling) in serverlosen/Edge-Kontexten; öffnen Sie keinen neuen Client pro Anfrage ohne Pooling.
- Abfrageoptimierung & N+1-Prävention: Verwenden Sie Drizzles relationale Abfragen (
db.query.x.findMany({ with: {...} })) oder explizite Joins, anstatt zu loopen und pro Zeile abzufragen; wählen Sie nur die Spalten aus, die Sie benötigen, anstattselect *-artige vollständige Zeilenabrufe; paginieren/begrenzen Sie jede Abfrage, die eine unbegrenzte Ergebnismenge zurückgeben kann. - Indizieren Sie Spalten, die in
WHERE/ORDER BY/Joins verwendet werden; fügen Sie sie im Schema hinzu, nicht als nachträglichen Einfall. - Halten Sie eine dokumentierte Sicherungs-/Wiederherstellungsstrategie für Produktionsdatenbanken bereit (minimal verwaltete Anbieter-Snapshots) – weisen Sie darauf hin, wenn das Setup des Nutzers keine hat.
7. Authentifizierung & Sicherheit
- Better Auth für die Authentifizierung (Sitzungen, OAuth-Anbieter, E-Mail/Passwort nach Bedarf); rollen Sie niemals selbst Passwort-Hashing oder Sitzungstoken aus.
- RBAC: Modellieren Sie Rollen/Berechtigungen explizit (eine
role-Spalte plus einen kleinen Berechtigungsprüf-Helper) und erzwingen Sie die Autorisierung in der Server Action / Datenzugriffsschicht, nicht nur durch Ausblenden der UI – ein ausgeblendeter Button ist keine Zugriffskontrolle. - Ratenbegrenzung für sensitive Endpunkte (Authentifizierung, Formulareinsendungen, alles Teure) – z. B. über Upstash Redis oder einen gleichwertigen Token-Bucket/Sliding-Window-Limiter.
- Setzen Sie Sicherheitsheader (über
next.config.js-Header oder Middleware):Content-Security-Policy,X-Frame-Options,Referrer-Policy,Permissions-Policy,Strict-Transport-Security. - Cookies:
httpOnly,secure,sameSite: 'lax'(oder'strict', wo praktikabel) auf allen Authentifizierungs-/Sitzungs-Cookies. - Validieren Sie jede externe Eingabe (Formulardaten, Abfrageparameter, Webhook-Payloads) mit Zod an der Grenze, bevor sie die Geschäftslogik oder die Datenbank berührt.
- Protokollieren Sie niemals Geheimnisse, Token oder vollständige Anfragekörper mit Anmeldeinformationen.
8. SEO
- Verwenden Sie die Metadata-API (
generateMetadata/ statischermetadata-Export) pro Route – Titel, Beschreibung, Open Graph, Twitter Card. - Stellen Sie
app/sitemap.tsundapp/robots.tsbereit, die aus echten Routendaten generiert werden, nicht aus einer hartcodierten veralteten Liste. - Legen Sie kanonische URLs über
alternates.canonicalin den Metadaten fest, insbesondere bei Routen, die über mehrere Query-String-Varianten erreichbar sind. - Fügen Sie JSON-LD-Structured-Data für Inhaltstypen hinzu, die davon profitieren (Artikel, Produkte, Breadcrumbs, Organisation), indem Sie ein Skript-Tag mit
type="application/ld+json"verwenden.
9. Barrierefreiheit
- Semantisches HTML zuerst (
button,nav,main,header,label) – greifen Sie nur auf ARIA zurück, um eine echte Lücke zu füllen, die semantisches HTML nicht abdecken kann. - Alles erreichbar und bedienbar allein mit der Tastatur; sichtbare Fokus-Zustände (entfernen Sie
:focus-visible-Umrisse nicht, ohne sie zu ersetzen). - Jedes Bild hat einen aussagekräftigen
alt-Text (leeresalt=""nur für rein dekorative Bilder). - Jede Formulareingabe hat ein tatsächliches zugehöriges
<label>(nicht nur einen Platzhalter). - Überprüfen Sie den Farbkontrast mindestens gegen WCAG AA für Text und interaktive Elemente.
10. Fehlerbehandlung & Ladezustände
Jedes Routensegment, das fehlschlagen oder Zeit in Anspruch nehmen kann, sollte haben:
error.tsx– Segment-Level-Fehlergrenze mit einer Wiederholungsaktion.global-error.tsx– Top-Level-Fallback für Fehler, dieerror.tsxnicht abfangen kann.not-found.tsx– für 404er, einschließlichnotFound()-Aufrufen aus Datenabfragen.loading.tsx– Suspense-Fallback; machen Sie es zu einem echten Skeleton, das dem endgültigen Layout entspricht, nicht zu einem bloßen Spinner.
11. Tests
- Vitest für Unit-Tests (reine Funktionen, Schema-Validierung, Utility-Logik) und Komponententests (React Testing Library) – platzieren Sie sie als
*.test.ts(x)oder unter__tests__/. - Playwright für End-to-End-Abläufe: Authentifizierung, kritische Benutzerreisen, Formulareinsendungen. Führen Sie sie gegen ein Preview-Deployment oder einen lokalen Build aus, nicht gegen die Produktion.
- Neue Server Actions und Validierungsschemata sollten mit mindestens einem Basistest ausgeliefert werden; lassen Sie kritische Geschäftslogik nicht standardmäßig ungetestet.
12. Monitoring & Protokollierung
- Sentry für die Fehlerverfolgung sowohl auf dem Client als auch auf dem Server (Instrumentierungsdatei +
sentry.client.config/sentry.server.config), mit hochgeladenen Source Maps beim Deployment. - Strukturierte Protokollierung (JSON-Logs mit Anfrage-ID, Route, Benutzer-ID, wo verfügbar) anstelle von Ad-hoc
console.log. - Verfolgen Sie Core Web Vitals in der Produktion (Vercel Analytics oder Sentry Performance) und richten Sie Uptime-Monitoring für die bereitgestellte URL ein.
13. DevOps
- Git mit konventionellen, bereichsbezogenen Commits; geschützter
main-Branch. - GitHub Actions CI bei jedem PR: installieren → lint → typecheck → Unit-Tests → build (e2e für größere Änderungen hinzufügen).
- Deployment auf Vercel; jeder PR erhält ein Preview-Deployment vor dem Merge.
- Umgebungsvariablen pro Umgebung in Vercel verwaltet, beim Booten über das Zod-Env-Schema aus §5 validiert.
14. Medien
- Cloudinary für benutzerhochgeladene/dynamische Medien: Hochladen über signierte, serverausgestellte Upload-Parameter (das API-Geheimnis niemals clientseitig offenlegen) und Bereitstellung über Cloudinary-Transformations-URLs anstelle einer Neuimplementierung der Größenänderung.
15. Arbeitskonventionen für Claude
Wenn Sie aufgefordert werden, ein Feature in einem Projekt mit diesem Stack hinzuzufügen:
- Überprüfen Sie vorhandene Schemas/Aktionen/Komponenten, bevor Sie neue erstellen – erweitern Sie, duplizieren Sie nicht.
- Neue DB-Felder → aktualisieren Sie
schema.ts, generieren Sie eine Migration, bearbeiten Sie SQL nicht von Hand. - Neues Formular → Zod-Schema → RHF-Formular → Server Action mit serverseitiger Revalidierung und einer Autorisierungsprüfung.
- Neue Route → entscheiden Sie bewusst statisch vs. dynamisch; fügen Sie
loading.tsx/error.tsxhinzu, falls nicht vorhanden; fügen Sie Metadaten hinzu. - Führen Sie nach einer Mutation eine Revalidierung des spezifischen Pfads/Tags durch – nicht die gesamte App pauschal revalidieren.
- Führen Sie gedanklich Lint/Typ-Check im strikten Modus durch, bevor Sie Code präsentieren; kennzeichnen Sie jedes
any, ungeprüfte Eingabe oder fehlende Auth-Prüfung, anstatt es stillschweigend auszuliefern. - Fragen Sie den Nutzer mit Optionen, bevor Sie ein Tool aus Abschnitt 0 einführen, ersetzen oder überspringen (siehe die Regel "Empfohlen, nicht streng" in Abschnitt 0).
16. Companion-Regeldatei
AGENTS.md– die Projekt-Workflow-Regel (Hauptablauf, Feature-Ablauf, Genehmigungs-Gates, Änderungsprotokolle). Delegieren Sie die Verwaltung von Änderungsanfragen und -genehmigungen an diese Datei.