home / skills / vercel-labs / next-skills / next-best-practices

next-best-practices skill

/skills/next-best-practices

This skill helps you apply Next.js best practices across routing, data handling, and optimization to improve reliability and performance.

npx playbooks add skill vercel-labs/next-skills --skill next-best-practices

Review the files below or copy the command above to add this skill to your agents.

Files (20)
SKILL.md
3.9 KB
---
name: next-best-practices
description: Next.js best practices - file conventions, RSC boundaries, data patterns, async APIs, metadata, error handling, route handlers, image/font optimization, bundling
user-invocable: false
---

# Next.js Best Practices

Apply these rules when writing or reviewing Next.js code.

## File Conventions

See [file-conventions.md](./file-conventions.md) for:
- Project structure and special files
- Route segments (dynamic, catch-all, groups)
- Parallel and intercepting routes
- Middleware rename in v16 (middleware → proxy)

## RSC Boundaries

Detect invalid React Server Component patterns.

See [rsc-boundaries.md](./rsc-boundaries.md) for:
- Async client component detection (invalid)
- Non-serializable props detection
- Server Action exceptions

## Async Patterns

Next.js 15+ async API changes.

See [async-patterns.md](./async-patterns.md) for:
- Async `params` and `searchParams`
- Async `cookies()` and `headers()`
- Migration codemod

## Runtime Selection

See [runtime-selection.md](./runtime-selection.md) for:
- Default to Node.js runtime
- When Edge runtime is appropriate

## Directives

See [directives.md](./directives.md) for:
- `'use client'`, `'use server'` (React)
- `'use cache'` (Next.js)

## Functions

See [functions.md](./functions.md) for:
- Navigation hooks: `useRouter`, `usePathname`, `useSearchParams`, `useParams`
- Server functions: `cookies`, `headers`, `draftMode`, `after`
- Generate functions: `generateStaticParams`, `generateMetadata`

## Error Handling

See [error-handling.md](./error-handling.md) for:
- `error.tsx`, `global-error.tsx`, `not-found.tsx`
- `redirect`, `permanentRedirect`, `notFound`
- `forbidden`, `unauthorized` (auth errors)
- `unstable_rethrow` for catch blocks

## Data Patterns

See [data-patterns.md](./data-patterns.md) for:
- Server Components vs Server Actions vs Route Handlers
- Avoiding data waterfalls (`Promise.all`, Suspense, preload)
- Client component data fetching

## Route Handlers

See [route-handlers.md](./route-handlers.md) for:
- `route.ts` basics
- GET handler conflicts with `page.tsx`
- Environment behavior (no React DOM)
- When to use vs Server Actions

## Metadata & OG Images

See [metadata.md](./metadata.md) for:
- Static and dynamic metadata
- `generateMetadata` function
- OG image generation with `next/og`
- File-based metadata conventions

## Image Optimization

See [image.md](./image.md) for:
- Always use `next/image` over `<img>`
- Remote images configuration
- Responsive `sizes` attribute
- Blur placeholders
- Priority loading for LCP

## Font Optimization

See [font.md](./font.md) for:
- `next/font` setup
- Google Fonts, local fonts
- Tailwind CSS integration
- Preloading subsets

## Bundling

See [bundling.md](./bundling.md) for:
- Server-incompatible packages
- CSS imports (not link tags)
- Polyfills (already included)
- ESM/CommonJS issues
- Bundle analysis

## Scripts

See [scripts.md](./scripts.md) for:
- `next/script` vs native script tags
- Inline scripts need `id`
- Loading strategies
- Google Analytics with `@next/third-parties`

## Hydration Errors

See [hydration-error.md](./hydration-error.md) for:
- Common causes (browser APIs, dates, invalid HTML)
- Debugging with error overlay
- Fixes for each cause

## Suspense Boundaries

See [suspense-boundaries.md](./suspense-boundaries.md) for:
- CSR bailout with `useSearchParams` and `usePathname`
- Which hooks require Suspense boundaries

## Parallel & Intercepting Routes

See [parallel-routes.md](./parallel-routes.md) for:
- Modal patterns with `@slot` and `(.)` interceptors
- `default.tsx` for fallbacks
- Closing modals correctly with `router.back()`

## Self-Hosting

See [self-hosting.md](./self-hosting.md) for:
- `output: 'standalone'` for Docker
- Cache handlers for multi-instance ISR
- What works vs needs extra setup

## Debug Tricks

See [debug-tricks.md](./debug-tricks.md) for:
- MCP endpoint for AI-assisted debugging
- Rebuild specific routes with `--debug-build-paths`

Overview

This skill provides a concise, opinionated set of Next.js best practices covering file conventions, RSC boundaries, data patterns, runtime selection, metadata, error handling, route handlers, image/font optimization, and bundling. It is designed to be a single reference when writing or reviewing Next.js apps and when making architecture or migration decisions. The guidance targets Next.js 15+ async APIs and modern React Server Component patterns. It focuses on practical rules that reduce bugs, improve performance, and simplify maintenance.

How this skill works

The skill inspects code and architecture choices against a curated checklist: file and routing conventions, RSC/client boundaries, async usage, runtime choices, metadata generation, and common pitfalls like hydration errors and bundle incompatibilities. It flags invalid patterns (e.g., async client components, non-serializable props to RSCs), suggests alternatives (e.g., route handlers vs server actions), and recommends optimizations for images, fonts, and bundles. It also captures migration patterns and codemods related to async APIs and runtime changes. Outputs are prescriptive, actionable, and tied to concrete file-level or API-level fixes.

When to use it

  • During code reviews to enforce consistent Next.js patterns and catch anti-patterns early.
  • When designing new pages, routes, or data-fetching flows for Next.js 15+ apps.
  • Before migrating to a newer Next.js version or switching runtimes (Node.js ↔ Edge).
  • When diagnosing hydration errors, slow LCP, or unexpected bundle size increases.
  • While implementing metadata, OG image generation, or static/dynamic metadata strategies.

Best practices

  • Follow explicit file conventions: use route segments, groups, parallel routes, and reserved filenames predictably.
  • Respect RSC boundaries: keep server-only APIs and non-serializable values out of client components.
  • Prefer async patterns supported by the runtime: async params, cookies(), and headers() in Server Components.
  • Default to Node.js runtime; choose Edge only for low-latency, globally distributed needs.
  • Use next/image and next/font for optimization; preload critical subsets and set responsive sizes.
  • Avoid server-side data waterfalls—use Promise.all, Suspense, or preload to parallelize fetching.

Example use cases

  • Linting a pull request to find a client component incorrectly marked async or receiving non-serializable props.
  • Choosing between a route.ts handler and a server action for an API endpoint with file-based routing.
  • Optimizing page load by converting a large hero image to next/image with responsive sizes and blur placeholder.
  • Fixing a hydration error caused by direct use of browser APIs inside a Server Component.
  • Analyzing bundle output to replace server-incompatible packages and reduce CJS/ESM friction.

FAQ

When should I use Edge runtime instead of Node.js?

Use Edge for low-latency, globally distributed endpoints where cold-start and Node APIs are acceptable trade-offs; default to Node.js for broad compatibility and server-side features.

When should I use route handlers vs Server Actions?

Use route handlers for low-level HTTP handling and non-React logic; prefer Server Actions for tightly-coupled server calls initiated from client components where RPC-style ergonomics help.