stack.menu

Next.js

React interfaces with server rendering, routes and application logic.

React · Next.js · PostgreSQL · Drizzle

Complete guide (Markdown) · Structured record (JSON)

Original source review: 2026-10-10. Core guidance rechecked: 2026-10-13. Check scope. Dependency combinations and setup need project-specific qualification.

Use cases

Choose it when

Consider another path when

Working practices

Tools by job

runtime and dependency management: Node LTS + npm lockfile

LTS production policy and reproducible dependency install

Pin resolved runtime/dependencies; latest is a scaffold-time lookup, not a CI dependency strategy

application framework: Next.js App Router + React + strict TypeScript

Full-stack React with version-matched agent documentation

TanStack Start official homepage labelled RC at review; web UI is not native UI; framework does not supply business correctness

project instructions: README navigation + generated version-matched agent guidance

Keep repository instructions and installed framework documentation discoverable

Honor existing instruction ownership. Optional README-only policy: scaffold with --no-agents-md and set agentRules:false before next dev; neither is required by this stack.

Agent runtime inspection: Next.js development MCP endpoint with real browser inspection

Combine version-matched framework context, compilation errors, routes and runtime logs with the actual rendered application.

Development only. Inspect the installed Next.js and next-devtools-mcp versions before configuring tools. Some runtime inspection requires an open browser session; Turbopack compilation tools have their own constraints. Framework tools do not replace authorization tests or real browser verification. Do not install optional skills or enable automatic upgrades merely to read this reference.

validation: Zod

Runtime schemas with inferred TypeScript types

Validate requests/environment/external results; shape checks do not establish permission or truth

database and migrations: PostgreSQL + Drizzle + reviewed SQL migrations

Typed schema with inspectable SQL history

Configure schema paths and target environment; apply migration once; rehearse fresh DB and forward compatibility

identity: Better Auth + Drizzle PostgreSQL adapter

Integrated session/provider support without designing password/session primitives

Auth schema generate then Drizzle migrations; direct Better Auth migrate is Kysely-only; configure origin/secrets/recovery; authorize near data

background work: Inngest durable workflows when required

Checkpointed steps, retries and waits

Idempotent effects and authorized approvals required; use outbox for DB/event consistency; avoid beta durable endpoints as default

Static typing: TypeScript strict

Independent deterministic checks for generated edits

Next build does not run lint; never ignore build/type errors to satisfy a check

Linting: ESLint

Independent deterministic checks for generated edits

Next build does not run lint; never ignore build/type errors to satisfy a check

Domain tests: Vitest

Run isolated domain behavior checks with a configured test environment

Install/configure Vitest and DOM environment for UI tests. Next async Server Components require browser/integration coverage instead.

Component tests: React Testing Library

Test rendered components through user-visible DOM behavior

Install @testing-library/react and its @testing-library/dom peer; configure the test runner/DOM environment. This is a component utility library, not a test runner.

Browser tests: Playwright

Exercise critical journeys in actual browser engines

Install @playwright/test and matching browsers; configure an isolated test server/data and test session expiry, routing and authorization failures.

deploy: Project-selected Node or Docker host

Documented full Next feature support with Node/Docker

Adapters vary; verify chosen host, secrets, DB connections, sessions, migrations and restore; Cloudflare needs separate compatibility review

Server state cache: TanStack Query for client-owned remote state

Queries, mutations and invalidation support interactive API screens

Install @tanstack/react-query and provide QueryClient. Define tenant-aware keys, staleTime/retry policy and clear session data on sign-out; in Next prefer server loading until a client cache has a job.

Forms: React Hook Form for complex client forms

Separates client form state and validation from page components

Install react-hook-form only where needed; wire existing runtime schemas deliberately. Render accessible labels/errors; validate and authorize submissions on the server.

Styling: Tailwind CSS when utility styling fits the project

Reusable styling without a runtime component dependency

For Vite install tailwindcss and @tailwindcss/vite, add the plugin and CSS import. Use the framework-specific installation path for Next; retain established styles when present.

Accessible UI primitives: Radix Primitives for complex controls

Provides focus and keyboard behavior for common interaction patterns

Install only used components. Authors still supply names, contrast and meaningful composition; verify keyboard and assistive-technology behavior.

Accessibility checks: axe-core through Playwright + manual keyboard review

Automated audits identify common accessibility defects in real pages

Install @axe-core/playwright; scan representative states and use a screen reader/keyboard. Passing automated rules is not complete accessibility evidence.

Transactional email: Nodemailer with project-selected SMTP provider

SMTP transport avoids coupling email templates to a hosting vendor

Install nodemailer; configure server-only transport, verified sender and TLS. Test locally, queue required delivery, handle ambiguous results and bounces; SMTP acceptance is not inbox delivery. Verify the resolved Nodemailer release supports the pinned Node runtime and preserves TLS certificate validation.

Uploads and object storage: AWS SDK for JavaScript v3 S3 client

Object storage separates durable files from ephemeral application disks

Install @aws-sdk/client-s3; authorize object keys, restrict size/type and configure lifecycle. Keep credentials server-side; add presigner only for direct uploads and validate provider compatibility.

Live server updates: EventSource for one-way server events

Browser-standard streaming suits status/progress feeds

Backend owns authenticated stream and event IDs. Test reconnect, replay and proxy buffering; EventSource is one-way and its constructor offers no arbitrary authorization-header option. Confirm long-lived connection support on host.

Build with the stack’s strengths

Architecture and developer workflow.

A Next application contains server rendering and browser interactivity with an explicit trust boundary. Recommendation: preserve an existing backend's domain ownership during UI adoption; for a new owned backend use server-only data access. Node/Docker and alternative adapters require separate runtime checks.

Version scope: Documentation reviewed 11 October 2026: current Next.js App Router docs label 16.4.0. Pin the installed Next, React, Node and database packages; distinguish cacheComponents:true from the previous caching model. This profile does not qualify a lockfile or hosting adapter. · Reviewed 2026-10-11

Architecture boundaries

Tools and feedback

Translations to avoid

For an existing application

Keep the contracts while you change the stack.

These are documented options and proposed checks. Inspect the actual source application before adopting a transition.

Data and schema

Inspect the source

Existing REST/GraphQL behavior, DTOs, authorization, transactions and one schema owner.

During coexistence

Recommendation: Adopt server-rendered routes that call the old API; keep its writer and migration authority. Compare read-only fixtures without replaying real side effects.

Target design

Recommendation: Retain the API permanently if appropriate, or transfer a bounded domain to a server-only DAL with minimal DTOs after mixed-version checks.

Rollback

Route the cohort back while old-compatible schema remains; reconcile writes before any writer reversal.

Benefits and prerequisites

Server loading can reduce client waterfalls; an owned DAL centralizes authorization.
Requires: Server-reachable API or reviewed database ownership; measurable user journeys.
Tradeoffs: A new domain writer requires schema/transaction review; framework adoption alone changes neither.

Checks before transfer

  • Old and new UI decode identical success/error/empty fixtures.
  • Forged resource IDs remain denied on both mutation paths.
  • An acknowledged write is readable through the old interface.
Identity and authorization

Inspect the source

Existing session issuer, cookie/token format, expiry, revocation, tenant membership and CSRF behavior.

During coexistence

Recommendation: Retain the issuer behind an adapter and authorize data/mutations in both implementations; inventory origin/domain/cookie differences before sharing.

Target design

Recommendation: Use an explicitly selected issuer and server-side authorization boundary; transfer session contracts or require a controlled sign-in when compatibility cannot be preserved.

Rollback

Restore old routes/issuer acceptance only while its keys and session semantics remain supported; do not resurrect revoked sessions.

Benefits and prerequisites

One identity authority can support gradual UI/backend replacement.
Requires: Validated issuer integration and old/new expiry/revocation fixtures.
Tradeoffs: Session sharing is format/security work; sign-in continuity is not guaranteed by using cookies.

Checks before transfer

  • Revoked and expired sessions fail in old/new paths.
  • Cross-tenant direct action requests are denied.
  • Sign-out clears browser remote-state caches and back navigation reveals no protected data.
Caching and shared state

Inspect the source

Actual enabled caching model, personalized response policy, keys, freshness, invalidation and shared-instance behavior.

During coexistence

Recommendation: Keep the prior policy while converting one route/data category; separate old/new cache namespaces and observe stale/account-crossing outcomes.

Target design

Recommendation: Choose Cache Components or version-matched previous-model APIs explicitly; keep user-specific data outside shared public entries and coordinate shared invalidation when deployed across instances.

Rollback

Disable the new cache path and purge its namespace; keep source data unchanged and retain old invalidation until transfer completes.

Benefits and prerequisites

Repeated eligible work can be reused without refetching each time.
Requires: A documented freshness tolerance, safe keys and working invalidation.
Tradeoffs: Coordination/storage adds operations; freshness and cost gains require measurement.

Checks before transfer

  • A write refreshes affected reads through every serving instance.
  • Account A cannot read cached output for account B.
  • Cold, warm and forced-refresh responses agree with the selected policy.
Jobs and schedules

Inspect the source

Existing job producer/consumer payloads, ready/scheduled/retry/failed/in-flight states and external-effect idempotency.

During coexistence

Recommendation: Keep existing workers; move a named job type behind a versioned event contract. Reconcile backlog and retain one consumer owner per item.

Target design

Recommendation: Use selected durable execution such as Inngest for required workflows; a transactional outbox is a proposed design when domain commit and event submission are separate systems.

Rollback

Stop new producers for the transferred type, account for active runs and resume old workers with compatible payloads; reconcile irreversible effects first.

Benefits and prerequisites

Checkpointed completed steps allow retry/resume without starting every step again.
Requires: Selected service/SDK integration, stable step IDs, replay-safe external effects and delivery reconciliation.
Tradeoffs: Operating a workflow service adds dependency/cost; checkpoints do not supply business exactly-once effects.

Checks before transfer

  • Crash after an external effect but before step acknowledgement; retry causes one intended business effect.
  • Domain commit with event-send failure is eventually reconciled.
  • Old scheduled/retry work is drained or deliberately transformed.
Delivery and recovery

Inspect the source

Current hosting/runtime, static assets, open-tab state, prefetched payloads and Server Function compatibility.

During coexistence

Recommendation: Keep old assets and compatible API routes; promote one built artifact per deployment and rehearse an old tab against the new deployment.

Target design

Recommendation: Use version-matched deploymentId support and infrastructure routing as needed; same-build instances share required action keys and cache coordination.

Rollback

Restore the prior artifact and routing while compatible assets/data remain; do not claim traffic rollback reverses schema or external effects.

Benefits and prerequisites

Explicit rollout handling reduces missing-chunk/navigation mismatches.
Requires: A qualified host, retained assets and tested old-client behavior.
Tradeoffs: Hard navigation can lose component state; same encryption key does not make old action IDs compatible.

Checks before transfer

  • Open an old tab, deploy, navigate and submit an old form; observe success or a controlled update path.
  • Preserved drafts survive any required full reload.
  • All instances serve matching build/deployment identifiers.

Read the migration workflow →

Setup

  1. Start in an external source repository parent in a local development workspace with runtime, identity, database and host requirements documented.
  2. Run npx create-next-app@latest my-app --ts --eslint --app --src-dir --use-npm; review prompts; enter my-app; record resolved versions. Add --no-agents-md only for a repository that explicitly opts out of generated agent files.
  3. Preserve generated agent guidance and put purpose, commands, environment names and installed-documentation navigation in README. For an explicit README-only repository policy, set agentRules:false before next dev.
  4. Confirm strict TypeScript. Install npm install zod drizzle-orm pg better-auth server-only and npm install -D drizzle-kit @types/pg dotenv; add inngest only for required durable work.
  5. Configure server-only database/auth modules and Drizzle PostgreSQL schema/config, development DATABASE_URL, auth secret/base URL and Next route/client integration.
  6. Run npx auth@latest generate; include generated schema in Drizzle paths; run npx drizzle-kit generate; review SQL; apply npx drizzle-kit migrate only to verified development DB.
  7. Install npm install -D vitest @vitejs/plugin-react jsdom @testing-library/react @testing-library/dom vite-tsconfig-paths @playwright/test; configure unit/UI environments and production Playwright webServer; run npx playwright install.
  8. Implement invalid-input, tenant ownership, session and critical browser tests. Register durable workflow endpoint/worker only if used; exercise retries and duplicate events.
  9. Rehearse migrations on fresh test DB, run checks, configure chosen host and single migration job; inspect production session/browser behavior and rollback compatibility.

Verification

Run these in the configured application; they are instructions, not recorded passes.

npm ci
npx next typegen
npx tsc --noEmit
npx eslint .
npx vitest run
npm run build
npx playwright test

Open questions

Sources