What this prompt does
This prompt drives an AI to output an entire Next.js 14+ feature as a set of real files — not a tutorial fragment, not a concept sketch. The ten-point structure maps directly to how the App Router actually works: route segments, async server components for initial data, server actions for mutations, and client components kept to the interactive minimum. Because every variable ([orm], [auth_provider], [validation_lib]) is explicit, the AI cannot paper over integration details with vague pseudocode.
The server-first constraint in the closing instruction ("server-first rendering, minimal client JS") is load-bearing. Without it, most AI tools default to useEffect-heavy output that contradicts App Router conventions and worsens Core Web Vitals. By stating it explicitly alongside generateMetadata() and revalidation, the prompt locks in production-quality patterns rather than tutorial-quality placeholders.
When to use it
- Scaffolding a new product area — user dashboard, billing portal, notification centre — where you need the full file tree before writing any real logic.
- Prototyping a multi-step form with Prisma mutations and Zod validation before your team reviews the data model.
- Migrating a Pages Router feature to App Router and needing a reference implementation of the equivalent server-action + route-handler split.
- Starting a client project where the stack is fixed (e.g., Supabase + Tailwind + NextAuth) and you want all the boilerplate wired correctly from day one.
- Exploring how a new auth provider (Clerk, Auth.js, Lucia) integrates into middleware and protected layouts.
Example output
For [feature_name] = "user onboarding wizard", [database] = Postgres via Prisma, [auth_provider] = Clerk, [validation_lib] = Zod:
app/onboarding/
layout.tsx <- checks Clerk auth, redirects if complete
page.tsx <- server component, reads onboarding step from DB
loading.tsx <- skeleton for step form
error.tsx <- boundary with retry button
actions.ts <- server actions: saveStep(), completeOnboarding()
types.ts <- OnboardingStep, UserProfile shared types
_components/
StepForm.tsx <- 'use client', calls saveStep() via form action
ProgressBar.tsx <- 'use client', receives step as prop
app/api/onboarding/
route.ts <- GET /api/onboarding for external webhook
prisma/
schema.prisma <- OnboardingState model added
Each file is output in full with imports, Zod schemas, Prisma queries, and Clerk auth() calls in the correct locations.
Pro tips
- Fill
[api_needs]precisely. Writing "REST endpoint for step data" produces a generic route handler. Writing "GET /api/onboarding/status for a Zapier webhook trigger" produces one with the correct response shape and auth bypass pattern. - Name the ORM version.
[orm] = Prisma 5versus[orm] = Drizzle ORMproduces structurally different database layers. Vague input gets a guess that may not match your lock file. - Run the output through
tsc --noEmitimmediately. The AI will sometimes infer incompatible types between the server action return and the client form state. Catching this before you wire state is faster than debugging hydration errors. - Seed the AI with your existing schema. Before sending this prompt, paste your current Prisma schema or Drizzle table definitions (or a
CLAUDE.md/.cursorrulesfile that lists them) as context. This eliminates duplicate type definitions and naming conflicts that are otherwise tedious to untangle. - Iterate on one section at a time after the first pass. Once you have the full tree, re-prompt with just the
actions.tsblock and add "include optimistic updates usinguseOptimistic" — surgical regeneration is faster than a full re-run.