T
ToolsOx

Next.js Cheat Sheet: 100+ Code Examples, 18 Categories, and 6 Interactive Code Generators

Published: June 9, 2026Updated: June 12, 2026
Next.js Cheat Sheet & Code Tools Online - Complete Reference with Live Code Generators

This is the most comprehensive Next.js cheat sheet available online. It covers every major feature of Next.js 16 and the App Router across 18 categories and 80+ sections, with over 100 copy-ready code examples you can paste directly into your project. The cheat sheet documents Server Components, Client Components, Server Actions, Middleware, API Routes, the Layout and Template system, Metadata and SEO configuration, data fetching and caching strategies, error handling with error.tsx and not-found.tsx, image and font optimization, authentication patterns, deployment configuration, and performance best practices. Each code example includes the file path, a brief explanation of what the code does, and syntax highlighting so you can verify it visually before copying. Beyond the reference material, six interactive code generators let you produce boilerplate for routes, metadata, middleware, Next.js config, layouts, and API routes by filling in a few fields instead of writing from scratch. The entire tool runs in your browser, requires free, and works on mobile so you can look up syntax during a code review or on the go. Whether you are building your first Next.js application or maintaining a production codebase with hundreds of routes, this reference gives you every API, every pattern, and every configuration option in one searchable place without switching between the official docs and your editor.

How to Use This Next.js Cheat Sheet and Code Generators

This tool is built for speed and productivity. Whether you know the exact API name and want to confirm its signature, or you know what you want to achieve and need the right Next.js pattern, the search and navigation system handles both directions. Everything runs client-side with zero server calls, so results appear as you type and you never wait for a page load. The cheat sheet and tools tabs give you two complementary ways to access the information: the reference view for looking up existing APIs, and the generators view for creating new code from scratch.
1

Browse by category in the sidebar

All 18 categories are listed in the left sidebar: Getting Started, App Router, Pages and Routing, Layouts and Templates, Server Components, Client Components, Data Fetching, Server Actions, API Routes, Middleware, Metadata and SEO, Error Handling, Image and Asset Optimization, Font Optimization, Loading and Suspense, Authentication, Deployment, and Performance. Click any category to jump to its sections. The sidebar highlights your current position as you scroll through the cheat sheet, so you always know where you are in the reference. The scroll-spy tracking updates in real time as you move through content, making it easy to browse sequentially through a category or jump to a specific section when you need it.

2

Search across all sections instantly with Ctrl+K

Press Ctrl+K on Windows and Linux or Cmd+K on Mac to open the search dialog. Type any Next.js API name, concept, or keyword and results filter in real time as you type each character. Search works across titles, descriptions, code examples, tags, and file paths. Click a result to jump directly to that section with smooth scrolling. This is the fastest way to find a specific API or pattern when you know what you are looking for but cannot remember the exact syntax. The search index is built from all 80+ sections and 100+ code examples, so even obscure options like generateStaticParams or dynamicParams appear instantly.

3

Copy any code example with one click

Every code block has a copy button in the top-right corner. Click once and the entire code example including imports, function signatures, and export statements is on your clipboard, ready to paste into your project. Each code example also shows the file path at the top of the block so you know exactly where to place the file in your project structure. For example, if the file path shows app/blog/[slug]/page.tsx, you know to create that exact directory structure. The code examples follow Next.js best practices with proper TypeScript types, correct import paths, and the latest API signatures for Next.js 16.

4

Use the interactive code generators for boilerplate

Switch to the Tools tab to access six code generators: Route Generator creates page.tsx and layout.tsx files for any route path with proper TypeScript interfaces. Metadata Generator builds your metadata export with title, description, Open Graph tags, Twitter Card tags, and alternate URLs. Middleware Generator produces a middleware.ts file with custom matcher patterns for authentication and redirect logic. Next.js Config Generator creates next.config.ts with common settings like image domains, redirects, headers, and experimental features. Layout Generator builds nested layouts with proper type imports and the children prop pattern. API Route Generator creates route handlers with GET, POST, PUT, and DELETE methods plus request validation. Fill in a few fields and the generator outputs ready-to-use code that follows the same best practices as the cheat sheet examples.

5

Download the cheat sheet as PDF or TXT for offline use

Click the Export button in the header to download the entire cheat sheet as a PDF via browser print or as a plain text file. The PDF option preserves formatting and code highlighting when printed, making it useful as a desk reference or for sharing with teammates who prefer physical copies. The TXT option gives you the raw text of all code examples and descriptions in a single file you can keep locally for offline reference, search with grep or your text editor, or include in your project documentation. The text file format is structured with clear section headers, file paths, and code fences so it remains readable and searchable without any special software.

6

Share a link to any specific section

Each section card has a link icon that appears on hover in the top-right corner. Click it to copy a URL that jumps directly to that section using the hash fragment. This is useful for sharing a specific code example with a teammate in Slack or Discord, referencing a pattern in a pull request comment, or bookmarking a section you use frequently during development. The shared URL includes the full hash anchor so the recipient lands exactly on the section you intended, with no scrolling required. This is particularly valuable for teams that standardize on specific patterns and want to point new members to the canonical example.

Next.js App Router Architecture: How Server Components, Client Components, and Server Actions Work Together

The App Router, introduced in Next.js 13 and matured through versions 14, 15, and 16, fundamentally changed how Next.js applications are structured. Instead of the Pages Router where every file in the pages directory becomes a route, the App Router uses a nested layout system where each route segment can have its own layout.tsx, page.tsx, loading.tsx, error.tsx, and not-found.tsx files. This system enables granular control over loading states, error boundaries, and data fetching at every level of the route hierarchy, which was impossible with the single _app.tsx wrapper in the Pages Router. Server Components are the default in the App Router. Every component in a Server Component tree renders on the server and sends HTML to the client with zero JavaScript. This means your page load is faster because the browser does not need to download, parse, and execute component JavaScript for static content. Server Components can directly access databases, read files from the filesystem, and use server-only secrets because they never run in the browser. When you need interactivity like useState, useEffect, or event handlers, you opt into Client Components by adding the 'use client' directive at the top of the file. The key insight is that Client Components should be leaf nodes in your component tree: keep the server-rendered shell as large as possible and push interactivity as far down as possible. Server Actions are async functions that run exclusively on the server. They replace the pattern of creating an API route and then calling it from a client component with fetch. Instead, you define an async function with the 'use server' directive and call it directly from a form action or a client component. The framework handles the network call, serialization, and revalidation automatically. Server Actions are the recommended way to handle form submissions and data mutations in Next.js 16 because they eliminate boilerplate, provide type safety end-to-end with TypeScript, and integrate with the caching and revalidation system through revalidatePath and revalidateTag functions. The data fetching model in the App Router uses the native fetch API with extended options for caching and revalidation. By default, fetch requests are cached with cache: 'force-cache', which means the response is stored and reused across requests until explicitly invalidated. You can opt into dynamic rendering with cache: 'no-store' for data that must always be fresh, or time-based revalidation with next: { revalidate: 60 } for data that can be stale for up to 60 seconds. This replaces the getServerSideProps and getStaticProps functions from the Pages Router with a simpler, more flexible API that works the same way in Server Components and Server Actions. The framework also automatically deduplicates identical fetch requests within a single render pass, so you can call the same API in multiple components without worrying about duplicate network requests. The rendering pipeline in the App Router follows a specific order. When a request comes in, Next.js first runs the middleware function if one exists, which can redirect or rewrite the request before it reaches the route. Then it renders the layout tree from the root layout down to the leaf layout, followed by the page component. During rendering, any fetch calls with cached responses return immediately, while uncached calls trigger dynamic rendering. The resulting HTML is streamed to the client using React Suspense boundaries, which means the browser can start painting the page before all data has loaded. This streaming architecture is a significant improvement over the Pages Router, which had to wait for all data to be fetched before sending any HTML.

Complete Category Reference: All 18 Sections of the Cheat Sheet

This table lists every category in the cheat sheet with the number of code examples, what Next.js features it covers, and which App Router concepts it documents. Use this as a navigation map to find what you need quickly, or browse through each category sequentially to build a comprehensive understanding of the framework.

All 18 Cheat Sheet Categories with Code Example Counts and Feature Coverage

CategoryExamplesWhat It CoversKey Concepts
Getting Started8+Project creation, dev server, TypeScript setup, environment variables, project structurecreate-next-app, dev/build/start scripts, .env files, tsconfig.json
App Router10+File-based routing, dynamic routes, route groups, parallel routes, intercepting routesapp directory, [slug], (group), @parallel, (.intercept)
Pages and Routing8+Page components, route params, search params, route handlers, redirectspage.tsx, params, searchParams, redirect(), useRouter hook
Layouts and Templates8+Root layout, nested layouts, templates, layout nesting, shared UI patternslayout.tsx, template.tsx, children prop, metadata merging
Server Components8+Default server rendering, direct data access, async components, server-only code'use server' default, async/await, database access, fs module
Client Components6+Client-side interactivity, React hooks, event handlers, browser APIs'use client', useState, useEffect, onClick, window access
Data Fetching10+fetch API, caching strategies, revalidation, parallel requests, streaming SSRfetch(), cache options, revalidate, Promise.all, Suspense
Server Actions8+Form handling, data mutations, cache revalidation, optimistic updates, validation'use server', formData, revalidatePath, useOptimistic hook
API Routes6+Route handlers, HTTP methods, request/response, middleware chains, streamingroute.ts, GET/POST/PUT/DELETE, NextRequest, NextResponse
Middleware6+Request interception, authentication checks, redirects, matcher configurationmiddleware.ts, NextRequest, NextResponse, matcher config
Metadata and SEO8+Static metadata, dynamic metadata, Open Graph, Twitter Cards, sitemap, robotsmetadata export, generateMetadata, OG images, robots.txt
Error Handling6+Error boundaries, not-found pages, error recovery UI, global error handlingerror.tsx, not-found.tsx, global-error.tsx, reset function
Image Optimization4+Next/Image component, remote images, placeholders, responsive sizingnext/image, width/height, placeholder, blurDataURL, priority
Font Optimization4+Next/Font system, Google Fonts integration, local fonts, CSS variablesnext/font/google, next/font/local, font CSS variables
Loading and Suspense4+Loading UI, streaming SSR, Suspense boundaries, skeleton statesloading.tsx, Suspense, fallback prop, streaming rendering
Authentication6+Auth patterns, session management, protected routes, OAuth integrationNextAuth.js, session, middleware auth, route protection
Deployment4+Vercel deployment, Docker, standalone output, environment configurationnext.config.ts, output: 'standalone', Dockerfile, env vars
Performance6+Bundle analysis, code splitting, prefetching, Core Web Vitals optimizationdynamic import, lazy loading, prefetch, LCP/CLS/INP

Next.js App Router vs Pages Router: Complete Migration Guide

The Pages Router is the original Next.js routing system where every file in the pages directory automatically becomes a route. The App Router, introduced in Next.js 13, uses the app directory with a nested layout system. Both routers can coexist in the same project during migration, but the App Router is the recommended path forward for all new projects and features. Understanding the differences in routing, data fetching, layouts, and component rendering helps you decide when to migrate existing pages and how to approach the transition incrementally without breaking your production application.

Routing: flat file-based vs nested layout system

In the Pages Router, pages/about.tsx becomes the /about route and pages/blog/[id].tsx becomes /blog/:id. Each page is a standalone React component with no built-in concept of shared layout state. In the App Router, app/about/page.tsx becomes /about and app/blog/[id]/page.tsx becomes /blog/:id. The critical difference is that the App Router supports nested layouts: app/layout.tsx wraps the entire app, app/about/layout.tsx wraps only the about section, and app/blog/[id]/layout.tsx wraps each blog post. Layouts persist across client-side navigations, preserving state and avoiding unnecessary re-renders. This means a sidebar or navigation in a layout stays mounted while the page content changes, which is impossible in the Pages Router without custom workarounds.

Data fetching: getServerSideProps/getStaticProps vs fetch with cache options

The Pages Router uses getServerSideProps for server-side rendering and getStaticProps for static generation with getStaticPaths for dynamic routes. Both are special functions exported from page components that run at build time or request time. The App Router replaces these with the standard fetch API extended with Next.js-specific options: cache: 'force-cache' for static generation equivalent to getStaticProps, cache: 'no-store' for server-side rendering equivalent to getServerSideProps, and next: { revalidate: 60 } for incremental static regeneration. This approach is more composable because you can make multiple fetch calls at different caching levels within the same component, which was impossible with the single getServerSideProps or getStaticProps function per page.

API routes: pages/api handler vs app route handlers

Pages Router API routes live in pages/api/ and export a default handler function that receives Express-like req and res objects with methods like req.query, req.body, res.status(), and res.json(). App Router route handlers live in app/api/route.ts and export named functions like GET, POST, PUT, and DELETE. Route handlers use the standard Web Request and Response APIs instead of Express-like objects, making them portable to other runtimes like Cloudflare Workers and Deno. Route handlers also support streaming responses, which is useful for AI chat endpoints and large file downloads. The transition from req/res to Request/Response is straightforward: req.query becomes URL search params, req.body is parsed from the Request object, and res.json() becomes Response.json().

Layouts: single _app.tsx vs nested layout.tsx per route segment

The Pages Router has a single _app.tsx that wraps all pages and a _document.tsx for the HTML shell. You cannot have per-route layouts without using a custom Layout component and manually passing it through _app.tsx with logic that checks the router pathname. The App Router natively supports nested layouts where each folder can have its own layout.tsx that wraps all pages within that segment. Layouts receive a children prop and persist across client-side navigations, which means a sidebar, breadcrumb, or tab navigation in a layout does not re-render when the user navigates between pages in that section. This dramatically improves perceived performance and enables complex UI patterns that were impractical in the Pages Router.

Server Components: not available in Pages Router vs default rendering mode in App Router

The Pages Router does not support React Server Components. Every component in the Pages Router is a client component that ships JavaScript to the browser, even if it only renders static HTML. The App Router makes Server Components the default, meaning components render on the server and send HTML without any JavaScript. This dramatically reduces bundle size for content-heavy pages. A typical blog page in the Pages Router might send 50KB of JavaScript for the page component, while the same page in the App Router with Server Components sends zero JavaScript because the content renders to HTML on the server. You opt into Client Components only when you need interactivity, using the 'use client' directive at the top of the file.

Form handling: manual fetch calls vs Server Actions with 'use server'

In the Pages Router, handling a form submission requires creating an API route in pages/api/, then calling it with fetch from the client component, managing loading and error states manually, and refreshing data after the mutation succeeds. In the App Router with Server Actions, you define an async function with the 'use server' directive and call it directly from the form action prop or from a client component. The framework handles the network serialization, provides automatic type safety with TypeScript, and integrates cache revalidation through revalidatePath and revalidateTag. You also get optimistic UI updates with useOptimistic and pending state tracking with useFormStatus, which previously required custom hooks and state management boilerplate.

Migration strategy: incremental coexistence approach

You do not need to migrate all pages at once. The App Router and Pages Router coexist in the same project without conflicts. Keep your existing pages in the pages directory and add new features in the app directory. When you are ready to migrate a specific page, create its equivalent in the app directory and delete the old file from pages. The App Router takes precedence when both directories define the same route. The recommended migration order is: first create the root app/layout.tsx, then migrate the home page, then migrate high-traffic pages that benefit most from Server Components, then convert API routes to route handlers, and finally remove the pages directory entirely. Start with pages that have no getServerSideProps or getStaticProps because they are the simplest to migrate.

Who Uses This Next.js Cheat Sheet: Real-World Use Cases

This cheat sheet is designed for developers at every level who work with Next.js professionally. Whether you are building your first Next.js project or maintaining a large production application with hundreds of routes, the reference material and code generators save time by putting the exact syntax and patterns you need one click away. The following use cases describe the most common scenarios where developers reach for this tool and how it fits into their daily workflow.

Junior developers learning Next.js App Router for the first time

If you are transitioning from Create React App, Vite, or the Pages Router to the App Router, the Getting Started and App Router categories walk you through file conventions, route definitions, and the server/client component split step by step. The code generators produce starter files that follow Next.js best practices, so you learn the correct patterns from the beginning instead of piecing together outdated tutorials from different blog posts. Each code example includes the exact file path, which teaches you the directory structure convention that the App Router expects. The FAQ section answers the most common beginner questions like when to use Server Components versus Client Components and how data fetching works differently from useEffect.

Senior developers who need quick syntax reference during implementation

When you know the concept but forget the exact API signature or configuration option, the search function gets you the answer in seconds. Instead of opening the official Next.js docs, navigating to the right page, and scanning for the specific option you need, you press Ctrl+K, type the API name, and copy the code example. This is especially useful for less-frequently used features like middleware matcher patterns, dynamic metadata generation with generateMetadata, or Next.js config options like experimental.serverActions. The cheat sheet eliminates context switching between your editor and the documentation, which is one of the biggest productivity killers during implementation.

Development teams standardizing on Next.js patterns and onboarding new members

Share a link to a specific section when reviewing pull requests or answering questions in your team chat. Instead of writing out code snippets by hand and risking typos or inconsistencies, send a URL like toolsox.com/nextjs-cheat-sheet/nextjs-cheat-sheet-code-online#server-actions that jumps directly to the Server Actions section with copy-ready examples. This ensures everyone on the team uses consistent patterns and avoids the variations that come from each developer Googling their own solution. For onboarding, point new team members to the How to Use section first, then the deep dive on App Router architecture, and finally the best practices section for production patterns your team follows.

Interview preparation for Next.js and React roles

Technical interviews for Next.js positions often cover Server Components, the rendering pipeline, data fetching strategies, middleware, and the architectural differences between App Router and Pages Router. The deep dive section provides thorough explanations of each concept with enough detail for senior-level discussions, while the comparison section gives you clear talking points for architectural questions about migration decisions. The code examples are concise enough to write on a whiteboard or explain verbally. The FAQ section covers the most commonly asked interview questions about Next.js including the Server vs Client Component distinction, Server Actions usage, and caching strategies.

Freelance developers building client projects with Next.js

Freelancers often need to deliver working features quickly across multiple client projects. The code generators eliminate the time spent writing boilerplate for routes, metadata, middleware, and API routes. Instead of starting from a blank file, you fill in the tool name and route path, and the generator produces a complete, best-practice-compliant file you can customize for the specific project. The PDF and TXT download options let you keep a local copy for offline reference when working in environments with limited internet access, such as client offices with restricted networks or coworking spaces with unreliable WiFi.

Next.js Best Practices: Production-Ready Patterns for 2026

These patterns represent the current best practices for building production Next.js applications with the App Router in 2026. They incorporate lessons from the official Next.js documentation, the Vercel templates and examples repository, community best practices from the Next.js GitHub discussions, and real-world production deployments at scale. Following these patterns ensures your application is fast, maintainable, and ready for the feature evolution that Next.js 16 and beyond will bring.

Use Server Components by default, Client Components only when necessary

Every component in the App Router is a Server Component unless you explicitly add 'use client' to the file. This is the correct default because Server Components send zero JavaScript to the browser, reducing bundle size and improving page load performance. Only reach for Client Components when you need useState, useEffect, onClick handlers, browser APIs like window, localStorage, or sessionStorage, or third-party libraries that depend on client-side lifecycle hooks. When you do use Client Components, keep them as leaf nodes in your component tree and push interactivity as far down as possible to maximize the amount of server-rendered HTML. A common pattern is to have a Server Component parent that fetches data and passes it as props to a Client Component child that handles only the interactive UI.

Use Server Actions for mutations instead of API routes with fetch calls

Server Actions eliminate the boilerplate of creating an API route, calling it with fetch from a client component, handling loading and error states, and then revalidating the cache after a successful mutation. With Server Actions, you define an async function on the server with the 'use server' directive and call it directly from a form action or a client component. TypeScript validates the input and output types end-to-end, the framework handles network serialization, and you get automatic cache revalidation with revalidatePath and revalidateTag. Reserve API routes for external integrations like webhooks from Stripe or GitHub, third-party API proxies, and cases where you need to return non-HTML responses like images or file downloads.

Implement proper error boundaries at every route segment level

Every route segment can have its own error.tsx and not-found.tsx files. error.tsx catches runtime errors and provides a recovery UI with a reset function that retries the rendering. not-found.tsx handles the specific case when a resource is not found, which provides a more informative and helpful UI than a generic error page. For critical errors that crash the entire layout, use global-error.tsx at the root level because the root layout itself may have failed to render. Always test error states during development by intentionally throwing errors in your components, because a missing error boundary means the user sees a blank white screen instead of a helpful recovery interface that lets them try again or navigate elsewhere.

Optimize images with next/image and always define proper dimensions

Always use the next/image component instead of raw img tags in your Next.js application. It provides automatic lazy loading so images below the fold do not block page render, responsive sizing with srcSet so the browser downloads the smallest appropriate image, modern format conversion to WebP and AVIF that reduces file sizes by 30-50%, and visual stability by preventing Cumulative Layout Shift because the browser reserves space based on the width and height props. The only requirement is that you provide width and height props for remote images or use the fill prop for container-based sizing. Configure remote image domains in next.config.ts using the remotePatterns option to whitelist external image sources. For images above the fold, add the priority prop to disable lazy loading and trigger early preloading in the initial HTML response.

Configure caching and revalidation based on data freshness requirements

The default fetch cache strategy in the App Router is cache: 'force-cache', which stores the response indefinitely and serves it from the cache on subsequent requests. This is ideal for content that rarely changes like blog posts, documentation pages, and static product listings. For data that changes frequently like user dashboards, real-time analytics, or social feeds, use cache: 'no-store' for always-fresh data or next: { revalidate: 60 } for time-based revalidation that balances freshness with performance. Use revalidatePath and revalidateTag in Server Actions to purge specific cached data after mutations instead of invalidating the entire cache. Avoid the common mistake of setting cache: 'no-store' everywhere as a shortcut because it forces every request to render dynamically, eliminating the significant performance benefit of static generation and increasing your server load.

Keep middleware lightweight and use matcher to limit execution scope

Middleware runs on every request before the route handler executes, making it ideal for authentication checks, A/B testing, locale detection, and setting custom headers. However, middleware should not perform heavy computations, database queries, or external API calls because it runs on the Edge Runtime with limited APIs, a 25-second execution time limit on Vercel, and no access to Node.js-specific modules. Keep middleware as lightweight and fast as possible. Always use the matcher config in your middleware export to limit which routes trigger middleware execution, avoiding unnecessary runs on static assets, API routes that do not need auth checks, and public pages that have no conditional logic. A well-configured matcher can reduce middleware executions by 80% compared to running on every request.

Use TypeScript strictly and define proper types for route params and search params

Next.js 16 provides first-class TypeScript support with generated types for route params, search params, and metadata objects. Always define explicit TypeScript interfaces for your page props, layout props, and Server Action input parameters. This prevents runtime errors from malformed URLs and provides autocompletion in your editor. For dynamic routes like app/blog/[slug]/page.tsx, define a type like { params: Promise<{ slug: string }> } and await the params promise before using it. For search params, use { searchParams: Promise<{ q?: string; page?: string }> } and parse numeric values with Number() or parseInt() since URL search params are always strings. Strict typing also makes refactoring safer because the TypeScript compiler will catch any places where the route structure changes but the component props have not been updated.

Implement proper loading states with loading.tsx and Suspense boundaries

Every route segment can have a loading.tsx file that displays while the page content is loading. This is powered by React Suspense under the hood and gives users immediate visual feedback that something is happening, preventing the perception that the application is frozen or broken. Use skeleton UI components that match the shape of the actual content for the best user experience. For data-heavy sections that load independently, wrap them in their own Suspense boundaries with appropriate fallbacks so that fast-loading sections appear immediately while slower sections stream in progressively. This streaming architecture is one of the biggest advantages of the App Router over the Pages Router, which required the entire page to wait for all data before showing anything.

Common Next.js Errors and How to Fix Them

These are the most frequently encountered errors and pitfalls when building Next.js applications with the App Router. Each one has a clear explanation of why it happens and the correct fix. Avoiding these errors from the start saves hours of debugging time and prevents common mistakes that lead to poor performance, broken builds, or confusing behavior in production.

Error: 'use client' component tries to access server-only modules

This happens when you add 'use client' to a component that imports server-only modules like fs, path, or database clients. The fix is to split the component: keep the server-only logic in a Server Component parent that fetches the data and passes it as props to a Client Component child that handles only the interactive UI. You can also use the server-only package to throw a build-time error if a server-only module is accidentally imported in a client component, which catches the mistake before it reaches production.

Error: params is not a Promise in Next.js 16 dynamic routes

In Next.js 15 and earlier, route params were synchronous objects. In Next.js 16, params and searchParams are Promises that must be awaited before use. If you try to access params.slug directly without awaiting, you get a type error in TypeScript or undefined at runtime. The fix is to always await params: const { slug } = await params in your page component. This change enables partial prerendering and streaming because the framework can start rendering the static parts of the page while waiting for the dynamic params to resolve.

Error: Hydration mismatch from browser extensions or third-party scripts

Hydration mismatches occur when the HTML rendered on the server does not match what React expects on the client. Common causes include browser extensions that modify the DOM like Grammarly or translation tools, third-party scripts that run before hydration completes, and using Date.now() or Math.random() in Server Components which produces different values on server and client. The fix is to wrap client-only content in a Client Component that renders null on the first pass and the actual content after mounting with useEffect, or to use suppressHydrationWarning on elements that are known to differ.

Error: Missing revalidation after Server Action mutations

When you mutate data in a Server Action but forget to call revalidatePath or revalidateTag, the cached version of the page continues to show stale data even after the mutation succeeds. Users see the old content until the cache naturally expires or they hard-refresh the page. The fix is to always call revalidatePath('/path-to-page') or revalidateTag('tag-name') at the end of your Server Action to purge the specific cached routes that are affected by the mutation. Be specific with the path to avoid invalidating unrelated pages, and use tags when multiple pages share the same data source.

Error: Image optimization fails for external domains not configured in next.config.ts

The next/image component requires all external image domains to be explicitly whitelisted in your next.config.ts file using the remotePatterns configuration. If you try to render an image from an unconfigured domain, you get a 400 error from the image optimization API. The fix is to add the domain to remotePatterns in next.config.ts with the protocol, hostname, and optional pathname patterns. For example: { protocol: 'https', hostname: 'cdn.example.com', pathname: '/images/**' }. After updating the config, restart your development server for the changes to take effect.

Error: Middleware running on static assets and API routes unnecessarily

Without a matcher configuration, your middleware function runs on every single request including static JavaScript files, CSS files, images, and API routes that may not need authentication or redirect logic. This adds unnecessary latency to every request and can cause performance issues at scale. The fix is to export a config object with a matcher pattern that limits middleware execution to the routes that need it: export const config = { matcher: ['/dashboard/:path*', '/admin/:path*', '/api/protected/:path*'] }. This can reduce middleware executions by 80% or more, significantly improving response times for static assets and public pages.

Next.js Security Best Practices: Protecting Your Application

Security is critical for any web application, and Next.js provides several built-in features and patterns that help you protect your application from common vulnerabilities. These best practices cover the most important security considerations for Next.js applications in production, from Server Actions validation to headers configuration and environment variable management.

Validate and sanitize all Server Action inputs

Never trust data coming from the client, even when using Server Actions with TypeScript. Always validate and sanitize input data on the server using a validation library like Zod or Valibot before processing it. Define a schema for each Server Action input and parse the incoming data through the schema. If validation fails, return a structured error message. TypeScript types are erased at runtime, so a malicious client can send any shape of data to your Server Action. Zod schemas provide runtime validation that matches your TypeScript types, giving you type safety at compile time and data safety at runtime. This is especially important for form submissions, file uploads, and any mutation that writes to a database.

Configure security headers in next.config.ts

Add security headers to every response using the headers function in next.config.ts. Essential headers include Content-Security-Policy to prevent XSS attacks by controlling which resources the browser can load, X-Frame-Options to prevent clickjacking by blocking your pages from being embedded in iframes, X-Content-Type-Options to prevent MIME-type sniffing, Referrer-Policy to control how much referrer information is shared, and Permissions-Policy to limit which browser features your pages can access. These headers protect your users even if a vulnerability exists in your code by making exploitation harder. Configure them once in next.config.ts and they apply to all routes automatically.

Protect sensitive environment variables with server-only access

In Next.js, environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser and visible to anyone who inspects the page source. Database connection strings, API secret keys, authentication secrets, and other sensitive values must never use the NEXT_PUBLIC_ prefix. Keep them server-only by omitting the prefix, and they will only be available in Server Components, Server Actions, and API routes. Use the .env.local file for local development secrets that should not be committed to git, and use your hosting platform's environment variable settings for production secrets. The env.d.ts file can declare types for your environment variables to get autocompletion and type checking.

Implement rate limiting on API routes and Server Actions

Without rate limiting, an attacker can flood your Server Actions and API routes with requests, consuming server resources and potentially causing denial of service. Implement rate limiting using an in-memory store for single-instance deployments or a Redis-backed store for distributed deployments. A simple approach is to track request counts per IP address or per user session and reject requests that exceed a threshold within a time window. For Server Actions, you can implement rate limiting as a higher-order function that wraps your action handler. For API routes, use middleware-level rate limiting before the route handler executes.

Use CSRF protection for Server Actions that modify data

Cross-Site Request Forgery attacks trick authenticated users into submitting requests to your application from malicious websites. Next.js Server Actions include built-in CSRF protection when called from form actions because they require the Next-Action header that browsers automatically include but cross-origin requests cannot set. However, if you call Server Actions from client components using the direct function call syntax, ensure your application sets appropriate SameSite cookie attributes and considers adding a custom CSRF token for high-security operations like password changes and financial transactions.

Next.js Pro Tips: Speed Up Your Development Workflow

These tips go beyond the basics and cover productivity shortcuts, lesser-known features, and workflow optimizations that experienced Next.js developers use daily. Incorporating these into your development process can save significant time and reduce frustration when building and debugging Next.js applications.

Use parallel routes for dashboard layouts with multiple independent sections

Parallel routes let you render multiple pages in the same layout simultaneously using named slots like @analytics and @team. Each slot is a separate page component that loads independently with its own loading.tsx and error.tsx. This is perfect for dashboard layouts where different sections load data at different speeds. The URL stays the same while the individual sections stream in at their own pace. You can also use catch-all parallel routes to handle cases where one slot is missing by defining a default.tsx file that renders when the parallel route has no matching page.

Use intercepting routes for modals that have their own URL

Intercepting routes let you show a modal overlay when a user navigates to a detail page from a list, while still rendering the full page if the URL is accessed directly. Define the interceptor in app/(.)photo/[id]/page.tsx (note the dot prefix) and the full page in app/photo/[id]/page.tsx. When a user clicks a photo in the feed, the modal appears. When they refresh the page or share the URL, the full page renders. This pattern gives you the best of both worlds: the smooth UX of a modal and the SEO and shareability of a dedicated URL.

Use route groups to organize routes without affecting the URL

Route groups use parentheses in the directory name like (marketing) and (dashboard) and do not appear in the URL. app/(marketing)/about/page.tsx maps to /about, not /(marketing)/about. Use route groups to share layouts between related routes without changing the URL structure. For example, all marketing pages can share a marketing-specific header and footer through (marketing)/layout.tsx, while dashboard pages share a different layout through (dashboard)/layout.tsx, and both can coexist in the same app directory without URL conflicts.

Use generateStaticParams for dynamic routes with known paths

If you have dynamic routes like app/blog/[slug]/page.tsx where the possible slug values are known at build time, export generateStaticParams to pre-render all those pages during the build instead of rendering each one on demand at request time. This dramatically improves response times because pre-rendered pages are served from the edge cache with near-zero latency. Return an array of objects with all the param values: return [{ slug: 'getting-started' }, { slug: 'deployment' }, { slug: 'authentication' }]. For routes with thousands of possible values, combine generateStaticParams with fallback: true to pre-render the most popular pages and render the rest on demand.

Debug with Next.js Dev Overlay and server component logs

Next.js 16 includes an improved Dev Overlay that shows errors directly in the browser with clickable stack traces that point to the exact line in your source code. For Server Components, use console.log statements to debug data fetching and rendering logic because the logs appear in your terminal, not the browser console. For Client Components, use the browser developer tools and React DevTools as you would with any React application. The dev overlay also shows performance warnings when components take too long to render, helping you identify slow Server Components and data fetching bottlenecks early in development.

Use the Next.js ESLint plugin to catch errors at write time

Install eslint-config-next and it adds rules that catch common Next.js mistakes as you type: using img instead of next/image, accessing window in Server Components, missing key props in lists, incorrect metadata exports, and using Pages Router APIs in App Router files. Configure it as an extension in your .eslintrc.json and it works with any editor that supports ESLint including VS Code, WebStorm, and Neovim. The plugin saves debugging time by catching errors before they reach the browser or build step, and it helps new team members learn Next.js conventions by showing inline warnings when they write non-idiomatic code.

Frequently Asked Questions About Next.js and This Cheat Sheet

These are the most common questions developers ask about Next.js, the App Router, and how to use this cheat sheet effectively. Each answer provides a clear explanation with references to the relevant cheat sheet sections where you can find detailed code examples and deeper explanations.