Next.js App Router architecture — Server Components, routing, performance, SEO, and API patterns.
Patterns for building Next.js applications with the App Router.
Features live in features/ as self-contained modules, separate from app/ routes:
features/{name}/
actions/ # Server Actions ('use server')
components/ # Feature UI + co-located .test.tsx files
hooks/ # Custom React hooks (form logic, etc.)
queries/ # React Query hooks (queries + mutations)
schemas/ # Zod validation schemas + .test.ts
types/ # TypeScript types
index.ts # Barrel exports (public API)
Routes in app/ import from features via barrel: import { TaskCard } from '@/features/tasks'
Key rules:
lib/components/(marketing) and (app) separate layouts without affecting URLsFull directory tree and "Adding a New Feature" guide → project-structure.md
pnpm test:ci)pnpm test:e2e)pnpm check-types)Default to Server Components. Use "use client" ONLY when you need:
| Need | Use Client Component |
|---|---|
| Event handlers | onClick, onChange, onSubmit |
| React hooks | useState, useEffect, useReducer, useContext |
| Browser APIs | localStorage, window, navigator |
| Third-party libraries | Requiring client features |
children to Client Components to avoid turning the entire tree client-side'use client' provider wrapper, use it in a Server Component layout'use client' file| Use Case | Prefer |
|---|---|
| In-app form handling, mutations, optimistic UI | Server Actions |
| Public APIs, webhooks, cross-app consumption | Route Handlers |
Always use next/image. Required: alt, sizes for responsive. Use priority for above-fold. Static imports get automatic blur placeholder.
Use next/font (Google or local). Configure CSS variables. Use display: 'swap'.
Use loading.tsx for route-level loading. Use <Suspense> for component-level streaming.
Use next/dynamic for heavy components. Set ssr: false for client-only components.
metadata object from layout.tsx or page.tsxgenerateMetadata for dynamic pagessitemap.ts, robots.ts, opengraph-image.tsxgenerateStaticParams for static generation of dynamic routes(marketing) for organizational grouping without URL impact@modal for simultaneous renderingnot-found.tsx and error.tsx(.)photo/[id] pattern