app/preload-resources.tsx 'use client'

import ReactDOM from 'react-dom'

export function PreloadResources() {
  ReactDOM.preload('...', { as: '...' })
  ReactDOM.preconnect('...', { crossOrigin: '...' })
  ReactDOM.prefetchDNS('...')

  return null
}
<link rel="preload">
Start loading a resource early in the page rendering (browser) lifecycle. MDN Docs.
 ReactDOM.preload(href: string, options: { as: string })
<head> output <link rel="preload" href="..." as="..." />
<link rel="preconnect">
Preemptively initiate a connection to an origin. MDN Docs.
 ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<head> output <link rel="preconnect" href="..." crossorigin />
<link rel="dns-prefetch">


<link rel="dns-prefetch">
Attempt to resolve a domain name before resources get requested. MDN Docs.
 ReactDOM.prefetchDNS(href: string)
<head> output <link rel="dns-prefetch" href="..." />
Good to know:
These methods are currently only supported in Client Components, which are still Server Side Rendered on initial page load.
Next.js in-built features such as next/font, next/image and next/script automatically handle relevant resource hints.
React 18.3 does not yet include type definitions for ReactDOM.preload, ReactDOM.preconnect, and ReactDOM.preconnectDNS. You can use // @ts-ignore as a temporary solution to avoid type errors.
Types
You can add type safety to your metadata by using the Metadata type. If you are using the built-in TypeScript plugin in your IDE, you do not need to manually add the type, but you can still explicitly add it if you want.
metadata object


metadata object
 import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Next.js',
}
generateMetadata function
Regular function
 import type { Metadata } from 'next'

export function generateMetadata(): Metadata {
  return {
    title: 'Next.js',
  }
}
Async function
 import type { Metadata } from 'next'

export async function generateMetadata(): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}
With segment props
 import type { Metadata } from 'next'

type Props = {
  params: { id: string }
  searchParams: { [key: string]: string | string[] | undefined }
}

export function generateMetadata({ params, searchParams }: Props): Metadata {
  return {
    title: 'Next.js',


return {
    title: 'Next.js',
  }
}

export default function Page({ params, searchParams }: Props) {}
With parent metadata
 import type { Metadata, ResolvingMetadata } from 'next'

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  return {
    title: 'Next.js',
  }
}
JavaScript Projects
For JavaScript projects, you can use JSDoc to add type safety.
 /** @type {import("next").Metadata} */
export const metadata = {
  title: 'Next.js',
}
Version History
VersionChangesv13.2.0metadata and generateMetadata introduced.


generateStaticParamsThe generateStaticParams function can be used in combination with dynamic route segments to statically generate routes at build time instead of on-demand at request time.
app/blog/[slug]/page.js // Return a list of `params` to populate the [slug] dynamic segment
export async function generateStaticParams() {
  const posts = await fetch('https://.../posts').then((res) => res.json())

  return posts.map((post) => ({
    slug: post.slug,
  }))
}

// Multiple versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
export default function Page({ params }) {
  const { slug } = params
  // ...
}
Good to know
You can use the dynamicParams segment config option to control what happens when a dynamic segment is visited that was not generated with generateStaticParams.


During next dev, generateStaticParams will be called when you navigate to a route.
During next build, generateStaticParams runs before the corresponding Layouts or Pages are generated.
During revalidation (ISR), generateStaticParams will not be called again.
generateStaticParams replaces the getStaticPaths function in the Pages Router.
Parameters
options.params (optional)
If multiple dynamic segments in a route use generateStaticParams, the child generateStaticParams function is executed once for each set of params the parent generates.
The params object contains the populated params from the parent generateStaticParams, which can be used to generate the params in a child segment.
Returns
generateStaticParams should return an array of objects where each object represents the populated dynamic segments of a single route.
Each property in the object is a dynamic segment to be filled in for the route.


Each property in the object is a dynamic segment to be filled in for the route.
The properties name is the segment's name, and the properties value is what that segment should be filled in with.
Example RoutegenerateStaticParams Return Type/product/[id]{ id: string }[]/products/[category]/[product]{ category: string, product: string }[]/products/[...slug]{ slug: string[] }[]
Single Dynamic Segment
app/product/[id]/page.tsx export function generateStaticParams() {
  return [{ id: '1' }, { id: '2' }, { id: '3' }]
}

// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /product/1
// - /product/2
// - /product/3


// - /product/2
// - /product/3
export default function Page({ params }: { params: { id: string } }) {
  const { id } = params
  // ...
}
Multiple Dynamic Segments
app/products/[category]/[product]/page.tsx export function generateStaticParams() {
  return [
    { category: 'a', product: '1' },
    { category: 'b', product: '2' },
    { category: 'c', product: '3' },
  ]
}

// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /products/a/1
// - /products/b/2
// - /products/c/3
export default function Page({
  params,
}: {
  params: { category: string; product: string }


params,
}: {
  params: { category: string; product: string }
}) {
  const { category, product } = params
  // ...
}
Catch-all Dynamic Segment
app/product/[...slug]/page.tsx export function generateStaticParams() {
  return [{ slug: ['a', '1'] }, { slug: ['b', '2'] }, { slug: ['c', '3'] }]
}

// Three versions of this page will be statically generated
// using the `params` returned by `generateStaticParams`
// - /product/a/1
// - /product/b/2
// - /product/c/3
export default function Page({ params }: { params: { slug: string[] } }) {
  const { slug } = params
  // ...
}
Examples
Multiple Dynamic Segments in a Route


// ...
}
Examples
Multiple Dynamic Segments in a Route
You can generate params for dynamic segments above the current layout or page, but not below. For example, given the app/products/[category]/[product] route:
app/products/[category]/[product]/page.js can generate params for both [category] and [product].
app/products/[category]/layout.js can only generate params for [category].
There are two approaches to generating params for a route with multiple dynamic segments:
Generate params from the bottom up
Generate multiple dynamic segments from the child route segment.
app/products/[category]/[product]/page.tsx // Generate segments for both [category] and [product]
export async function generateStaticParams() {
  const products = await fetch('https://.../products').then((res) => res.json())

  return products.map((product) => ({
    category: product.category.slug,


return products.map((product) => ({
    category: product.category.slug,
    product: product.id,
  }))
}

export default function Page({
  params,
}: {
  params: { category: string; product: string }
}) {
  // ...
}
Generate params from the top down
Generate the parent segments first and use the result to generate the child segments.
app/products/[category]/layout.tsx // Generate segments for [category]
export async function generateStaticParams() {
  const products = await fetch('https://.../products').then((res) => res.json())

  return products.map((product) => ({
    category: product.category.slug,
  }))
}

export default function Layout({ params }: { params: { category: string } }) {
  // ...
}


// ...
}
A child route segment's generateStaticParams function is executed once for each segment a parent generateStaticParams generates.
The child generateStaticParams function can use the params returned from the parent generateStaticParams function to dynamically generate its own segments.
app/products/[category]/[product]/page.tsx // Generate segments for [product] using the `params` passed from
// the parent segment's `generateStaticParams` function
export async function generateStaticParams({
  params: { category },
}: {
  params: { category: string }
}) {
  const products = await fetch(
    `https://.../products?category=${category}`
  ).then((res) => res.json())

  return products.map((product) => ({
    product: product.id,
  }))
}

export default function Page({
  params,
}: {


}))
}

export default function Page({
  params,
}: {
  params: { category: string; product: string }
}) {
  // ...
}
Good to know: When rendering a route, Next.js will automatically deduplicate fetch requests for the same data across generateMetadata, generateStaticParams, Layouts, Pages, and Server Components. React cache can be used if fetch is unavailable.
Version History
VersionChangesv13.0.0generateStaticParams introduced.


headersThe headers function allows you to read the HTTP incoming request headers from a Server Component.
headers()
This API extends the Web Headers API. It is read-only, meaning you cannot set / delete the outgoing request headers.
app/page.tsx import { headers } from 'next/headers'

export default function Page() {
  const headersList = headers()
  const referer = headersList.get('referer')

  return
Referer: {referer}

}
Good to know:
headers() is a Dynamic Function whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into dynamic rendering at request time.
API Reference
 const headersList = headers()
Parameters
headers does not take any parameters.
Returns
headers returns a read-only Web Headers object.
Headers.entries(): Returns an iterator allowing to go through all key/value pairs contained in this object.


Headers.entries(): Returns an iterator allowing to go through all key/value pairs contained in this object.
Headers.forEach(): Executes a provided function once for each key/value pair in this Headers object.
Headers.get(): Returns a String sequence of all the values of a header within a Headers object with a given name.
Headers.has(): Returns a boolean stating whether a Headers object contains a certain header.
Headers.keys(): Returns an iterator allowing you to go through all keys of the key/value pairs contained in this object.
Headers.values(): Returns an iterator allowing you to go through all values of the key/value pairs contained in this object.
Examples
Usage with Data Fetching
headers() can be used in combination with Suspense for Data Fetching.
app/page.js import { headers } from 'next/headers'

async function getUser() {
  const headersInstance = headers()
  const authorization = headersInstance.get('authorization')
  // Forward the authorization header


const authorization = headersInstance.get('authorization')
  // Forward the authorization header
  const res = await fetch('...', {
    headers: { authorization },
  })
  return res.json()
}

export default async function UserPage() {
  const user = await getUser()
  return <h1>{user.name}</h1>
}
Version History
VersionChangesv13.0.0headers introduced.


ImageResponseThe ImageResponse constructor allows you to generate dynamic images using JSX and CSS. This is useful for generating social media images such as Open Graph images, Twitter cards, and more.
The following options are available for ImageResponse:
 import { ImageResponse } from 'next/server'

new ImageResponse(
  element: ReactElement,
  options: {
    width?: number = 1200
    height?: number = 630
    emoji?: 'twemoji' | 'blobmoji' | 'noto' | 'openmoji' = 'twemoji',
    fonts?: {
      name: string,
      data: ArrayBuffer,
      weight: number,
      style: 'normal' | 'italic'
    }[]
    debug?: boolean = false

    // Options that will be passed to the HTTP response
    status?: number = 200
    statusText?: string


status?: number = 200
    statusText?: string
    headers?: Record<string, string>
  },
)
Supported CSS Properties
Please refer to Satori’s documentation for a list of supported HTML and CSS features.
Version History
VersionChangesv13.3.0ImageResponse can be imported from next/server.v13.0.0ImageResponse introduced via @vercel/og package.


NextRequestNextRequest extends the Web Request API with additional convenience methods.
cookies
Read or mutate the Set-Cookie header of the request.
set(name, value)
Given a name, set a cookie with the given value on the request.
 // Given incoming request /home
// Set a cookie to hide the banner
// request will have a `Set-Cookie:show-banner=false;path=/home` header
request.cookies.set('show-banner', 'false')
get(name)
Given a cookie name, return the value of the cookie. If the cookie is not found, undefined is returned. If multiple cookies are found, the first one is returned.
 // Given incoming request /home
// { name: 'show-banner', value: 'false', Path: '/home' }
request.cookies.get('show-banner')
getAll()


request.cookies.get('show-banner')
getAll()
Given a cookie name, return the values of the cookie. If no name is given, return all cookies on the request.
 // Given incoming request /home
// [
//   { name: 'experiments', value: 'new-pricing-page', Path: '/home' },
//   { name: 'experiments', value: 'winter-launch', Path: '/home' },
// ]
request.cookies.getAll('experiments')
// Alternatively, get all cookies for the request
request.cookies.getAll()
delete(name)
Given a cookie name, delete the cookie from the request.
 // Returns true for deleted, false is nothing is deleted
request.cookies.delete('experiments')
has(name)
Given a cookie name, return true if the cookie exists on the request.
 // Returns true if cookie exists, false if it does not
request.cookies.has('experiments')
clear()


request.cookies.has('experiments')
clear()
Remove the Set-Cookie header from the request.
 request.cookies.clear()
nextUrl
Extends the native URL API with additional convenience methods, including Next.js specific properties.
 // Given a request to /home, pathname is /home
request.nextUrl.pathname
// Given a request to /home?name=lee, searchParams is { 'name': 'lee' }
request.nextUrl.searchParams
Version History
VersionChangesv13.0.0useSearchParams introduced.


NextResponseNextResponse extends the Web Response API with additional convenience methods.
cookies
Read or mutate the Set-Cookie header of the response.
set(name, value)
Given a name, set a cookie with the given value on the response.
 // Given incoming request /home
let response = NextResponse.next()
// Set a cookie to hide the banner
response.cookies.set('show-banner', 'false')
// Response will have a `Set-Cookie:show-banner=false;path=/home` header
return response
get(name)
Given a cookie name, return the value of the cookie. If the cookie is not found, undefined is returned. If multiple cookies are found, the first one is returned.
 // Given incoming request /home
let response = NextResponse.next()
// { name: 'show-banner', value: 'false', Path: '/home' }
response.cookies.get('show-banner')
getAll()


response.cookies.get('show-banner')
getAll()
Given a cookie name, return the values of the cookie. If no name is given, return all cookies on the response.
 // Given incoming request /home
let response = NextResponse.next()
// [
//   { name: 'experiments', value: 'new-pricing-page', Path: '/home' },
//   { name: 'experiments', value: 'winter-launch', Path: '/home' },
// ]
response.cookies.getAll('experiments')
// Alternatively, get all cookies for the response
response.cookies.getAll()
delete(name)
Given a cookie name, delete the cookie from the response.
 // Given incoming request /home
let response = NextResponse.next()
// Returns true for deleted, false is nothing is deleted
response.cookies.delete('experiments')
json()
Produce a response with the given JSON body.


json()
Produce a response with the given JSON body.
app/api/route.ts import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 })
}
redirect()
Produce a response that redirects to a URL.
 import { NextResponse } from 'next/server'

return NextResponse.redirect(new URL('/new', request.url))
The URL can be created and modified before being used in the NextResponse.redirect() method. For example, you can use the request.nextUrl property to get the current URL, and then modify it to redirect to a different URL.
 import { NextResponse } from 'next/server'

// Given an incoming request...
const loginUrl = new URL('/login', request.url)
// Add ?from=/incoming-url to the /login URL


// Add ?from=/incoming-url to the /login URL
loginUrl.searchParams.set('from', request.nextUrl.pathname)
// And redirect to the new URL
return NextResponse.redirect(loginUrl)
rewrite()
Produce a response that rewrites (proxies) the given URL while preserving the original URL.
 import { NextResponse } from 'next/server'

// Incoming request: /about, browser shows /about
// Rewritten request: /proxy, browser shows /about
return NextResponse.rewrite(new URL('/proxy', request.url))
next()
The next() method is useful for Middleware, as it allows you to return early and continue routing.
 import { NextResponse } from 'next/server'

return NextResponse.next()
You can also forward headers when producing the response:
 import { NextResponse } from 'next/server'

// Given an incoming request...


import { NextResponse } from 'next/server'

// Given an incoming request...
const newHeaders = new Headers(request.headers)
// Add a new header
newHeaders.set('x-version', '123')
// And produce a response with the new headers
return NextResponse.next({
  request: {
    // New request headers
    headers: newHeaders,
  },
})


notFoundThe notFound function allows you to render the not-found file within a route segment as well as inject a <meta name="robots" content="noindex" /> tag.
notFound()
Invoking the notFound() function throws a NEXT_NOT_FOUND error and terminates rendering of the route segment in which it was thrown. Specifying a not-found file allows you to gracefully handle such errors by rendering a Not Found UI within the segment.
app/user/[id]/page.js import { notFound } from 'next/navigation'

async function fetchUser(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({ params }) {
  const user = await fetchUser(params.id)

  if (!user) {
    notFound()
  }

  // ...
}


notFound()
  }

  // ...
}
Good to know: notFound() does not require you to use return notFound() due to using the TypeScript never type.
Version History
VersionChangesv13.0.0notFound introduced.


redirectThe redirect function allows you to redirect the user to another URL. redirect can be used in Server Components, Client Components, Route Handlers, and Server Actions.
If you need to redirect to a 404, use the notFound function instead.
Parameters
The redirect function accepts two arguments:
 redirect(path, type)
ParameterTypeDescriptionpathstringThe URL to redirect to. Can be a relative or absolute path.type'replace' (default) or 'push' (default in Server Actions)The type of redirect to perform.
By default, redirect will use push (adding a new entry to the browser history stack) in Server Actions) and replace (replacing the current URL in the browser history stack) everywhere else. You can override this behavior by specifying the type parameter.
The type parameter has no effect when used in Server Components.
Returns
redirect does not return any value.
Example


Returns
redirect does not return any value.
Example
Invoking the redirect() function throws a NEXT_REDIRECT error and terminates rendering of the route segment in which it was thrown.
app/team/[id]/page.js import { redirect } from 'next/navigation'

async function fetchTeam(id) {
  const res = await fetch('https://...')
  if (!res.ok) return undefined
  return res.json()
}

export default async function Profile({ params }) {
  const team = await fetchTeam(params.id)
  if (!team) {
    redirect('/login')
  }

  // ...
}
Good to know: redirect does not require you to use return redirect() as it uses the TypeScript never type.
VersionChangesv13.0.0redirect introduced.


revalidatePathrevalidatePath allows you to revalidate data associated with a specific path. This is useful for scenarios where you want to update your cached data without waiting for a revalidation period to expire.
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidatePath } from 'next/cache'

export async function GET(request: NextRequest) {
  const path = request.nextUrl.searchParams.get('path') || '/'
  revalidatePath(path)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}
Good to know:
revalidatePath is available in both Node.js and Edge runtimes.


Good to know:
revalidatePath is available in both Node.js and Edge runtimes.
revalidatePath will revalidate all segments under a dynamic route segment. For example, if you have a dynamic segment /product/[id] and you call revalidatePath('/product/[id]'), then all segments under /product/[id] will be revalidated as requested.
revalidatePath only invalidates the cache when the path is next visited. This means calling revalidatePath with a dynamic route segment will not immediately trigger many revalidations at once. The invalidation only happens when the path is next visited.
Parameters
 revalidatePath(path: string): void;
path: A string representing the filesystem path associated with the data you want to revalidate. This is not the literal route segment (e.g. /product/123) but instead the path on the filesystem (e.g. /product/[id]).
Returns


Returns
revalidatePath does not return any value.
Examples
Node.js Runtime
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidatePath } from 'next/cache'

export async function GET(request: NextRequest) {
  const path = request.nextUrl.searchParams.get('path') || '/'
  revalidatePath(path)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}
Edge Runtime
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidatePath } from 'next/cache'

export const runtime = 'edge'

export async function GET(request: NextRequest) {
  const path = request.nextUrl.searchParams.get('path') || '/'
  revalidatePath(path)


revalidatePath(path)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}


revalidateTagrevalidateTag allows you to revalidate data associated with a specific cache tag. This is useful for scenarios where you want to update your cached data without waiting for a revalidation period to expire.
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'

export async function GET(request: NextRequest) {
  const tag = request.nextUrl.searchParams.get('tag')
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}
Good to know:
revalidateTag is available in both Node.js and Edge runtimes.
Parameters
 revalidateTag(tag: string): void;
tag: A string representing the cache tag associated with the data you want to revalidate.
You can add tags to fetch as follows:


You can add tags to fetch as follows:
 fetch(url, { next: { tags: [...] } });
Returns
revalidateTag does not return any value.
Examples
Node.js Runtime
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'

export async function GET(request: NextRequest) {
  const tag = request.nextUrl.searchParams.get('tag')
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}
Edge Runtime
app/api/revalidate/route.ts import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'

export const runtime = 'edge'

export async function GET(request: NextRequest) {


export async function GET(request: NextRequest) {
  const tag = request.nextUrl.searchParams.get('tag')
  revalidateTag(tag)
  return NextResponse.json({ revalidated: true, now: Date.now() })
}


useParamsuseParams is a Client Component hook that lets you read a route's dynamic params filled in by the current URL.
app/example-client-component.tsx 'use client'

import { useParams } from 'next/navigation'

export default function ExampleClientComponent() {
  const params = useParams()

  // Route -> /shop/[tag]/[item]
  // URL -> /shop/shoes/nike-air-max-97
  // `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
  console.log(params)

  return <></>
}
Parameters
 const params = useParams()
useParams does not take any parameters.
Returns
useParams returns an object containing the current route's filled in dynamic parameters.
Each property in the object is an active dynamic segment.


Each property in the object is an active dynamic segment.
The properties name is the segment's name, and the properties value is what the segment is filled in with.
The properties value will either be a string or array of string's depending on the type of dynamic segment.
If the route contains no dynamic parameters, useParams returns an empty object.
If used in pages, useParams will return null.
For example:
RouteURLuseParams()app/shop/page.js/shopnullapp/shop/[slug]/page.js/shop/1{ slug: '1' }app/shop/[tag]/[item]/page.js/shop/1/2{ tag: '1', item: '2' }app/shop/[...slug]/page.js/shop/1/2{ slug: ['1', '2'] }
Version History
VersionChangesv13.3.0useParams introduced.


usePathnameusePathname is a Client Component hook that lets you read the current URL's pathname.
app/example-client-component.tsx 'use client'

import { usePathname } from 'next/navigation'

export default function ExampleClientComponent() {
  const pathname = usePathname()
  return
Current pathname: {pathname}

}
usePathname intentionally requires using a Client Component. It's important to note Client Components are not a de-optimization. They are an integral part of the Server Components architecture.
For example, a Client Component with usePathname will be rendered into HTML on the initial page load. When navigating to a new route, this component does not need to be re-fetched. Instead, the component is downloaded once (in the client JavaScript bundle), and re-renders based on the current state.
Good to know:


Good to know:
Reading the current URL from a Server Component is not supported. This design is intentional to support layout state being preserved across page navigations.
Compatibility mode:
usePathname can return null when a fallback route is being rendered or when a pages directory page has been automatically statically optimized by Next.js and the router is not ready.
Next.js will automatically update your types if it detects both an app and pages directory in your project.
Parameters
 const pathname = usePathname()
usePathname does not take any parameters.
Returns
usePathname returns a string of the current URL's pathname. For example:
URLReturned value/'/'/dashboard'/dashboard'/dashboard?v=2'/dashboard'/blog/hello-world'/blog/hello-world'
Examples
Do something in response to a route change
app/example-client-component.tsx 'use client'

import { usePathname, useSearchParams } from 'next/navigation'


import { usePathname, useSearchParams } from 'next/navigation'

function ExampleClientComponent() {
  const pathname = usePathname()
  const searchParams = useSearchParams()
  useEffect(() => {
    // Do something here...
  }, [pathname, searchParams])
}
VersionChangesv13.0.0usePathname introduced.


useReportWebVitals
The useReportWebVitals hook allows you to report Core Web Vitals, and can be used in combination with your analytics service.
app/_components/web-vitals.js 'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    console.log(metric)
  })
}app/layout.js import { WebVitals } from './_components/web-vitals'

export default function Layout({ children }) {
  return (
    <html>
      <body>
        <WebVitals />
        {children}
      </body>
    </html>
  )
}


{children}
      </body>
    </html>
  )
}
Since the useReportWebVitals hook requires the "use client" directive, the most performant approach is to create a separate component that the root layout imports. This confines the client boundary exclusively to the WebVitals component.
useReportWebVitals
The metric object passed as the hook's argument consists of a number of properties:
id: Unique identifier for the metric in the context of the current page load
name: The name of the performance metric. Possible values include names of Web Vitals metrics (TTFB, FCP, LCP, FID, CLS) specific to a web application.
delta: The difference between the current value and the previous value of the metric. The value is typically in milliseconds and represents the change in the metric's value over time.


entries: An array of Performance Entries associated with the metric. These entries provide detailed information about the performance events related to the metric.
navigationType: Indicates the type of navigation that triggered the metric collection. Possible values include "navigate", "reload", "back_forward", and "prerender".
rating: A qualitative rating of the metric value, providing an assessment of the performance. Possible values are "good", "needs-improvement", and "poor". The rating is typically determined by comparing the metric value against predefined thresholds that indicate acceptable or suboptimal performance.
value: The actual value or duration of the performance entry, typically in milliseconds. The value provides a quantitative measure of the performance aspect being tracked by the metric. The source of the value depends on the specific metric being measured and can come from various Performance APIs.
Web Vitals
Web Vitals are a set of useful metrics that aim to capture the user


Web Vitals
Web Vitals are a set of useful metrics that aim to capture the user
experience of a web page. The following web vitals are all included:
Time to First Byte (TTFB)
First Contentful Paint (FCP)
Largest Contentful Paint (LCP)
First Input Delay (FID)
Cumulative Layout Shift (CLS)
Interaction to Next Paint (INP)
You can handle all the results of these metrics using the name property.
app/components/web-vitals.tsx 'use client'

import { useReportWebVitals } from 'next/web-vitals'

export function WebVitals() {
  useReportWebVitals((metric) => {
    switch (metric.name) {
      case 'FCP': {
        // handle FCP results
      }
      case 'LCP': {
        // handle LCP results


}
      case 'LCP': {
        // handle LCP results
      }
      // ...
    }
  })
}
Usage on Vercel
Vercel Speed Insights are automatically configured on Vercel deployments, and don't require the use of useReportWebVitals. This hook is useful in local development, or if you're using a different analytics service.
Sending results to external systems
You can send results to any endpoint to measure and track
real user performance on your site. For example:
 useReportWebVitals((metric) => {
  const body = JSON.stringify(metric)
  const url = 'https://example.com/analytics'

  // Use `navigator.sendBeacon()` if available, falling back to `fetch()`.
  if (navigator.sendBeacon) {
    navigator.sendBeacon(url, body)
  } else {


navigator.sendBeacon(url, body)
  } else {
    fetch(url, { body, method: 'POST', keepalive: true })
  }
})
Good to know: If you use Google Analytics, using the
id value can allow you to construct metric distributions manually (to calculate percentiles,
etc.)
 useReportWebVitals(metric => {
  // Use `window.gtag` if you initialized Google Analytics as this example:
  // https://github.com/vercel/next.js/blob/canary/examples/with-google-analytics/pages/_app.js
  window.gtag('event', metric.name, {
    value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value), // values must be integers
    event_label: metric.id, // id unique to current page load
    non_interaction: true, // avoids affecting bounce rate.
  });
}


non_interaction: true, // avoids affecting bounce rate.
  });
}
Read more about sending results to Google Analytics.


useRouterThe useRouter hook allows you to programmatically change routes inside Client Components.
Recommendation: Use the <Link> component for navigation unless you have a specific requirement for using useRouter.
app/example-client-component.tsx 'use client'

import { useRouter } from 'next/navigation'

export default function Page() {
  const router = useRouter()

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}
useRouter()
router.push(href: string): Perform a client-side navigation to the provided route. Adds a new entry into the browser’s history stack.
router.replace(href: string): Perform a client-side navigation to the provided route without adding a new entry into the browser’s history stack.


router.refresh(): Refresh the current route. Making a new request to the server, re-fetching data requests, and re-rendering Server Components. The client will merge the updated React Server Component payload without losing unaffected client-side React (e.g. useState) or browser state (e.g. scroll position).
router.prefetch(href: string): Prefetch the provided route for faster client-side transitions.
router.back(): Navigate back to the previous route in the browser’s history stack using soft navigation.
router.forward(): Navigate forwards to the next page in the browser’s history stack using soft navigation.
Good to know:
The push() and replace() methods will perform a soft navigation if the new route has been prefetched, and either, doesn't include dynamic segments or has the same dynamic parameters as the current route.
next/link automatically prefetch routes as they become visible in the viewport.


next/link automatically prefetch routes as they become visible in the viewport.
refresh() could re-produce the same result if fetch requests are cached. Other dynamic functions like cookies and headers could also change the response.
Migrating from the pages directory:
The new useRouter hook should be imported from next/navigation and not next/router
The pathname string has been removed and is replaced by usePathname()
The query object has been removed and is replaced by useSearchParams()
router.events is not currently supported. See below.
View the full migration guide.
Examples
Router Events
You can listen for page changes by composing other Client Component hooks like usePathname and useSearchParams.
app/components/navigation-events.js 'use client'

import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'

export function NavigationEvents() {
  const pathname = usePathname()


export function NavigationEvents() {
  const pathname = usePathname()
  const searchParams = useSearchParams()

  useEffect(() => {
    const url = `${pathname}?${searchParams}`
    console.log(url)
    // You can now use the current URL
    // ...
  }, [pathname, searchParams])

  return null
}
Which can be imported into a layout.
app/layout.js import { Suspense } from 'react'
import { NavigationEvents } from './components/navigation-events'

export default function Layout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}

        <Suspense fallback={null}>
          <NavigationEvents />
        </Suspense>
      </body>
    </html>
  )
}


</body>
    </html>
  )
}
Good to know: <NavigationEvents> is wrapped in a Suspense boundary becauseuseSearchParams() causes client-side rendering up to the closest Suspense boundary during static rendering. Learn more.
VersionChangesv13.0.0useRouter from next/navigation introduced.


useSearchParamsuseSearchParams is a Client Component hook that lets you read the current URL's query string.
useSearchParams returns a read-only version of the URLSearchParams interface.
app/dashboard/search-bar.tsx 'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
  const searchParams = useSearchParams()

  const search = searchParams.get('search')

  // URL -> `/dashboard?search=my-project`
  // `search` -> 'my-project'
  return <>Search: {search}</>
}
Parameters
 const searchParams = useSearchParams()
useSearchParams does not take any parameters.
Returns
useSearchParams returns a read-only version of the URLSearchParams interface, which includes utility methods for reading the URL's query string:
URLSearchParams.get(): Returns the first value associated with the search parameter. For example:


URLSearchParams.get(): Returns the first value associated with the search parameter. For example:
URLsearchParams.get("a")/dashboard?a=1'1'/dashboard?a=''/dashboard?b=3null/dashboard?a=1&a=2'1' - use getAll() to get all values
URLSearchParams.has(): Returns a boolean value indicating if the given parameter exists. For example:
URLsearchParams.has("a")/dashboard?a=1true/dashboard?b=3false
Learn more about other read-only methods of URLSearchParams, including the getAll(), keys(), values(), entries(), forEach(), and toString().
Good to know:
useSearchParams is a Client Component hook and is not supported in Server Components to prevent stale values during partial rendering.


If an application includes the /pages directory, useSearchParams will return ReadonlyURLSearchParams | null. The null value is for compatibility during migration since search params cannot be known during pre-rendering of a page that doesn't use getServerSideProps
Behavior
Static Rendering
If a route is statically rendered, calling useSearchParams() will cause the tree up to the closest Suspense boundary to be client-side rendered.
This allows a part of the page to be statically rendered while the dynamic part that uses searchParams is client-side rendered.
You can reduce the portion of the route that is client-side rendered by wrapping the component that uses useSearchParams in a Suspense boundary. For example:
app/dashboard/search-bar.tsx 'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
  const searchParams = useSearchParams()

  const search = searchParams.get('search')


const search = searchParams.get('search')

  // This will not be logged on the server when using static rendering
  console.log(search)

  return <>Search: {search}</>
}
app/dashboard/page.tsx import { Suspense } from 'react'
import SearchBar from './search-bar'

// This component passed as a fallback to the Suspense boundary
// will be rendered in place of the search bar in the initial HTML.
// When the value is available during React hydration the fallback
// will be replaced with the `<SearchBar>` component.
function SearchBarFallback() {
  return <>placeholder</>
}

export default function Page() {
  return (
    <>
      <nav>
        <Suspense fallback={<SearchBarFallback />}>
          <SearchBar />
        </Suspense>
      </nav>


<SearchBar />
        </Suspense>

Dashboard

    </>
  )
}
Dynamic Rendering
If a route is dynamically rendered, useSearchParams will be available on the server during the initial server render of the Client Component.
Good to know: Setting the dynamic route segment config option to force-dynamic can be used to force dynamic rendering.
For example:
app/dashboard/search-bar.tsx 'use client'

import { useSearchParams } from 'next/navigation'

export default function SearchBar() {
  const searchParams = useSearchParams()

  const search = searchParams.get('search')

  // This will be logged on the server during the initial render
  // and on the client on subsequent navigations.
  console.log(search)

  return <>Search: {search}</>
}


console.log(search)

  return <>Search: {search}</>
}
app/dashboard/page.tsx import SearchBar from './search-bar'

export const dynamic = 'force-dynamic'

export default function Page() {
  return (
    <>

        <SearchBar />

Dashboard

    </>
  )
}
Server Components
Pages
To access search params in Pages (Server Components), use the searchParams prop.
Layouts
Unlike Pages, Layouts (Server Components) do not receive the searchParams prop. This is because a shared layout is not re-rendered during navigation which could lead to stale searchParams between navigations. View detailed explanation.


Instead, use the Page searchParams prop or the useSearchParams hook in a Client Component, which is re-rendered on the client with the latest searchParams.
Examples
Updating searchParams
You can use useRouter or Link to set new searchParams. After a navigation is performed, the current page.js will receive an updated searchParams prop.
app/example-client-component.tsx export default function ExampleClientComponent() {
  const router = useRouter()
  const pathname = usePathname()
  const searchParams = useSearchParams()!

  // Get a new searchParams string by merging the current
  // searchParams with a provided key/value pair
  const createQueryString = useCallback(
    (name: string, value: string) => {
      const params = new URLSearchParams(searchParams)
      params.set(name, value)

      return params.toString()
    },
    [searchParams]
  )


return params.toString()
    },
    [searchParams]
  )

  return (
    <>

Sort By

      {/* using useRouter */}
      <button
        onClick={() => {
          // <pathname>?sort=asc
          router.push(pathname + '?' + createQueryString('sort', 'asc'))
        }}
      >
        ASC
      </button>

      {/* using <Link> */}
      <Link
        href={
          // <pathname>?sort=desc
          pathname + '?' + createQueryString('sort', 'desc')
        }
      >
        DESC
      </Link>
    </>
  )
}
Version History
VersionChangesv13.0.0useSearchParams introduced.


useSelectedLayoutSegmentuseSelectedLayoutSegment is a Client Component hook that lets you read the active route segment one level below the Layout it is called from.
It is useful for navigation UI, such as tabs inside a parent layout that change style depending on the active child segment.
app/example-client-component.tsx 'use client'

import { useSelectedLayoutSegment } from 'next/navigation'

export default function ExampleClientComponent() {
  const segment = useSelectedLayoutSegment()

  return
Active segment: {segment}

}
Good to know:
Since useSelectedLayoutSegment is a Client Component hook, and Layouts are Server Components by default, useSelectedLayoutSegment is usually called via a Client Component that is imported into a Layout.
useSelectedLayoutSegment only returns the segment one level down. To return all active segments, see useSelectedLayoutSegments
Parameters
 const segment = useSelectedLayoutSegment()


Parameters
 const segment = useSelectedLayoutSegment()
useSelectedLayoutSegment does not take any parameters.
Returns
useSelectedLayoutSegment returns a string of the active segment or null if one doesn't exist.
For example, given the Layouts and URLs below, the returned segment would be:
LayoutVisited URLReturned Segmentapp/layout.js/nullapp/layout.js/dashboard'dashboard'app/dashboard/layout.js/dashboardnullapp/dashboard/layout.js/dashboard/settings'settings'app/dashboard/layout.js/dashboard/analytics'analytics'app/dashboard/layout.js/dashboard/analytics/monthly'analytics'
Examples
Creating an active link component
You can use useSelectedLayoutSegment to create an active link component that changes style depending on the active segment. For example, a featured posts list in the sidebar of a blog:
app/blog/blog-nav-link.tsx 'use client'

import Link from 'next/link'
import { useSelectedLayoutSegment } from 'next/navigation'


import { useSelectedLayoutSegment } from 'next/navigation'

// This *client* component will be imported into a blog layout
export default function BlogNavLink({
  slug,
  children,
}: {
  slug: string
  children: React.ReactNode
}) {
  // Navigating to `/blog/hello-world` will return 'hello-world'
  // for the selected layout segment
  const segment = useSelectedLayoutSegment()
  const isActive = slug === segment

  return (
    <Link
      href={`/blog/${slug}`}
      // Change style depending on whether the link is active
      style={{ fontWeight: isActive ? 'bold' : 'normal' }}
    >
      {children}
    </Link>
  )
}
app/blog/layout.tsx // Import the Client Component into a parent Layout (Server Component)


app/blog/layout.tsx // Import the Client Component into a parent Layout (Server Component)
import { BlogNavLink } from './blog-nav-link'
import getFeaturedPosts from './get-featured-posts'

export default async function Layout({
  children,
}: {
  children: React.ReactNode
}) {
  const featuredPosts = await getFeaturedPosts()
  return (

      {featuredPosts.map((post) => (

          <BlogNavLink slug={post.slug}>{post.title}</BlogNavLink>

      ))}

{children}

  )
}
Version History
VersionChangesv13.0.0useSelectedLayoutSegment introduced.


useSelectedLayoutSegmentsuseSelectedLayoutSegments is a Client Component hook that lets you read the active route segments below the Layout it is called from.
It is useful for creating UI in parent Layouts that need knowledge of active child segments such as breadcrumbs.
app/example-client-component.tsx 'use client'

import { useSelectedLayoutSegments } from 'next/navigation'

export default function ExampleClientComponent() {
  const segments = useSelectedLayoutSegments()

  return (

      {segments.map((segment, index) => (

{segment}

      ))}

  )
}
Good to know:
Since useSelectedLayoutSegments is a Client Component hook, and Layouts are Server Components by default, useSelectedLayoutSegments is usually called via a Client Component that is imported into a Layout.


The returned segments include Route Groups, which you might not want to be included in your UI. You can use the filter() array method to remove items that start with a bracket.
Parameters
 const segments = useSelectedLayoutSegments()
useSelectedLayoutSegments does not take any parameters.
Returns
useSelectedLayoutSegments returns an array of strings containing the active segments one level down from the layout the hook was called from. Or an empty array if none exist.
For example, given the Layouts and URLs below, the returned segments would be:
LayoutVisited URLReturned Segmentsapp/layout.js/[]app/layout.js/dashboard['dashboard']app/layout.js/dashboard/settings['dashboard', 'settings']app/dashboard/layout.js/dashboard[]app/dashboard/layout.js/dashboard/settings['settings']
Version History
VersionChangesv13.0.0useSelectedLayoutSegments introduced.


appDir
Good to know: This option is no longer needed as of Next.js 13.4. The App Router is now stable.
The App Router (app directory) enables support for layouts, Server Components, streaming, and colocated data fetching.
Using the app directory will automatically enable React Strict Mode. Learn how to incrementally adopt app.


assetPrefix
Attention: Deploying to Vercel automatically configures a global CDN for your Next.js project.
You do not need to manually setup an Asset Prefix.
Good to know: Next.js 9.5+ added support for a customizable Base Path, which is better
suited for hosting your application on a sub-path like /docs.
We do not suggest you use a custom Asset Prefix for this use case.
To set up a CDN, you can set up an asset prefix and configure your CDN's origin to resolve to the domain that Next.js is hosted on.
Open next.config.js and add the assetPrefix config:
next.config.js const isProd = process.env.NODE_ENV === 'production'

module.exports = {
  // Use the CDN in production and localhost for development.
  assetPrefix: isProd ? 'https://cdn.mydomain.com' : undefined,
}


}
Next.js will automatically use your asset prefix for the JavaScript and CSS files it loads from the /_next/ path (.next/static/ folder). For example, with the above configuration, the following request for a JS chunk:
 /_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js
Would instead become:
 https://cdn.mydomain.com/_next/static/chunks/4b9b41aaa062cbbfeff4add70f256968c51ece5d.4d708494b3aed70c04f0.js


The exact configuration for uploading your files to a given CDN will depend on your CDN of choice. The only folder you need to host on your CDN is the contents of .next/static/, which should be uploaded as _next/static/ as the above URL request indicates. Do not upload the rest of your .next/ folder, as you should not expose your server code and other configuration to the public.
While assetPrefix covers requests to _next/static, it does not influence the following paths:
Files in the public folder; if you want to serve those assets over a CDN, you'll have to introduce the prefix yourself


basePath
To deploy a Next.js application under a sub-path of a domain you can use the basePath config option.
basePath allows you to set a path prefix for the application. For example, to use /docs instead of '' (an empty string, the default), open next.config.js and add the basePath config:
next.config.js module.exports = {
  basePath: '/docs',
}
Good to know: This value must be set at build time and cannot be changed without re-building as the value is inlined in the client-side bundles.
Links
When linking to other pages using next/link and next/router the basePath will be automatically applied.
For example, using /about will automatically become /docs/about when basePath is set to /docs.
 export default function HomePage() {
  return (
    <>
      <Link href="/about">About Page</Link>
    </>
  )
}
Output html:


</>
  )
}
Output html:
 About Page
This makes sure that you don't have to change all links in your application when changing the basePath value.
Images
When using the next/image component, you will need to add the basePath in front of src.
For example, using /docs/me.png will properly serve your image when basePath is set to /docs.
 import Image from 'next/image'

function Home() {
  return (
    <>

My Homepage

      <Image
        src="/docs/me.png"
        alt="Picture of the author"
        width={500}
        height={500}
      />

Welcome to my homepage!

    </>
  )
}

export default Home


compress
Next.js provides gzip compression to compress rendered content and static files. In general you will want to enable compression on a HTTP proxy like nginx, to offload load from the Node.js process.
To disable compression, open next.config.js and disable the compress config:
next.config.js module.exports = {
  compress: false,
}


devIndicators
When you edit your code, and Next.js is compiling the application, a compilation indicator appears in the bottom right corner of the page.
Good to know: This indicator is only present in development mode and will not appear when building and running the app in production mode.
In some cases this indicator can be misplaced on your page, for example, when conflicting with a chat launcher. To change its position, open next.config.js and set the buildActivityPosition in the devIndicators object to bottom-right (default), bottom-left, top-right or top-left:next.config.js module.exports = {
  devIndicators: {
    buildActivityPosition: 'bottom-right',
  },
}In some cases this indicator might not be useful for you. To remove it, open next.config.js and disable the buildActivity config in devIndicators object:next.config.js module.exports = {
  devIndicators: {
    buildActivity: false,


devIndicators: {
    buildActivity: false,
  },
}


distDir
You can specify a name to use for a custom build directory to use instead of .next.
Open next.config.js and add the distDir config:
next.config.js module.exports = {
  distDir: 'build',
}
Now if you run next build Next.js will use build instead of the default .next folder.
distDir should not leave your project directory. For example, ../build is an invalid directory.


env
Since the release of Next.js 9.4 we now have a more intuitive and ergonomic experience for adding environment variables. Give it a try!
Examples
With env
Good to know: environment variables specified in this way will always be included in the JavaScript bundle, prefixing the environment variable name with NEXT_PUBLIC_ only has an effect when specifying them through the environment or .env files.
To add environment variables to the JavaScript bundle, open next.config.js and add the env config:
next.config.js module.exports = {
  env: {
    customKey: 'my-value',
  },
}
Now you can access process.env.customKey in your code. For example:
 function Page() {
  return
The value of customKey is: {process.env.customKey}

}

export default Page


}

export default Page
Next.js will replace process.env.customKey with 'my-value' at build time. Trying to destructure process.env variables won't work due to the nature of webpack DefinePlugin.
For example, the following line:
 return
The value of customKey is: {process.env.customKey}

Will end up being:
 return
The value of customKey is: {'my-value'}


eslint
When ESLint is detected in your project, Next.js fails your production build (next build) when errors are present.
If you'd like Next.js to produce production code even when your application has ESLint errors, you can disable the built-in linting step completely. This is not recommended unless you already have ESLint configured to run in a separate part of your workflow (for example, in CI or a pre-commit hook).
Open next.config.js and enable the ignoreDuringBuilds option in the eslint config:
next.config.js module.exports = {
  eslint: {
    // Warning: This allows production builds to successfully complete even if
    // your project has ESLint errors.
    ignoreDuringBuilds: true,
  },
}


exportPathMap (Deprecated)
This feature is exclusive to next export and currently deprecated in favor of getStaticPaths with pages or generateStaticParams with app.
Examples
Static Export
exportPathMap allows you to specify a mapping of request paths to page destinations, to be used during export. Paths defined in exportPathMap will also be available when using next dev.
Let's start with an example, to create a custom exportPathMap for an app with the following pages:
pages/index.js
pages/about.js
pages/post.js
Open next.config.js and add the following exportPathMap config:
next.config.js module.exports = {
  exportPathMap: async function (
    defaultPathMap,
    { dev, dir, outDir, distDir, buildId }
  ) {
    return {
      '/': { page: '/' },
      '/about': { page: '/about' },


'/about': { page: '/about' },
      '/p/hello-nextjs': { page: '/post', query: { title: 'hello-nextjs' } },
      '/p/learn-nextjs': { page: '/post', query: { title: 'learn-nextjs' } },
      '/p/deploy-nextjs': { page: '/post', query: { title: 'deploy-nextjs' } },
    }
  },
}
Good to know: the query field in exportPathMap cannot be used with automatically statically optimized pages or getStaticProps pages as they are rendered to HTML files at build-time and additional query information cannot be provided during next export.
The pages will then be exported as HTML files, for example, /about will become /about.html.


exportPathMap is an async function that receives 2 arguments: the first one is defaultPathMap, which is the default map used by Next.js. The second argument is an object with:
dev - true when exportPathMap is being called in development. false when running next export. In development exportPathMap is used to define routes.
dir - Absolute path to the project directory
outDir - Absolute path to the out/ directory (configurable with -o). When dev is true the value of outDir will be null.
distDir - Absolute path to the .next/ directory (configurable with the distDir config)
buildId - The generated build id
The returned object is a map of pages where the key is the pathname and the value is an object that accepts the following fields:
page: String - the page inside the pages directory to render


page: String - the page inside the pages directory to render
query: Object - the query object passed to getInitialProps when prerendering. Defaults to {}
The exported pathname can also be a filename (for example, /readme.md), but you may need to set the Content-Type header to text/html when serving its content if it is different than .html.
Adding a trailing slash
It is possible to configure Next.js to export pages as index.html files and require trailing slashes, /about becomes /about/index.html and is routable via /about/. This was the default behavior prior to Next.js 9.
To switch back and add a trailing slash, open next.config.js and enable the trailingSlash config:
next.config.js module.exports = {
  trailingSlash: true,
}
Customizing the output directory
next export will use out as the default output directory, you can customize this using the -o argument, like so:


Terminal next export -o outdir
Warning: Using exportPathMap is deprecated and is overridden by getStaticPaths inside pages. We don't recommend using them together.


generateBuildId
Next.js uses a constant id generated at build time to identify which version of your application is being served. This can cause problems in multi-server deployments when next build is run on every server. In order to keep a consistent build id between builds you can provide your own build id.
Open next.config.js and add the generateBuildId function:
next.config.js module.exports = {
  generateBuildId: async () => {
    // You can, for example, get the latest git commit hash here
    return 'my-build-id'
  },
}


generateEtags
Next.js will generate etags for every page by default. You may want to disable etag generation for HTML pages depending on your cache strategy.
Open next.config.js and disable the generateEtags option:
next.config.js module.exports = {
  generateEtags: false,
}


headers
Headers allow you to set custom HTTP headers on the response to an incoming request on a given path.
To set custom HTTP headers you can use the headers key in next.config.js:
next.config.js module.exports = {
  async headers() {
    return [
      {
        source: '/about',
        headers: [
          {
            key: 'x-custom-header',
            value: 'my custom header value',
          },
          {
            key: 'x-another-custom-header',
            value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}
headers is an async function that expects an array to be returned holding objects with source and headers properties:
source is the incoming request path pattern.
headers is an array of response header objects, with key and value properties.


headers is an array of response header objects, with key and value properties.
basePath: false or undefined - if false the basePath won't be included when matching, can be used for external rewrites only.
locale: false or undefined - whether the locale should not be included when matching.
has is an array of has objects with the type, key and value properties.
missing is an array of missing objects with the type, key and value properties.
Headers are checked before the filesystem which includes pages and /public files.
Header Overriding Behavior
If two headers match the same path and set the same header key, the last header key will override the first. Using the below headers, the path /hello will result in the header x-hello being world due to the last header value set being world.
next.config.js module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',


return [
      {
        source: '/:path*',
        headers: [
          {
            key: 'x-hello',
            value: 'there',
          },
        ],
      },
      {
        source: '/hello',
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
    ]
  },
}
Path Matching
Path matches are allowed, for example /blog/:slug will match /blog/hello-world (no nested paths):
next.config.js module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug',
        headers: [
          {
            key: 'x-slug',
            value: ':slug', // Matched parameters can be used in the value
          },
          {


},
          {
            key: 'x-slug-:slug', // Matched parameters can be used in the key
            value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}
Wildcard Path Matching
To match a wildcard path you can use * after a parameter, for example /blog/:slug* will match /blog/a/b/c/d/hello-world:
next.config.js module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:slug*',
        headers: [
          {
            key: 'x-slug',
            value: ':slug*', // Matched parameters can be used in the value
          },
          {
            key: 'x-slug-:slug*', // Matched parameters can be used in the key
            value: 'my other custom header value',
          },


value: 'my other custom header value',
          },
        ],
      },
    ]
  },
}
Regex Path Matching
To match a regex path you can wrap the regex in parenthesis after a parameter, for example /blog/:slug(\\d{1,}) will match /blog/123 but not /blog/abc:
next.config.js module.exports = {
  async headers() {
    return [
      {
        source: '/blog/:post(\\d{1,})',
        headers: [
          {
            key: 'x-post',
            value: ':post',
          },
        ],
      },
    ]
  },
}
The following characters (, ), {, }, :, *, +, ? are used for regex path matching, so when used in the source as non-special values they must be escaped by adding \\ before them:


next.config.js module.exports = {
  async headers() {
    return [
      {
        // this will match `/english(default)/something` being requested
        source: '/english\\(default\\)/:slug',
        headers: [
          {
            key: 'x-header',
            value: 'value',
          },
        ],
      },
    ]
  },
}
Header, Cookie, and Query Matching
To only apply a header when header, cookie, or query values also match the has field or don't match the missing field can be used. Both the source and all has items must match and all missing items must not match for the header to be applied.
has and missing items can have the following fields:
type: String - must be either header, cookie, host, or query.
key: String - the key from the selected type to match against.


key: String - the key from the selected type to match against.
value: String or undefined - the value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value, e.g. if the value first-(?<paramName>.*) is used for first-second then second will be usable in the destination with :paramName.
next.config.js module.exports = {
  async headers() {
    return [
      // if the header `x-add-header` is present,
      // the `x-another-header` header will be applied
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-add-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],


value: 'hello',
          },
        ],
      },
      // if the header `x-no-header` is not present,
      // the `x-another-header` header will be applied
      {
        source: '/:path*',
        missing: [
          {
            type: 'header',
            key: 'x-no-header',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: 'hello',
          },
        ],
      },
      // if the source, query, and cookie are matched,
      // the `x-authorized` header will be applied
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // the page value will not be available in the


key: 'page',
            // the page value will not be available in the
            // header key/values since value is provided and
            // doesn't use a named capture group e.g. (?<page>home)
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        headers: [
          {
            key: 'x-authorized',
            value: ':authorized',
          },
        ],
      },
      // if the header `x-authorized` is present and
      // contains a matching value, the `x-another-header` will be applied
      {
        source: '/:path*',
        has: [
          {
            type: 'header',
            key: 'x-authorized',


{
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
      // if the host is `example.com`,
      // this header will be applied
      {
        source: '/:path*',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        headers: [
          {
            key: 'x-another-header',
            value: ':authorized',
          },
        ],
      },
    ]
  },
}
Headers with basePath support


],
      },
    ]
  },
}
Headers with basePath support
When leveraging basePath support with headers each source is automatically prefixed with the basePath unless you add basePath: false to the header:
next.config.js module.exports = {
  basePath: '/docs',

  async headers() {
    return [
      {
        source: '/with-basePath', // becomes /docs/with-basePath
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        source: '/without-basePath', // is not modified since basePath: false is set
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
        basePath: false,
      },
    ]
  },
}
Headers with i18n support


},
    ]
  },
}
Headers with i18n support
When leveraging i18n support with headers each source is automatically prefixed to handle the configured locales unless you add locale: false to the header. If locale: false is used you must prefix the source with a locale for it to be matched correctly.
next.config.js module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },

  async headers() {
    return [
      {
        source: '/with-locale', // automatically handles all locales
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // does not handle locales automatically since locale: false is set
        source: '/nl/with-locale-manual',


source: '/nl/with-locale-manual',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // this matches '/' since `en` is the defaultLocale
        source: '/en',
        locale: false,
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },
      {
        // this gets converted to /(en|fr|de)/(.*) so will not match the top-level
        // `/` or `/fr` routes like /:path* would
        source: '/(.*)',
        headers: [
          {
            key: 'x-hello',
            value: 'world',
          },
        ],
      },


value: 'world',
          },
        ],
      },
    ]
  },
}
Cache-Control
You can set the Cache-Control header in your Next.js API Routes by using the res.setHeader method:
pages/api/user.js export default function handler(req, res) {
  res.setHeader('Cache-Control', 's-maxage=86400')
  res.status(200).json({ name: 'John Doe' })
}
You cannot set Cache-Control headers in next.config.js file as these will be overwritten in production to ensure that API Routes and static assets are cached effectively.
If you need to revalidate the cache of a page that has been statically generated, you can do so by setting the revalidate prop in the page's getStaticProps function.
Options
X-DNS-Prefetch-Control


Options
X-DNS-Prefetch-Control
This header controls DNS prefetching, allowing browsers to proactively perform domain name resolution on external links, images, CSS, JavaScript, and more. This prefetching is performed in the background, so the DNS is more likely to be resolved by the time the referenced items are needed. This reduces latency when the user clicks a link.
 {
  key: 'X-DNS-Prefetch-Control',
  value: 'on'
}
Strict-Transport-Security
This header informs browsers it should only be accessed using HTTPS, instead of using HTTP. Using the configuration below, all present and future subdomains will use HTTPS for a max-age of 2 years. This blocks access to pages or subdomains that can only be served over HTTP.
If you're deploying to Vercel, this header is not necessary as it's automatically added to all deployments unless you declare headers in your next.config.js.
 {


{
  key: 'Strict-Transport-Security',
  value: 'max-age=63072000; includeSubDomains; preload'
}
X-XSS-Protection
This header stops pages from loading when they detect reflected cross-site scripting (XSS) attacks. Although this protection is not necessary when sites implement a strong Content-Security-Policy disabling the use of inline JavaScript ('unsafe-inline'), it can still provide protection for older web browsers that don't support CSP.
 {
  key: 'X-XSS-Protection',
  value: '1; mode=block'
}
X-Frame-Options
This header indicates whether the site should be allowed to be displayed within an iframe. This can prevent against clickjacking attacks. This header has been superseded by CSP's frame-ancestors option, which has better support in modern browsers.
 {
  key: 'X-Frame-Options',


{
  key: 'X-Frame-Options',
  value: 'SAMEORIGIN'
}
Permissions-Policy
This header allows you to control which features and APIs can be used in the browser. It was previously named Feature-Policy. You can view the full list of permission options here.
 {
  key: 'Permissions-Policy',
  value: 'camera=(), microphone=(), geolocation=(), browsing-topics=()'
}
X-Content-Type-Options
This header prevents the browser from attempting to guess the type of content if the Content-Type header is not explicitly set. This can prevent XSS exploits for websites that allow users to upload and share files. For example, a user trying to download an image, but having it treated as a different Content-Type like an executable, which could be malicious. This header also applies to downloading browser extensions. The only valid value for this header is nosniff.
 {


{
  key: 'X-Content-Type-Options',
  value: 'nosniff'
}
Referrer-Policy
This header controls how much information the browser includes when navigating from the current website (origin) to another. You can read about the different options here.
 {
  key: 'Referrer-Policy',
  value: 'origin-when-cross-origin'
}
Content-Security-Policy
This header helps prevent cross-site scripting (XSS), clickjacking and other code injection attacks. Content Security Policy (CSP) can specify allowed origins for content including scripts, stylesheets, images, fonts, objects, media (audio, video), iframes, and more.
You can read about the many different CSP options here.
You can add Content Security Policy directives using a template string.
 // Before defining your Security Headers
// add Content Security Policy directives using a template string.


// add Content Security Policy directives using a template string.

const ContentSecurityPolicy = `
  default-src 'self';
  script-src 'self';
  child-src example.com;
  style-src 'self' example.com;
  font-src 'self';
`
When a directive uses a keyword such as self, wrap it in single quotes ''.
In the header's value, replace the new line with a space.
 {
  key: 'Content-Security-Policy',
  value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim()
}
Version History
VersionChangesv13.3.0missing added.v10.2.0has added.v9.5.0Headers added.


httpAgentOptions
In Node.js versions prior to 18, Next.js automatically polyfills fetch() with node-fetch and enables HTTP Keep-Alive by default.
To disable HTTP Keep-Alive for all fetch() calls on the server-side, open next.config.js and add the httpAgentOptions config:
next.config.js module.exports = {
  httpAgentOptions: {
    keepAlive: false,
  },
}


images
If you want to use a cloud provider to optimize images instead of using the Next.js built-in Image Optimization API, you can configure next.config.js with the following:
next.config.js module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './my/image/loader.js',
  },
}
This loaderFile must point to a file relative to the root of your Next.js application. The file must export a default function that returns a string, for example:
 export default function myImageLoader({ src, width, quality }) {
  return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}
Alternatively, you can use the loader prop to pass the function to each instance of next/image.
Example Loader Configuration
Akamai
Cloudinary
Cloudflare
Contentful
Fastly
Gumlet
ImageEngine
Imgix
Thumbor


Contentful
Fastly
Gumlet
ImageEngine
Imgix
Thumbor
Supabase
Akamai
 // Docs: https://techdocs.akamai.com/ivm/reference/test-images-on-demand
export default function akamaiLoader({ src, width, quality }) {
  return `https://example.com/${src}?imwidth=${width}`
}
Cloudinary
 // Demo: https://res.cloudinary.com/demo/image/upload/w_300,c_limit,q_auto/turtles.jpg
export default function cloudinaryLoader({ src, width, quality }) {
  const params = ['f_auto', 'c_limit', `w_${width}`, `q_${quality || 'auto'}`]
  return `https://example.com/${params.join(',')}${src}`
}
Cloudflare
 // Docs: https://developers.cloudflare.com/images/url-format
export default function cloudflareLoader({ src, width, quality }) {


export default function cloudflareLoader({ src, width, quality }) {
  const params = [`width=${width}`, `quality=${quality || 75}`, 'format=auto']
  return `https://example.com/cdn-cgi/image/${params.join(',')}/${src}`
}
Contentful
 // Docs: https://www.contentful.com/developers/docs/references/images-api/
export default function contentfulLoader({ src, width, quality }) {
  const url = new URL(`https://example.com${src}`)
  url.searchParams.set('fm', 'webp')
  url.searchParams.set('w', width.toString())
  url.searchParams.set('q', (quality || 75).toString())
  return url.href
}
Fastly
 // Docs: https://developer.fastly.com/reference/io/
export default function fastlyLoader({ src, width, quality }) {


export default function fastlyLoader({ src, width, quality }) {
  const url = new URL(`https://example.com${src}`)
  url.searchParams.set('auto', 'webp')
  url.searchParams.set('width', width.toString())
  url.searchParams.set('quality', (quality || 75).toString())
  return url.href
}
Gumlet
 // Docs: https://docs.gumlet.com/reference/image-transform-size
export default function gumletLoader({ src, width, quality }) {
  const url = new URL(`https://example.com${src}`)
  url.searchParams.set('format', 'auto')
  url.searchParams.set('w', width.toString())
  url.searchParams.set('q', (quality || 75).toString())
  return url.href
}
ImageEngine


return url.href
}
ImageEngine
 // Docs: https://support.imageengine.io/hc/en-us/articles/360058880672-Directives
export default function imageengineLoader({ src, width, quality }) {
  const compression = 100 - (quality || 50)
  const params = [`w_${width}`, `cmpr_${compression}`)]
  return `https://example.com${src}?imgeng=/${params.join('/')`
}
Imgix
 // Demo: https://static.imgix.net/daisy.png?format=auto&fit=max&w=300
export default function imgixLoader({ src, width, quality }) {
  const url = new URL(`https://example.com${src}`)
  const params = url.searchParams
  params.set('auto', params.getAll('auto').join(',') || 'format')
  params.set('fit', params.get('fit') || 'max')


params.set('fit', params.get('fit') || 'max')
  params.set('w', params.get('w') || width.toString())
  params.set('q', (quality || 50).toString())
  return url.href
}
Thumbor
 // Docs: https://thumbor.readthedocs.io/en/latest/
export default function thumborLoader({ src, width, quality }) {
  const params = [`${width}x0`, `filters:quality(${quality || 75})`]
  return `https://example.com${params.join('/')}${src}`
}
Supabase
 // Docs: https://supabase.com/docs/guides/storage/image-transformations#nextjs-loader
export default function supabaseLoader({ src, width, quality }) {
  const url = new URL(`https://example.com${src}`)
  url.searchParams.set('width', width.toString())


url.searchParams.set('width', width.toString())
  url.searchParams.set('quality', (quality || 75).toString())
  return url.href
}


incrementalCacheHandlerPathIn Next.js, the default cache handler uses the filesystem cache. This requires no configuration, however, you can customize the cache handler by using the incrementalCacheHandlerPath field in next.config.js.
next.config.js module.exports = {
  experimental: {
    incrementalCacheHandlerPath: require.resolve('./cache-handler.js'),
  },
}
Here's an example of a custom cache handler:
cache-handler.js const cache = new Map()

module.exports = class CacheHandler {
  constructor(options) {
    this.options = options
    this.cache = {}
  }

  async get(key) {
    return cache.get(key)
  }

  async set(key, data) {
    cache.set(key, {
      value: data,
      lastModified: Date.now(),
    })
  }
}
API Reference


lastModified: Date.now(),
    })
  }
}
API Reference
The cache handler can implement the following methods: get, set, and revalidateTag.
get()
ParameterTypeDescriptionkeystringThe key to the cached value.
Returns the cached value or null if not found.
set()
ParameterTypeDescriptionkeystringThe key to store the data under.dataData or nullThe data to be cached.
Returns Promise<void>.
revalidateTag()
ParameterTypeDescriptiontagstringThe cache tag to revalidate.
Returns Promise<void>. Learn more about revalidating data or the revalidateTag() function.


mdxRsFor use with @next/mdx. Compile MDX files using the new Rust compiler.
next.config.js const withMDX = require('@next/mdx')()

/** @type {import('next').NextConfig} */
const nextConfig = {
  pageExtensions: ['ts', 'tsx', 'mdx'],
  experimental: {
    mdxRs: true,
  },
}

module.exports = withMDX(nextConfig)


onDemandEntries
Next.js exposes some options that give you some control over how the server will dispose or keep in memory built pages in development.
To change the defaults, open next.config.js and add the onDemandEntries config:
next.config.js module.exports = {
  onDemandEntries: {
    // period (in ms) where the server will keep pages in the buffer
    maxInactiveAge: 25 * 1000,
    // number of pages that should be kept simultaneously without being disposed
    pagesBufferLength: 2,
  },
}


output
During a build, Next.js will automatically trace each page and its dependencies to determine all of the files that are needed for deploying a production version of your application.
This feature helps reduce the size of deployments drastically. Previously, when deploying with Docker you would need to have all files from your package's dependencies installed to run next start. Starting with Next.js 12, you can leverage Output File Tracing in the .next/ directory to only include the necessary files.
Furthermore, this removes the need for the deprecated serverless target which can cause various issues and also creates unnecessary duplication.
How it Works
During next build, Next.js will use @vercel/nft to statically analyze import, require, and fs usage to determine all files that a page might load.
Next.js' production server is also traced for its needed files and output at .next/next-server.js.nft.json which can be leveraged in production.


To leverage the .nft.json files emitted to the .next output directory, you can read the list of files in each trace that are relative to the .nft.json file and then copy them to your deployment location.
Automatically Copying Traced Files
Next.js can automatically create a standalone folder that copies only the necessary files for a production deployment including select files in node_modules.
To leverage this automatic copying you can enable it in your next.config.js:
next.config.js module.exports = {
  output: 'standalone',
}
This will create a folder at .next/standalone which can then be deployed on its own without installing node_modules.


Additionally, a minimal server.js file is also output which can be used instead of next start. This minimal server does not copy the public or .next/static folders by default as these should ideally be handled by a CDN instead, although these folders can be copied to the standalone/public and standalone/.next/static folders manually, after which server.js file will serve these automatically.
Good to know:
next.config.js is read during next build and serialized into the server.js output file. If the legacy serverRuntimeConfig or publicRuntimeConfig options are being used, the values will be specific to values at build time.
If your project uses Image Optimization with the default loader, you must install sharp as a dependency:
If your project needs alternative port or hostname for listening, you can define PORT and HOSTNAME environment variables, before running server.js. For example, PORT=3000 HOSTNAME=localhost node server.js.
Terminal npm i sharp
Terminal yarn add sharp
Terminal pnpm add sharp


Terminal npm i sharp
Terminal yarn add sharp
Terminal pnpm add sharp
Caveats
While tracing in monorepo setups, the project directory is used for tracing by default. For next build packages/web-app, packages/web-app would be the tracing root and any files outside of that folder will not be included. To include files outside of this folder you can set experimental.outputFileTracingRoot in your next.config.js.
packages/web-app/next.config.js module.exports = {
  experimental: {
    // this includes files from the monorepo base two directories up
    outputFileTracingRoot: path.join(__dirname, '../../'),
  },
}


outputFileTracingRoot: path.join(__dirname, '../../'),
  },
}
There are some cases in which Next.js might fail to include required files, or might incorrectly include unused files. In those cases, you can leverage experimental.outputFileTracingExcludes and experimental.outputFileTracingIncludes respectively in next.config.js. Each config accepts an object with minimatch globs for the key to match specific pages and a value of an array with globs relative to the project's root to either include or exclude in the trace.
next.config.js module.exports = {
  experimental: {
    outputFileTracingExcludes: {
      '/api/hello': ['./un-necessary-folder/**/*'],
    },
    outputFileTracingIncludes: {
      '/api/another': ['./necessary-folder/**/*'],
    },
  },
}


},
  },
}
Currently, Next.js does not do anything with the emitted .nft.json files. The files must be read by your deployment platform, for example Vercel, to create a minimal deployment. In a future release, a new command is planned to utilize these .nft.json files.
Experimental turbotrace
Tracing dependencies can be slow because it requires very complex computations and analysis. We created turbotrace in Rust as a faster and smarter alternative to the JavaScript implementation.
To enable it, you can add the following configuration to your next.config.js:
next.config.js module.exports = {
  experimental: {
    turbotrace: {
      // control the log level of the turbotrace, default is `error`
      logLevel?:
      | 'bug'
      | 'fatal'
      | 'error'
      | 'warning'
      | 'hint'


| 'error'
      | 'warning'
      | 'hint'
      | 'note'
      | 'suggestions'
      | 'info',
      // control if the log of turbotrace should contain the details of the analysis, default is `false`
      logDetail?: boolean
      // show all log messages without limit
      // turbotrace only show 1 log message for each categories by default
      logAll?: boolean
      // control the context directory of the turbotrace
      // files outside of the context directory will not be traced
      // set the `experimental.outputFileTracingRoot` has the same effect
      // if the `experimental.outputFileTracingRoot` and this option are both set, the `experimental.turbotrace.contextDirectory` will be used
      contextDirectory?: string


contextDirectory?: string
      // if there is `process.cwd()` expression in your code, you can set this option to tell `turbotrace` the value of `process.cwd()` while tracing.
      // for example the require(process.cwd() + '/package.json') will be traced as require('/path/to/cwd/package.json')
      processCwd?: string
      // control the maximum memory usage of the `turbotrace`, in `MB`, default is `6000`.
      memoryLimit?: number
    },
  },
}


pageExtensions
By default, Next.js accepts files with the following extensions: .tsx, .ts, .jsx, .js. This can be modified to allow other extensions like markdown (.md, .mdx).next.config.js const withMDX = require('@next/mdx')()

/** @type {import('next').NextConfig} */
const nextConfig = {
  pageExtensions: ['ts', 'tsx', 'mdx'],
  experimental: {
    mdxRs: true,
  },
}


experimental: {
    mdxRs: true,
  },
}

module.exports = withMDX(nextConfig)For custom advanced configuration of Next.js, you can create a next.config.js or next.config.mjs file in the root of your project directory (next to package.json).next.config.js is a regular Node.js module, not a JSON file. It gets used by the Next.js server and build phases, and it's not included in the browser build.Take a look at the following next.config.js example:next.config.js /**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  /* config options here */
}

module.exports = nextConfigIf you need ECMAScript modules, you can use next.config.mjs:next.config.mjs /**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  /* config options here */


*/
const nextConfig = {
  /* config options here */
}

export default nextConfigYou can also use a function:next.config.mjs module.exports = (phase, { defaultConfig }) => {
  /**
   * @type {import('next').NextConfig}
   */
  const nextConfig = {
    /* config options here */
  }
  return nextConfig
}Since Next.js 12.1.0, you can use an async function:next.config.js module.exports = async (phase, { defaultConfig }) => {
  /**
   * @type {import('next').NextConfig}
   */
  const nextConfig = {
    /* config options here */
  }
  return nextConfig


/* config options here */
  }
  return nextConfig
}phase is the current context in which the configuration is loaded. You can see the available phases. Phases can be imported from next/constants: const { PHASE_DEVELOPMENT_SERVER } = require('next/constants')

module.exports = (phase, { defaultConfig }) => {
  if (phase === PHASE_DEVELOPMENT_SERVER) {
    return {
      /* development only config options here */
    }
  }

  return {
    /* config options for all phases except development here */
  }


return {
    /* config options for all phases except development here */
  }
}The commented lines are the place where you can put the configs allowed by next.config.js, which are defined in this file.However, none of the configs are required, and it's not necessary to understand what each config does. Instead, search for the features you need to enable or modify in this section and they will show you what to do.
Avoid using new JavaScript features not available in your target Node.js version. next.config.js will not be parsed by Webpack, Babel or TypeScript.


poweredByHeader
By default Next.js will add the x-powered-by header. To opt-out of it, open next.config.js and disable the poweredByHeader config:
next.config.js module.exports = {
  poweredByHeader: false,
}


productionBrowserSourceMaps
Source Maps are enabled by default during development. During production builds, they are disabled to prevent you leaking your source on the client, unless you specifically opt-in with the configuration flag.
Next.js provides a configuration flag you can use to enable browser source map generation during the production build:
next.config.js module.exports = {
  productionBrowserSourceMaps: true,
}
When the productionBrowserSourceMaps option is enabled, the source maps will be output in the same directory as the JavaScript files. Next.js will automatically serve these files when requested.
Adding source maps can increase next build time
Increases memory usage during next build


reactStrictMode
Good to know: Since Next.js 13.4, Strict Mode is true by default with app router, so the above configuration is only necessary for pages. You can still disable Strict Mode by setting reactStrictMode: false.
Suggested: We strongly suggest you enable Strict Mode in your Next.js application to better prepare your application for the future of React.
React's Strict Mode is a development mode only feature for highlighting potential problems in an application. It helps to identify unsafe lifecycles, legacy API usage, and a number of other features.
The Next.js runtime is Strict Mode-compliant. To opt-in to Strict Mode, configure the following option in your next.config.js:
next.config.js module.exports = {
  reactStrictMode: true,
}


next.config.js module.exports = {
  reactStrictMode: true,
}
If you or your team are not ready to use Strict Mode in your entire application, that's OK! You can incrementally migrate on a page-by-page basis using <React.StrictMode>.


redirects
Redirects allow you to redirect an incoming request path to a different destination path.
To use redirects you can use the redirects key in next.config.js:
next.config.js module.exports = {
  async redirects() {
    return [
      {
        source: '/about',
        destination: '/',
        permanent: true,
      },
    ]
  },
}
redirects is an async function that expects an array to be returned holding objects with source, destination, and permanent properties:
source is the incoming request path pattern.
destination is the path you want to route to.
permanent true or false - if true will use the 308 status code which instructs clients/search engines to cache the redirect forever, if false will use the 307 status code which is temporary and is not cached.


Why does Next.js use 307 and 308? Traditionally a 302 was used for a temporary redirect, and a 301 for a permanent redirect, but many browsers changed the request method of the redirect to GET, regardless of the original method. For example, if the browser made a request to POST /v1/users which returned status code 302 with location /v2/users, the subsequent request might be GET /v2/users instead of the expected POST /v2/users. Next.js uses the 307 temporary redirect, and 308 permanent redirect status codes to explicitly preserve the request method used.
basePath: false or undefined - if false the basePath won't be included when matching, can be used for external redirects only.
locale: false or undefined - whether the locale should not be included when matching.
has is an array of has objects with the type, key and value properties.


has is an array of has objects with the type, key and value properties.
missing is an array of missing objects with the type, key and value properties.
Redirects are checked before the filesystem which includes pages and /public files.
Redirects are not applied to client-side routing (Link, router.push), unless Middleware is present and matches the path.
When a redirect is applied, any query values provided in the request will be passed through to the redirect destination. For example, see the following redirect configuration:
 {
  source: '/old-blog/:path*',
  destination: '/blog/:path*',
  permanent: false
}
When /old-blog/post-1?hello=world is requested, the client will be redirected to /blog/post-1?hello=world.
Path Matching
Path matches are allowed, for example /old-blog/:slug will match /old-blog/hello-world (no nested paths):


next.config.js module.exports = {
  async redirects() {
    return [
      {
        source: '/old-blog/:slug',
        destination: '/news/:slug', // Matched parameters can be used in the destination
        permanent: true,
      },
    ]
  },
}
Wildcard Path Matching
To match a wildcard path you can use * after a parameter, for example /blog/:slug* will match /blog/a/b/c/d/hello-world:
next.config.js module.exports = {
  async redirects() {
    return [
      {
        source: '/blog/:slug*',
        destination: '/news/:slug*', // Matched parameters can be used in the destination
        permanent: true,
      },
    ]
  },
}
Regex Path Matching


},
    ]
  },
}
Regex Path Matching
To match a regex path you can wrap the regex in parentheses after a parameter, for example /post/:slug(\\d{1,}) will match /post/123 but not /post/abc:
next.config.js module.exports = {
  async redirects() {
    return [
      {
        source: '/post/:slug(\\d{1,})',
        destination: '/news/:slug', // Matched parameters can be used in the destination
        permanent: false,
      },
    ]
  },
}
The following characters (, ), {, }, :, *, +, ? are used for regex path matching, so when used in the source as non-special values they must be escaped by adding \\ before them:
next.config.js module.exports = {
  async redirects() {
    return [
      {


async redirects() {
    return [
      {
        // this will match `/english(default)/something` being requested
        source: '/english\\(default\\)/:slug',
        destination: '/en-us/:slug',
        permanent: false,
      },
    ]
  },
}
Header, Cookie, and Query Matching
To only match a redirect when header, cookie, or query values also match the has field or don't match the missing field can be used. Both the source and all has items must match and all missing items must not match for the redirect to be applied.
has and missing items can have the following fields:
type: String - must be either header, cookie, host, or query.
key: String - the key from the selected type to match against.


key: String - the key from the selected type to match against.
value: String or undefined - the value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value, e.g. if the value first-(?<paramName>.*) is used for first-second then second will be usable in the destination with :paramName.
next.config.js module.exports = {
  async redirects() {
    return [
      // if the header `x-redirect-me` is present,
      // this redirect will be applied
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'header',
            key: 'x-redirect-me',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },


],
        permanent: false,
        destination: '/another-page',
      },
      // if the header `x-dont-redirect` is present,
      // this redirect will NOT be applied
      {
        source: '/:path((?!another-page$).*)',
        missing: [
          {
            type: 'header',
            key: 'x-do-not-redirect',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
      // if the source, query, and cookie are matched,
      // this redirect will be applied
      {
        source: '/specific/:path*',
        has: [
          {
            type: 'query',
            key: 'page',
            // the page value will not be available in the
            // destination since value is provided and doesn't


// destination since value is provided and doesn't
            // use a named capture group e.g. (?<page>home)
            value: 'home',
          },
          {
            type: 'cookie',
            key: 'authorized',
            value: 'true',
          },
        ],
        permanent: false,
        destination: '/another/:path*',
      },
      // if the header `x-authorized` is present and
      // contains a matching value, this redirect will be applied
      {
        source: '/',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        permanent: false,
        destination: '/home?authorized=:authorized',
      },
      // if the host is `example.com`,


},
      // if the host is `example.com`,
      // this redirect will be applied
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
    ]
  },
}
Redirects with basePath support
When leveraging basePath support with redirects each source and destination is automatically prefixed with the basePath unless you add basePath: false to the redirect:
next.config.js module.exports = {
  basePath: '/docs',

  async redirects() {
    return [
      {
        source: '/with-basePath', // automatically becomes /docs/with-basePath
        destination: '/another', // automatically becomes /docs/another
        permanent: false,
      },


permanent: false,
      },
      {
        // does not add /docs since basePath: false is set
        source: '/without-basePath',
        destination: 'https://example.com',
        basePath: false,
        permanent: false,
      },
    ]
  },
}
Redirects with i18n support
When leveraging i18n support with redirects each source and destination is automatically prefixed to handle the configured locales unless you add locale: false to the redirect. If locale: false is used you must prefix the source and destination with a locale for it to be matched correctly.
next.config.js module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },

  async redirects() {
    return [
      {
        source: '/with-locale', // automatically handles all locales


{
        source: '/with-locale', // automatically handles all locales
        destination: '/another', // automatically passes the locale on
        permanent: false,
      },
      {
        // does not handle locales automatically since locale: false is set
        source: '/nl/with-locale-manual',
        destination: '/nl/another',
        locale: false,
        permanent: false,
      },
      {
        // this matches '/' since `en` is the defaultLocale
        source: '/en',
        destination: '/en/another',
        locale: false,
        permanent: false,
      },
      // it's possible to match all locales even when locale: false is set
      {
        source: '/:locale/page',
        destination: '/en/newpage',
        permanent: false,
        locale: false,
      }
      {