//
Search across all documentation pages
A condensed summary of the 25 most important best practices drawn from every page in this section.
AUTH_SECRET; use npx auth secret so you get a cryptographically strong value, and give dev and prod different secrets so a leaked dev key does not compromise real sessions.auth.config.ts (no adapters, no DB drivers) separate from auth.ts where you wire in the database adapter, so middleware can call auth() under the Edge Runtime without pulling in Node-only code.Session and JWT in types/next-auth.d.ts via module augmentation so session.user.role, subscriptionStatus, etc. are typed in every Server Component, action, and middleware.create-next-app@15 (or whichever major you want) and pass --reset-preferences or explicit flags in CI so scaffolds are deterministic.cache: "auto", not force-cache, so set cache or next: { revalidate: N } on every fetch instead of assuming data is cached — silent per-request fetching is a common regression from Next 14.output: "standalone" produces a tiny self-contained server but excludes .next/static and public/ — your Dockerfile or deploy script must copy both in, otherwise the app serves 404s for assets.127.0.0.1 by default, so inside a Fargate/EKS/Docker container you must set ENV HOSTNAME=0.0.0.0 (and an explicit PORT) or the load balancer's health check never reaches the app.cacheHandler in next.config with cacheMaxMemorySize: 0.pm2 reload does a graceful rolling restart across cluster workers for zero-downtime deploys; pm2 restart kills all workers and produces a visible outage window./_next/static/ and public/ directly with Cache-Control: public, immutable, max-age=31536000 so static assets bypass Node entirely and survive app restarts..next/server/ and .next/static/ but keep .next/cache/ so ISR and build caches survive; a blunt rm -rf .next wipes them and forces full rebuilds plus cold ISR regeneration.globalThis in development so hot-reload does not open a new connection pool every save — without this, Postgres refuses new connections within minutes and the dev server hangs..env, not .env.local, so prisma generate and migrate fail silently or with confusing messages if the URL only lives in .env.local.revalidatePath (or revalidateTag) afterward, otherwise the cached Server Component render keeps serving stale data and the UI appears to not update.prisma migrate deploy (non-interactive, applies committed migrations); prisma migrate dev is interactive, can reset the database, and must never run against production or staging.gray-matter returns whatever keys happen to be in the file, so run the result through a Zod schema to catch typos and missing required fields at import time instead of shipping broken docs.<Tag /> parses as JSX, so wrap code samples in backticks or escape the braces — otherwise MDX throws build errors on prose that looks fine in plain Markdown.events.createUser, not during checkout, so there is no double-click race that produces duplicate customers and the user has a Stripe ID the moment they exist.stripe.webhooks.constructEvent(rawBody, sig, whsec); parsing JSON without verifying the signature lets anyone mutate your database via forged POSTs.export const runtime = "nodejs" on the Stripe webhook route because crypto.createHmac is not available on the Edge Runtime, and use a distinct STRIPE_WEBHOOK_SECRET per environment or signatures silently fail.tailwind.config.js — theme tokens, variants, and plugins are declared in globals.css via @theme and @custom-variant, and the PostCSS plugin is @tailwindcss/postcss, not the old tailwindcss package.cn() (clsx + tailwind-merge), so concatenate classes through cn(...) instead of template strings — otherwise consumer prop overrides randomly lose to defaults.env array, so unlisted vars are undefined at build time; declare every build-time env var explicitly or cache keys will not reflect your configuration.node_modules, so when consuming internal monorepo packages like @repo/ui add them to transpilePackages in next.config.ts or imports error at build.workspace:* protocol is only understood by pnpm, yarn, and bun — npm does not parse it; set "packageManager": "pnpm@…" in root package.json and use --frozen-lockfile in CI to avoid drift.