Communitygithub.com

Nuvraxis/nuvraxis-plugins

Produktionsregeln für Next.js 16 App Router Apps bei Nuvraxis – Server/Client Component Grenzen, Cache Components ("use cache", cacheLife, cacheTag, updateTag), Server Actions, Route Handler, Environment Handling, Instrumentierung, Output Standalone und die /api/health Route. Verwenden, wenn das Projekt "next" in package.json, ein app/ oder src/app/ Verzeichnis, next.config.ts, proxy.ts, instrumentation.ts oder Dateien namens page.tsx, layout.tsx, route.ts, loading.tsx, error.tsx hat.

Was ist nuvraxis-plugins?

Dieses Skill definiert die spezifischen Produktionsregeln für Next.js 16 App Router Anwendungen bei Nuvraxis. Es ergänzt die allgemeinen Best Practices und konzentriert sich auf die Architektur mit Cache Components ("use cache", cacheLife, cacheTag, updateTag), die korrekte Trennung von Server- und Client-Komponenten, Server Actions mit Validierung und Autorisierung, sowie die Konfiguration für selbst gehostete Anwendungen (output: "standalone", Nonce-basiertes CSP). Das Skill setzt Next 16.4, React 19.3, Turbopack und Cache Components voraus und stellt sicher, dass Server Actions immer Eingaben validieren und autorisieren, dass dynamische Daten in Suspense-Boundaries gekapselt werden, und dass die Anwendung eine Abhängigkeits-freie /api/health Route bereitstellt. Es behandelt auch Environment-Variablen, die Verwendung von "server-only", die after()-Funktion für asynchrone Aufgaben nach der Antwort, und die Instrumentierung mit OpenTelemetry. Entwickler, die dieses Skill nutzen, erhalten detaillierte Anweisungen mit Codebeispielen, die die konsistente Einhaltung der Nuvraxis-Standards in allen Next.js-Projekten sicherstellen.

Funktioniert mit✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Nuvraxis/nuvraxis-plugins/tree/HEAD/plugins/nuvraxis-frontend/skills/nextjs-production

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Next.js in Produktion

Verwenden für jeglichen Code in einer Next.js 16 App Router App. Sicherheitsspezifische Regeln (Authentifizierung in Actions, CSP, Header, Taint) befinden sich in nextjs-security; Container-Regeln in docker-nextjs. Das integrierte next-best-practices-Skill von Claude Code behandelt allgemeine Dateikonventionen, Metadaten, Bild- und Schriftoptimierung ausführlich; dieses Skill fügt nur hinzu, was für unsere Art zu bauen und auszuliefern spezifisch ist.

Basislinie: Next 16.4, React 19.3, Turbopack (Standard für dev und build), cacheComponents: true mit partialPrefetching: true, output: "standalone", typedRoutes: true. Die next.config.ts der Vorlage ist die Quelle der Wahrheit.

Regeln

  1. Server Components standardmäßig; "use client" nur für State, Effekte, Browser-APIs oder Event-Handler. Setze die Direktive auf das kleinste Blatt, das sie benötigt. Füge sie nicht hinzu, weil eine Datei nuvui importiert: Die statebehafteten Teile von nuvui tragen ihre eigene Direktive (siehe das nuvui Skill, rules/server-components.md).

    // Falsch: ganze Seite ist client wegen eines Handlers
    "use client";
    export default function Page() { … <Select onValueChange={…} /> … }
    
    // Richtig: die Seite bleibt auf dem Server, der Handler lebt in einem Blatt
    export default async function Page() {
      const people = await getPeople();
      return <PeopleFilter people={people} />; // people-filter.tsx hat "use client"
    }
    

    Props, die in eine Client-Komponente übergeben werden, müssen serialisierbar sein: keine Funktionen (außer Server Actions), keine Klasseninstanzen.

  2. Fetch auf dem Server, in der Komponente, die die Daten benötigt. Kein useEffect-Fetching, kein Route Handler nur um die eigene Seite zu füttern. Deduplizieren pro Request mit Reacts cache(); über Requests hinweg cachen mit Regel 3.

  3. Cachen mit "use cache" + cacheLife + cacheTag; alles andere ist dynamisch. Mit Cache Components wird nichts gecached, es sei denn, du sagst es, und fetch hat keinen impliziten Cache.

    import { cacheLife, cacheTag } from "next/cache";
    
    export async function getInvoice(id: InvoiceId) {
      "use cache";
      cacheLife("minutes");
      cacheTag(`invoice:${id}`);
      return db.invoice.findUnique({ where: { id } });
    }
    

    Verwende nicht die alte Segment-Konfiguration (export const dynamic, revalidate, fetchCache): Sie verursacht Fehler unter Cache Components. Argumente und geschlossene Werte werden Teil des Cache-Keys, also übergib IDs, nicht ganze Request-Objekte. Details, die Profile und "use cache: private": references/caching.md.

  4. Invalidieren mit updateTag in Server Actions, revalidateTag(tag, "max") anderswo. updateTag(tag) ermöglicht Read-Your-Own-Writes und funktioniert nur innerhalb einer Server Action. Von einem Webhook oder Route Handler aus verwende revalidateTag(tag, "max") (Stale-While-Revalidate) oder revalidateTag(tag, { expire: 0 }). Die Ein-Argument-Variante revalidateTag(tag) ist veraltet.

  5. Kapsle anfragezeitliche Daten in <Suspense>, sonst schlägt der Build fehl. cookies(), headers(), searchParams, connection() und ungecachte I/O außerhalb einer Suspense-Grenze stoppen das Vorrendern mit "uncached or runtime data during prerendering". Gib ihm eine Grenze mit einem Skeleton-Fallback, cache es oder (nur Root-Layout, siehe Regel 14) markiere die Route als blockierend mit export const instant = false. Alle params, searchParams, cookies(), headers() sind asynchron: await sie.

  6. Jede Server Action validiert ihre Eingabe und überprüft die Autorisierung selbst. Eine Server Action ist ein öffentlicher POST-Endpunkt, egal auf welcher Seite sie geschrieben ist. Parse FormData mit dem Schema aus typescript-production (valibot), dann autorisiere, dann mutiere, dann updateTag. Gib ein typisiertes Ergebnis für erwartete Fehler zurück; wirf nur für Bugs. Das vollständige Regelwerk befindet sich in nextjs-security.

    "use server";
    export async function renameProject(_: State, form: FormData): Promise<State> {
      const session = await requireSession();                  // 401 wenn abwesend
      const input = v.safeParse(RenameProject, Object.fromEntries(form));
      if (!input.success) return { ok: false, errors: flatten(input.issues) };
      await assertCanEdit(session, input.output.projectId);    // 403 wenn nicht erlaubt
      await db.project.update(…);
      updateTag(`project:${input.output.projectId}`);
      return { ok: true };
    }
    
  7. Route Handler sind für andere Clients (Webhooks, Mobil, Health), nicht für deine eigenen Seiten. Lege sie unter app/api/. Validiere den Body wie eine Action, gib Response.json(...) zurück und setze Statuscodes bewusst.

  8. Jede App hat GET /api/health, dynamisch und abhängigkeitsfrei. Docker HEALTHCHECK und die Kubernetes-Probes treffen darauf. Es muss antworten, ohne die Datenbank zu berühren, damit eine langsame Abhängigkeit nicht jeden Pod neustartet. await connection() verhindert, dass es zu einer statischen Datei vorgerendert wird. Es befindet sich in der Vorlage unter src/app/api/health/route.ts; proxy.ts schließt /api/health von seinem Matcher aus.

  9. error.tsx, loading.tsx und not-found.tsx im Root und pro Segment, wo sich die UX unterscheidet. error.tsx ist eine Client-Komponente; logge durch onRequestError von instrumentation.ts, zeige einen Retry mit reset, niemals die Fehlermeldung. Rufe notFound() für fehlende Datensätze auf, anstatt einen leeren Zustand zu rendern.

  10. NEXT_PUBLIC_* wird zur Build-Zeit eingebrannt; alles andere wird zur Laufzeit auf dem Server gelesen. Ein Image wird unverändert von Main auf Production befördert, daher ist ein NEXT_PUBLIC_-Wert in jeder Umgebung gleich. Gib dort nur Build-Zeit-Konstanten an (App-Name, ein öffentlicher Sentry DSN, der überall gleich ist). Umgebungsspezifische Konfiguration (API-URLs, Feature-Flags, Secrets) ist serverseitiges process.env.X, gelesen in einer Server Component oder Action, und wird bei Bedarf als Props an den Client übergeben. Validiere Env einmal in src/env.ts (valibot) und importiere von dort. Verwende niemals den env-Schlüssel in next.config.ts: Er wird in Client-Bundles inline eingefügt.

  11. Markiere Server-Only-Module mit import "server-only". Alles, was Secrets liest, mit der DB spricht oder ein SDK mit Anmeldedaten importiert. Ein Client-Import davon führt dann zu einem Build-Fehler anstatt zu einem Leak.

  12. after() für Arbeit, die die Antwort nicht verzögern sollte (Audit-Logs, Analytics, Cache-Warm-up). Lese cookies()/headers() vor dem Aufruf von after, nicht darin. Es läuft im selben Prozess, daher braucht der Pod seine SIGTERM-Grace-Periode (das Chart setzt terminationGracePeriodSeconds).

  13. Instrumentieren mit src/instrumentation.ts: registerOTel + onRequestError. OpenTelemetry via @vercel/otel, Exporter konfiguriert durch die standardmäßigen OTEL_EXPORTER_OTLP_*-Umgebungsvariablen zur Laufzeit. Siehe references/observability.md.

  14. Behalte output: "standalone" und importiere niemals von außerhalb des Workspace. Der Docker-Runner kopiert nur .next/standalone, .next/static und public. Im Monorepo landet server.js unter .next/standalone/apps/<app>/server.js; das Workspace-Root wird aus pnpm-lock.yaml gefunden, also setze outputFileTracingRoot oder turbopack.root nur, wenn der Build warnt. Self-Hosting-Details (Multi-Replica, Server Action Keys, deploymentId): references/self-hosting.md.

  15. Das Root-Layout liest den CSP-Nonce, daher rendert die App pro Request. Die proxy.ts der Vorlage setzt ein Nonce-basiertes CSP und src/app/layout.tsx hat export const instant = false. Das ist ein bewusster Kompromiss: Nonces und vorgerenderte statische Shells können nicht koexistieren, und für eingeloggte Business-Apps gewinnt ein striktes CSP. Daten-Caching mit "use cache" funktioniert weiterhin. Entferne keine der beiden Hälften, ohne nextjs-security Regel 4 zu lesen.

  16. Styles: globales BEM SCSS, von der Komponente importiert. Turbopack kompiliert Sass mit dem sass-Paket; sassOptions.loadPaths: ["src/styles"] macht @use "abstracts" aus jeder Tiefe funktionsfähig. Keine ~-Imports, keine sassOptions.functions. Regeln in scss-bem.

  17. Bilder durch next/image, Schriften durch next/font. sharp kommt mit Next für den Optimierer; das Runner-Image benötigt kein zusätzliches Paket. Remote-Bilder benötigen images.remotePatterns mit einem exakten Hostnamen.

  18. Überprüfe die Bundle-Größe mit pnpm next analyze (Turbopacks Analyzer; @next/bundle-analyzer ist nur für Webpack). Lade schwere Client-Widgets (nuvui Editor, Karten, Diagramme unter dem Fold) lazy mit next/dynamic.

  19. Verwende typisierte Routen und generierte Typen. typedRoutes: true überprüft <Link href>; PageProps<"/invoices/[id]"> und LayoutProps sind global nach next typegen (wird automatisch von next dev/next build ausgeführt). Schreibe params-Typen nicht von Hand.

  20. Kein next lint. Es wurde in 16 entfernt. Biome lintet (siehe biome); TypeScript überprüft mit tsc --noEmit pro Paket.

Überprüfen

pnpm typecheck
pnpm lint
pnpm build                      # turbo run build: schlägt fehl bei Prerender-Fehlern, Typfehlern, Sass-Fehlern
pnpm --filter <app> start &     # dann:
curl -fsS localhost:3000/api/health

Quellen

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Nuvraxis/nuvraxis-plugins

>- Biome 2.5 setup and rules for Nuvraxis monorepos — root biome.json with pinned $schema, VCS ignore, formatter settings, the recommended preset with a11y and the react/next domains, nursery policy, organize imports, overrides, nested per-package configs ("extends": "//"), biome check --write locally, biome ci in CI, VS Code settings, and migrating from ESLint/Prettier. Use when the repo has biome.json or biome.jsonc, @biomejs/biome in package.json, .eslintrc*/eslint.config.*/.prettierrc* to migrate, or when fixing lint and formatting errors.

Nuvraxis/nuvraxis-plugins

>- Dockerfile rules for Next.js standalone apps in a pnpm + Turborepo monorepo — multi-stage build (turbo prune → pnpm fetch/offline install → turbo build → minimal runner), pinned Node 26 Alpine by digest, checksum-verified pnpm binary, non-root uid 1001, read-only root filesystem with a writable .next/cache, HEALTHCHECK on /api/health, build args only for NEXT_PUBLIC_* values, BuildKit secrets and cache mounts, multi-arch, OCI labels and .dockerignore. Use when the repo has a Dockerfile, .dockerignore, compose file, or next.config with output "standalone", or when asked to containerise, shrink, harden or debug an image.

Nuvraxis/nuvraxis-plugins

>- GitHub Actions conventions for Nuvraxis Next.js apps — exactly three workflows: pr.yaml (every PR to any branch: Biome, stylelint, typecheck/test/build with turbo --affected, Docker build + health check, helm lint + kubeconform; publishes nothing), main.yaml (push to main: one multi-arch image to GHCR tagged sha-SHORTSHA and main, provenance + SBOM, gha cache), release.yaml (tag vX.Y.Z: verify on main, retag the existing image without rebuilding, package and push the Helm chart to OCI, GitHub Release with chart, digest and SBOM). Minimal permissions per job, GITHUB_TOKEN only, pinned action majors. Use when editing .github/workflows/*, adding a CI step, or debugging a failed run or release.

Nuvraxis/nuvraxis-plugins

>- Helm chart rules for Nuvraxis Next.js apps — one chart per app in charts/ (named after the app), published to oci://ghcr.io/nuvraxis/charts and synced by Argo CD; Chart.yaml version/appVersion set only by release.yaml; Deployment with startup/liveness/readiness probes on /api/health, non-root read-only security context, emptyDir for .next/cache, ConfigMap + existing Secret via envFrom, Service, Ingress with cert-manager, HPA, PDB, ServiceAccount, topology spread; no Helm hooks; helm lint --strict + kubeconform. Use when the repo has charts/, Chart.yaml, values*.yaml, templates/*.yaml with Helm syntax, or an Argo CD Application, or when asked to deploy, scale, expose or configure the app on Kubernetes.

Verwandte Skills