Next.js Best Practices for LLMs (2026)
Last updated: January 2026 (aligned to Next.js 16.1.1)
This document summarizes the latest, authoritative best practices for building, structuring, and maintaining Next.js applications. It is intended for use by LLMs and developers to ensure code quality, maintainability, and scalability.
1. Project Structure & Organization
Use the app/ directory (App Router) for all new projects. Prefer it over the legacy pages/ directory.
Top-level folders:
app/ — Routing, layouts, pages, and route handlers
public/ — Static assets (images, fonts, etc.)
lib/ — Shared utilities, API clients, and logic
components/ — Reusable UI components
contexts/ — React context providers
styles/ — Global and modular stylesheets
hooks/ — Custom React hooks
types/ — TypeScript type definitions
Colocation: Place files (components, styles, tests) near where they are used, but avoid deeply nested structures.
Route Groups: Use parentheses (e.g., (admin)) to group routes without affecting the URL path.
Private Folders: Prefix with _ (e.g., _internal) to opt out of routing and signal implementation details.
Feature Folders: For large apps, group by feature (e.g., app/dashboard/, app/auth/).
Use src/ (optional): Place all source code in src/ to separate from config files.
2.1. Server and Client Component Integration (App Router)
Never use next/dynamic with { ssr: false } inside a Server Component. This is not supported and will cause a build/runtime error.
Correct Approach:
- If you need to use a Client Component (e.g., a component that uses hooks, browser APIs, or client-only libraries) inside a Server Component, you must:
- Move all client-only logic/UI into a dedicated Client Component (with
'use client' at the top).
- Import and use that Client Component directly in the Server Component (no need for
next/dynamic).
- If you need to compose multiple client-only elements (e.g., a navbar with a profile dropdown), create a single Client Component that contains all of them.
Example:
// Server Component
import DashboardNavbar from "@/components/DashboardNavbar";
export default async function DashboardPage() {
// ...server logic...
return (
<>
<DashboardNavbar /> {/* This is a Client Component */}
{/* ...rest of server-rendered page... */}
</>
);
}
Why:
- Server Components cannot use client-only features or dynamic imports with SSR disabled.
- Client Components can be rendered inside Server Components, but not the other way around.
Summary:
Always move client-only UI into a Client Component and import it directly in your Server Component. Never use next/dynamic with { ssr: false } in a Server Component.
2.2. Next.js 16+ async request APIs (App Router)
- Assume request-bound data is async in Server Components and Route Handlers. In Next.js 16, APIs like
cookies(), headers(), and draftMode() are async in the App Router.
- Be careful with route props:
params / searchParams may be Promises in Server Components. Prefer awaiting them instead of treating them as plain objects.
- Avoid dynamic rendering by accident: Accessing request data (cookies/headers/searchParams) opts the route into dynamic behavior. Read them intentionally and isolate dynamic parts behind
Suspense boundaries when appropriate.
2. Component Best Practices
- Component Types:
- Server Components (default): For data fetching, heavy logic, and non-interactive UI.
- Client Components: Add
'use client' at the top. Use for interactivity, state, or browser APIs.
- When to Create a Component:
- If a UI pattern is reused more than once.
- If a section of a page is complex or self-contained.
- If it improves readability or testability.
- Naming Conventions:
- Use
PascalCase for component files and exports (e.g., UserCard.tsx).
- Use
camelCase for hooks (e.g., useUser.ts).
- Use
snake_case or kebab-case for static assets (e.g., logo_dark.svg).
- Name context providers as
XyzProvider (e.g., ThemeProvider).
- File Naming:
- Match the component name to the file name.
- For single-export files, default export the component.
- For multiple related components, use an
index.ts barrel file.
- Component Location:
- Place shared components in
components/.
- Place route-specific components inside the relevant route folder.
- Props:
- Use TypeScript interfaces for props.
- Prefer explicit prop types and default values.
- Testing:
- Co-locate tests with components (e.g.,
UserCard.test.tsx).
3. Naming Conventions (General)
- Folders:
kebab-case (e.g., user-profile/)
- Files:
PascalCase for components, camelCase for utilities/hooks, kebab-case for static assets
- Variables/Functions:
camelCase
- Types/Interfaces:
PascalCase
- Constants:
UPPER_SNAKE_CASE
4. API Routes (Route Handlers)
- Prefer API Routes over Edge Functions unless you need ultra-low latency or geographic distribution.
- Location: Place API routes in
app/api/ (e.g., app/api/users/route.ts).
- HTTP Methods: Export async functions named after HTTP verbs (
GET, POST, etc.).
- Request/Response: Use the Web
Request and Response APIs. Use NextRequest/NextResponse for advanced features.
- Dynamic Segments: Use
[param] for dynamic API routes (e.g., app/api/users/[id]/route.ts).
- Validation: Always validate and sanitize input. Use libraries like
zod or yup.
- Error Handling: Return appropriate HTTP status codes and error messages.
- Authentication: Protect sensitive routes using middleware or server-side session checks.
Route Handler usage note (performance)
- Do not call your own Route Handlers from Server Components (e.g.,
fetch('/api/...')) just to reuse logic. Prefer extracting shared logic into modules (e.g., lib/) and calling it directly to avoid extra server hops.
5. General Best Practices
- TypeScript: Use TypeScript for all code. Enable
strict mode in tsconfig.json.
- ESLint & Prettier: Enforce code style and linting. Use the official Next.js ESLint config. In Next.js 16, prefer running ESLint via the ESLint CLI (not
next lint).
- Environment Variables: Store secrets in
.env.local. Never commit secrets to version control.
- In Next.js 16,
serverRuntimeConfig / publicRuntimeConfig are removed. Use environment variables instead.
NEXT_PUBLIC_ variables are inlined at build time (changing them after build won’t affect a deployed build).
- If you truly need runtime evaluation of env in a dynamic context, follow Next.js guidance (e.g., call
connection() before reading process.env).
- Testing: Use Jest, React Testing Library, or Playwright. Write tests for all critical logic and components.
- Accessibility: Use semantic HTML and ARIA attributes. Test with screen readers.
- Performance:
- Use built-in Image and Font optimization.
- Prefer Cache Components (
cacheComponents + use cache) over legacy caching patterns.
- Use Suspense and loading states for async data.
- Avoid large client bundles; keep most logic in Server Components.
- Security:
- Sanitize all user input.
- Use HTTPS in production.
- Set secure HTTP headers.
- Prefer server-side authorization for Server Actions and Route Handlers; never trust client input.
- Documentation:
- Write clear README and code comments.
- Document public APIs and components.
6. Caching & Revalidation (Next.js 16 Cache Components)
- Prefer Cache Components for memoization/caching in the App Router.
- Enable in
next.config.* via cacheComponents: true.
- Use the
use cache directive to opt a component/function into caching.
- Use cache tagging and lifetimes intentionally:
- Use
cacheTag(...) to associate cached results with tags.
- Use
cacheLife(...) to control cache lifetime (presets or configured profiles).
- Revalidation guidance:
- Prefer
revalidateTag(tag, 'max') (stale-while-revalidate) for most cases.
- The single-argument form
revalidateTag(tag) is legacy/deprecated.
- Use
updateTag(...) inside Server Actions when you need “read-your-writes” / immediate consistency.
- Avoid
unstable_cache for new code; treat it as legacy and migrate toward Cache Components.
7. Tooling updates (Next.js 16)
- Turbopack is the default dev bundler. Configure via the top-level
turbopack field in next.config.* (do not use the removed experimental.turbo).
- Typed routes are stable via
typedRoutes (TypeScript required).
Avoid Unnecessary Example Files
Do not create example/demo files (like ModalExample.tsx) in the main codebase unless the user specifically requests a live example, Storybook story, or explicit documentation component. Keep the repository clean and production-focused by default.
Always use the latest documentation and guides
- For every nextjs related request, begin by searching for the most current nextjs documentation, guides, and examples.
- Use the following tools to fetch and search documentation if they are available:
resolve_library_id to resolve the package/library name in the docs.
get_library_docs for up to date documentation.
1---2name: nextjs3description: Next.js Best Practices for LLMs (2026)4---5# Next.js Best Practices for LLMs (2026)67_Last updated: January 2026 (aligned to Next.js 16.1.1)_89This document summarizes the latest, authoritative best practices for building, structuring, and maintaining Next.js applications. It is intended for use by LLMs and developers to ensure code quality, maintainability, and scalability.1011---1213## 1. Project Structure & Organization1415- **Use the `app/` directory** (App Router) for all new projects. Prefer it over the legacy `pages/` directory.16- **Top-level folders:**17 - `app/` — Routing, layouts, pages, and route handlers18 - `public/` — Static assets (images, fonts, etc.)19 - `lib/` — Shared utilities, API clients, and logic20 - `components/` — Reusable UI components21 - `contexts/` — React context providers22 - `styles/` — Global and modular stylesheets23 - `hooks/` — Custom React hooks24 - `types/` — TypeScript type definitions25- **Colocation:** Place files (components, styles, tests) near where they are used, but avoid deeply nested structures.26- **Route Groups:** Use parentheses (e.g., `(admin)`) to group routes without affecting the URL path.27- **Private Folders:** Prefix with `_` (e.g., `_internal`) to opt out of routing and signal implementation details.2829- **Feature Folders:** For large apps, group by feature (e.g., `app/dashboard/`, `app/auth/`).30- **Use `src/`** (optional): Place all source code in `src/` to separate from config files.3132## 2.1. Server and Client Component Integration (App Router)3334**Never use `next/dynamic` with `{ ssr: false }` inside a Server Component.** This is not supported and will cause a build/runtime error.3536**Correct Approach:**3738- If you need to use a Client Component (e.g., a component that uses hooks, browser APIs, or client-only libraries) inside a Server Component, you must:39 1. Move all client-only logic/UI into a dedicated Client Component (with `'use client'` at the top).40 2. Import and use that Client Component directly in the Server Component (no need for `next/dynamic`).41 3. If you need to compose multiple client-only elements (e.g., a navbar with a profile dropdown), create a single Client Component that contains all of them.4243**Example:**4445```tsx46// Server Component47import DashboardNavbar from "@/components/DashboardNavbar";4849export default async function DashboardPage() {50 // ...server logic...51 return (52 <>53 <DashboardNavbar /> {/* This is a Client Component */}54 {/* ...rest of server-rendered page... */}55 </>56 );57}58```5960**Why:**6162- Server Components cannot use client-only features or dynamic imports with SSR disabled.63- Client Components can be rendered inside Server Components, but not the other way around.6465**Summary:**66Always move client-only UI into a Client Component and import it directly in your Server Component. Never use `next/dynamic` with `{ ssr: false }` in a Server Component.6768## 2.2. Next.js 16+ async request APIs (App Router)6970- **Assume request-bound data is async in Server Components and Route Handlers.** In Next.js 16, APIs like `cookies()`, `headers()`, and `draftMode()` are async in the App Router.71- **Be careful with route props:** `params` / `searchParams` may be Promises in Server Components. Prefer `await`ing them instead of treating them as plain objects.72- **Avoid dynamic rendering by accident:** Accessing request data (cookies/headers/searchParams) opts the route into dynamic behavior. Read them intentionally and isolate dynamic parts behind `Suspense` boundaries when appropriate.7374---7576## 2. Component Best Practices7778- **Component Types:**79 - **Server Components** (default): For data fetching, heavy logic, and non-interactive UI.80 - **Client Components:** Add `'use client'` at the top. Use for interactivity, state, or browser APIs.81- **When to Create a Component:**82 - If a UI pattern is reused more than once.83 - If a section of a page is complex or self-contained.84 - If it improves readability or testability.85- **Naming Conventions:**86 - Use `PascalCase` for component files and exports (e.g., `UserCard.tsx`).87 - Use `camelCase` for hooks (e.g., `useUser.ts`).88 - Use `snake_case` or `kebab-case` for static assets (e.g., `logo_dark.svg`).89 - Name context providers as `XyzProvider` (e.g., `ThemeProvider`).90- **File Naming:**91 - Match the component name to the file name.92 - For single-export files, default export the component.93 - For multiple related components, use an `index.ts` barrel file.94- **Component Location:**95 - Place shared components in `components/`.96 - Place route-specific components inside the relevant route folder.97- **Props:**98 - Use TypeScript interfaces for props.99 - Prefer explicit prop types and default values.100- **Testing:**101 - Co-locate tests with components (e.g., `UserCard.test.tsx`).102103## 3. Naming Conventions (General)104105- **Folders:** `kebab-case` (e.g., `user-profile/`)106- **Files:** `PascalCase` for components, `camelCase` for utilities/hooks, `kebab-case` for static assets107- **Variables/Functions:** `camelCase`108- **Types/Interfaces:** `PascalCase`109- **Constants:** `UPPER_SNAKE_CASE`110111## 4. API Routes (Route Handlers)112113- **Prefer API Routes over Edge Functions** unless you need ultra-low latency or geographic distribution.114- **Location:** Place API routes in `app/api/` (e.g., `app/api/users/route.ts`).115- **HTTP Methods:** Export async functions named after HTTP verbs (`GET`, `POST`, etc.).116- **Request/Response:** Use the Web `Request` and `Response` APIs. Use `NextRequest`/`NextResponse` for advanced features.117- **Dynamic Segments:** Use `[param]` for dynamic API routes (e.g., `app/api/users/[id]/route.ts`).118- **Validation:** Always validate and sanitize input. Use libraries like `zod` or `yup`.119- **Error Handling:** Return appropriate HTTP status codes and error messages.120- **Authentication:** Protect sensitive routes using middleware or server-side session checks.121122### Route Handler usage note (performance)123124- **Do not call your own Route Handlers from Server Components** (e.g., `fetch('/api/...')`) just to reuse logic. Prefer extracting shared logic into modules (e.g., `lib/`) and calling it directly to avoid extra server hops.125126## 5. General Best Practices127128- **TypeScript:** Use TypeScript for all code. Enable `strict` mode in `tsconfig.json`.129- **ESLint & Prettier:** Enforce code style and linting. Use the official Next.js ESLint config. In Next.js 16, prefer running ESLint via the ESLint CLI (not `next lint`).130- **Environment Variables:** Store secrets in `.env.local`. Never commit secrets to version control.131 - In Next.js 16, `serverRuntimeConfig` / `publicRuntimeConfig` are removed. Use environment variables instead.132 - `NEXT_PUBLIC_` variables are **inlined at build time** (changing them after build won’t affect a deployed build).133 - If you truly need runtime evaluation of env in a dynamic context, follow Next.js guidance (e.g., call `connection()` before reading `process.env`).134- **Testing:** Use Jest, React Testing Library, or Playwright. Write tests for all critical logic and components.135- **Accessibility:** Use semantic HTML and ARIA attributes. Test with screen readers.136- **Performance:**137 - Use built-in Image and Font optimization.138 - Prefer **Cache Components** (`cacheComponents` + `use cache`) over legacy caching patterns.139 - Use Suspense and loading states for async data.140 - Avoid large client bundles; keep most logic in Server Components.141- **Security:**142 - Sanitize all user input.143 - Use HTTPS in production.144 - Set secure HTTP headers.145 - Prefer server-side authorization for Server Actions and Route Handlers; never trust client input.146- **Documentation:**147 - Write clear README and code comments.148 - Document public APIs and components.149150## 6. Caching & Revalidation (Next.js 16 Cache Components)151152- **Prefer Cache Components for memoization/caching** in the App Router.153 - Enable in `next.config.*` via `cacheComponents: true`.154 - Use the **`use cache` directive** to opt a component/function into caching.155- **Use cache tagging and lifetimes intentionally:**156 - Use `cacheTag(...)` to associate cached results with tags.157 - Use `cacheLife(...)` to control cache lifetime (presets or configured profiles).158- **Revalidation guidance:**159 - Prefer `revalidateTag(tag, 'max')` (stale-while-revalidate) for most cases.160 - The single-argument form `revalidateTag(tag)` is legacy/deprecated.161 - Use `updateTag(...)` inside **Server Actions** when you need “read-your-writes” / immediate consistency.162- **Avoid `unstable_cache`** for new code; treat it as legacy and migrate toward Cache Components.163164## 7. Tooling updates (Next.js 16)165166- **Turbopack is the default dev bundler.** Configure via the top-level `turbopack` field in `next.config.*` (do not use the removed `experimental.turbo`).167- **Typed routes are stable** via `typedRoutes` (TypeScript required).168169# Avoid Unnecessary Example Files170171Do not create example/demo files (like ModalExample.tsx) in the main codebase unless the user specifically requests a live example, Storybook story, or explicit documentation component. Keep the repository clean and production-focused by default.172173# Always use the latest documentation and guides174175- For every nextjs related request, begin by searching for the most current nextjs documentation, guides, and examples.176- Use the following tools to fetch and search documentation if they are available:177 - `resolve_library_id` to resolve the package/library name in the docs.178 - `get_library_docs` for up to date documentation.