opinionated-nextjs-patterns
Opinionated Next.js 16 Patterns
Implementation-pattern reference for Next.js 16 (App Router) codebases that want a single, opinionated architecture. Contains 50 rules across 8 categories, prioritised by execution-lifecycle cascade impact — authorization and (optional) tenant modeling first, then the request boundary, server fetching, mutations, client boundaries, architecture, and UI conventions.
The rules are backend-agnostic in principle but use Supabase as the concrete example. Each rule teaches the transferable idea (e.g. "authorize at the data layer", "read through a typed repository"); where the backend genuinely matters, a *Transferable:* note explains the pattern for other stores (Drizzle, Prisma). The structure is a Turbo monorepo with @app/* packages you own — built on canonical libraries (next-safe-action, @supabase/ssr, @tanstack/react-query, react-hook-form + zod, shadcn/ui, next-intl, pino), not a vendored starter kit.
When to Apply
Reach for these rules when:
- Writing new code — pages, layouts, server actions, route handlers,
proxy.ts, feature packages, client components, hooks, the data-access package, SQL/migrations, forms. - Reviewing a PR — authorization slips (privileged client without a guard, missing
'server-only'), waterfalls (sequential awaits, client-fetching server data), drift (hand-edited generated types, deep package imports, hardcoded i18n strings). - Refactoring — moving code between
apps/webandpackages/*, splitting actions and services, lifting'use client'boundaries, replacing raw queries with a typed data-access factory, swapping a backend behind the data-access package. - Designing a feature — choosing the right client (request-scoped vs privileged vs browser), deciding action vs route handler, planning the form/server-action contract, scoping a tenant (if multi-tenant).
- Onboarding — understanding why the codebase looks the way it does, with concrete, transferable examples.