App RouterThe App Router is a new paradigm for building applications using React's latest features. If you're already familiar with Next.js, you'll find that the App Router is a natural evolution of the existing file-system based router in the Pages Router.
For new applications, we recommend using the App Router. For existing applications, you can incrementally migrate to the App Router.
This section of the documentation includes the features available in the App Router:


Next.js CLI
The Next.js CLI allows you to start, build, and export your application.
To get a list of the available CLI commands, run the following command inside your project directory:
Terminal npx next -h
(npx comes with npm 5.2+ and higher)
The output should look like this:
Terminal Usage
  $ next <command>

Available commands
  build, start, export, dev, lint, telemetry, info

Options
  --version, -v   Version number
  --help, -h      Displays this message

For more information run a command with the --help flag
  $ next build --help
You can pass any node arguments to next commands:
Terminal NODE_OPTIONS='--throw-deprecation' next
NODE_OPTIONS='-r esm' next
NODE_OPTIONS='--inspect' next


NODE_OPTIONS='-r esm' next
NODE_OPTIONS='--inspect' next
Good to know: Running next without a command is the same as running next dev
Build
next build creates an optimized production build of your application. The output displays information about each route.
Size – The number of assets downloaded when navigating to the page client-side. The size for each route only includes its dependencies.
First Load JS – The number of assets downloaded when visiting the page from the server. The amount of JS shared by all is shown as a separate metric.
Both of these values are compressed with gzip. The first load is indicated by green, yellow, or red. Aim for green for performant applications.
You can enable production profiling for React with the --profile flag in next build. This requires Next.js 9.5:
Terminal next build --profile
After that, you can use the profiler in the same way as you would in development.


After that, you can use the profiler in the same way as you would in development.
You can enable more verbose build output with the --debug flag in next build. This requires Next.js 9.5.3:
Terminal next build --debug
With this flag enabled additional build output like rewrites, redirects, and headers will be shown.
Development
next dev starts the application in development mode with hot-code reloading, error reporting, and more:
The application will start at http://localhost:3000 by default. The default port can be changed with -p, like so:
Terminal npx next dev -p 4000
Or using the PORT environment variable:
Terminal PORT=4000 npx next dev
Good to know: PORT cannot be set in .env as booting up the HTTP server happens before any other code is initialized.


You can also set the hostname to be different from the default of 0.0.0.0, this can be useful for making the application available for other devices on the network. The default hostname can be changed with -H, like so:
Terminal npx next dev -H 192.168.1.2
Production
next start starts the application in production mode. The application should be compiled with next build first.
The application will start at http://localhost:3000 by default. The default port can be changed with -p, like so:
Terminal npx next start -p 4000
Or using the PORT environment variable:
Terminal PORT=4000 npx next start
Good to know:
-PORT cannot be set in .env as booting up the HTTP server happens before any other code is initialized.
next start cannot be used with output: 'standalone' or output: 'export'.
Keep Alive Timeout


Keep Alive Timeout
When deploying Next.js behind a downstream proxy (e.g. a load-balancer like AWS ELB/ALB) it's important to configure Next's underlying HTTP server with keep-alive timeouts that are larger than the downstream proxy's timeouts. Otherwise, once a keep-alive timeout is reached for a given TCP connection, Node.js will immediately terminate that connection without notifying the downstream proxy. This results in a proxy error whenever it attempts to reuse a connection that Node.js has already terminated.
To configure the timeout values for the production Next.js server, pass --keepAliveTimeout (in milliseconds) to next start, like so:
Terminal npx next start --keepAliveTimeout 70000
Lint
next lint runs ESLint for all files in the pages/, app/, components/, lib/, and src/ directories. It also
provides a guided setup to install any required dependencies if ESLint is not already configured in
your application.


your application.
If you have other directories that you would like to lint, you can specify them using the --dir
flag:
Terminal next lint --dir utils
Telemetry
Next.js collects completely anonymous telemetry data about general usage.
Participation in this anonymous program is optional, and you may opt-out if you'd not like to share any information.
To learn more about Telemetry, please read this document.
Next Info
next info prints relevant details about the current system which can be used to report Next.js bugs.
This information includes Operating System platform/arch/version, Binaries (Node.js, npm, Yarn, pnpm) and npm package versions (next, react, react-dom).
Running the following in your project's root directory:
Terminal next info
will give you information like this example:
Terminal
    Operating System:
      Platform: linux
      Arch: x64


Terminal
    Operating System:
      Platform: linux
      Arch: x64
      Version: #22-Ubuntu SMP Fri Nov 5 13:21:36 UTC 2021
    Binaries:
      Node: 16.13.0
      npm: 8.1.0
      Yarn: 1.22.17
      pnpm: 6.24.2
    Relevant packages:
      next: 12.0.8
      react: 17.0.2
      react-dom: 17.0.2

This information should then be pasted into GitHub Issues.


create-next-app
The easiest way to get started with Next.js is by using create-next-app. This CLI tool enables you to quickly start building a new Next.js application, with everything set up for you.
You can create a new app using the default Next.js template, or by using one of the official Next.js examples.
Interactive
You can create a new project interactively by running:
Terminal npx create-next-app@latest
Terminal yarn create next-app
Terminal pnpm create next-app
You will then be asked the following prompts:
Terminal What is your project named?  my-app
Would you like to use TypeScript?  No / Yes
Would you like to use ESLint?  No / Yes
Would you like to use Tailwind CSS?  No / Yes
Would you like to use `src/` directory?  No / Yes
Would you like to use App Router? (recommended)  No / Yes


Would you like to use App Router? (recommended)  No / Yes
Would you like to customize the default import alias?  No / Yes
Once you've answered the prompts, a new project will be created with the correct configuration depending on your answers.
Non-interactive
You can also pass command line arguments to set up a new project non-interactively.
Further, you can negate default options by prefixing them with --no- (e.g. --no-eslint).
See create-next-app --help:
Terminal Usage: create-next-app <project-directory> [options]

Options:
  -V, --version                        output the version number
  --ts, --typescript

    Initialize as a TypeScript project. (default)

  --js, --javascript

    Initialize as a JavaScript project.

  --tailwind

    Initialize with Tailwind CSS config. (default)


--tailwind

    Initialize with Tailwind CSS config. (default)

  --eslint

    Initialize with ESLint config.

  --app

    Initialize as an App Router project.

  --src-dir

    Initialize inside a `src/` directory.

  --import-alias <alias-to-configure>

    Specify import alias to use (default "@/*").

  --use-npm

    Explicitly tell the CLI to bootstrap the app using npm

  --use-pnpm

    Explicitly tell the CLI to bootstrap the app using pnpm

  --use-yarn

    Explicitly tell the CLI to bootstrap the app using Yarn

  -e, --example [name]|[github-url]


-e, --example [name]|[github-url]

    An example to bootstrap the app with. You can use an example name
    from the official Next.js repo or a public GitHub URL. The URL can use
    any branch and/or subdirectory

  --example-path <path-to-example>

    In a rare case, your GitHub URL might contain a branch name with
    a slash (e.g. bug/fix-1) and the path to the example (e.g. foo/bar).
    In this case, you must specify the path to the example separately:
    --example-path foo/bar

  --reset-preferences

    Explicitly tell the CLI to reset any stored preferences

  -h, --help                           output usage information
Why use Create Next App?


-h, --help                           output usage information
Why use Create Next App?
create-next-app allows you to create a new Next.js app within seconds. It is officially maintained by the creators of Next.js, and includes a number of benefits:
Interactive Experience: Running npx create-next-app@latest (with no arguments) launches an interactive experience that guides you through setting up a project.
Zero Dependencies: Initializing a project is as quick as one second. Create Next App has zero dependencies.
Offline Support: Create Next App will automatically detect if you're offline and bootstrap your project using your local package cache.
Support for Examples: Create Next App can bootstrap your application using an example from the Next.js examples collection (e.g. npx create-next-app --example api-routes) or any public GitHub repository.


Tested: The package is part of the Next.js monorepo and tested using the same integration test suite as Next.js itself, ensuring it works as expected with every release.


Edge Runtime
The Next.js Edge Runtime is based on standard Web APIs, it supports the following APIs:
Network APIs
APIDescriptionBlobRepresents a blobfetchFetches a resourceFetchEventRepresents a fetch eventFileRepresents a fileFormDataRepresents form dataHeadersRepresents HTTP headersRequestRepresents an HTTP requestResponseRepresents an HTTP responseURLSearchParamsRepresents URL search parametersWebSocketRepresents a websocket connection
Encoding APIs
APIDescriptionatobDecodes a base-64 encoded stringbtoaEncodes a string in base-64TextDecoderDecodes a Uint8Array into a stringTextDecoderStreamChainable decoder for streamsTextEncoderEncodes a string into a Uint8ArrayTextEncoderStreamChainable encoder for streams
Stream APIs


Stream APIs
APIDescriptionReadableStreamRepresents a readable streamReadableStreamBYOBReaderRepresents a reader of a ReadableStreamReadableStreamDefaultReaderRepresents a reader of a ReadableStreamTransformStreamRepresents a transform streamWritableStreamRepresents a writable streamWritableStreamDefaultWriterRepresents a writer of a WritableStream
Crypto APIs
APIDescriptioncryptoProvides access to the cryptographic functionality of the platformCryptoKeyRepresents a cryptographic keySubtleCryptoProvides access to common cryptographic primitives, like hashing, signing, encryption or decryption
Web Standard APIs


APIDescriptionAbortControllerAllows you to abort one or more DOM requests as and when desiredArrayRepresents an array of valuesArrayBufferRepresents a generic, fixed-length raw binary data bufferAtomicsProvides atomic operations as static methodsBigIntRepresents a whole number with arbitrary precisionBigInt64ArrayRepresents a typed array of 64-bit signed integersBigUint64ArrayRepresents a typed array of 64-bit unsigned integersBooleanRepresents a logical entity and can have two values: true and falseclearIntervalCancels a timed, repeating action which was previously established by a call to setInterval()clearTimeoutCancels a timed, repeating action which was previously established by a call to setTimeout()consoleProvides access to the browser's debugging consoleDataViewRepresents a generic view of an ArrayBufferDateRepresents a single moment in time in a platform-independent formatdecodeURIDecodes a Uniform Resource Identifier (URI) previously created by encodeURI or by a similar routinedecodeURIComponentDecodes


Identifier (URI) previously created by encodeURI or by a similar routinedecodeURIComponentDecodes a Uniform Resource Identifier (URI) component previously created by encodeURIComponent or by a similar routineDOMExceptionRepresents an error that occurs in the DOMencodeURIEncodes a Uniform Resource Identifier (URI) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the characterencodeURIComponentEncodes a Uniform Resource Identifier (URI) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the characterErrorRepresents an error when trying to execute a statement or accessing a propertyEvalErrorRepresents an error that occurs regarding the global function eval()Float32ArrayRepresents a typed array of 32-bit floating point numbersFloat64ArrayRepresents a typed array of 64-bit floating point numbersFunctionRepresents a functionInfinityRepresents the mathematical Infinity


typed array of 64-bit floating point numbersFunctionRepresents a functionInfinityRepresents the mathematical Infinity valueInt8ArrayRepresents a typed array of 8-bit signed integersInt16ArrayRepresents a typed array of 16-bit signed integersInt32ArrayRepresents a typed array of 32-bit signed integersIntlProvides access to internationalization and localization functionalityisFiniteDetermines whether a value is a finite numberisNaNDetermines whether a value is NaN or notJSONProvides functionality to convert JavaScript values to and from the JSON formatMapRepresents a collection of values, where each value may occur only onceMathProvides access to mathematical functions and constantsNumberRepresents a numeric valueObjectRepresents the object that is the base of all JavaScript objectsparseFloatParses a string argument and returns a floating point numberparseIntParses a string argument and returns an integer of the specified radixPromiseRepresents the eventual completion (or failure) of an asynchronous operation, and its resulting valueProxyRepresents


the eventual completion (or failure) of an asynchronous operation, and its resulting valueProxyRepresents an object that is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc)queueMicrotaskQueues a microtask to be executedRangeErrorRepresents an error when a value is not in the set or range of allowed valuesReferenceErrorRepresents an error when a non-existent variable is referencedReflectProvides methods for interceptable JavaScript operationsRegExpRepresents a regular expression, allowing you to match combinations of charactersSetRepresents a collection of values, where each value may occur only oncesetIntervalRepeatedly calls a function, with a fixed time delay between each callsetTimeoutCalls a function or evaluates an expression after a specified number of millisecondsSharedArrayBufferRepresents a generic, fixed-length raw binary data bufferStringRepresents a sequence of charactersstructuredCloneCreates a deep copy of a valueSymbolRepresents a unique and immutable data type that is used


a deep copy of a valueSymbolRepresents a unique and immutable data type that is used as the key of an object propertySyntaxErrorRepresents an error when trying to interpret syntactically invalid codeTypeErrorRepresents an error when a value is not of the expected typeUint8ArrayRepresents a typed array of 8-bit unsigned integersUint8ClampedArrayRepresents a typed array of 8-bit unsigned integers clamped to 0-255Uint32ArrayRepresents a typed array of 32-bit unsigned integersURIErrorRepresents an error when a global URI handling function was used in a wrong wayURLRepresents an object providing static methods used for creating object URLsURLPatternRepresents a URL patternURLSearchParamsRepresents a collection of key/value pairsWeakMapRepresents a collection of key/value pairs in which the keys are weakly referencedWeakSetRepresents a collection of objects in which each object may occur only onceWebAssemblyProvides access to WebAssembly


Next.js Specific Polyfills
AsyncLocalStorage
Environment Variables
You can use process.env to access Environment Variables for both next dev and next build.
Unsupported APIs
The Edge Runtime has some restrictions including:
Native Node.js APIs are not supported. For example, you can't read or write to the filesystem.
node_modules can be used, as long as they implement ES Modules and do not use native Node.js APIs.
Calling require directly is not allowed. Use ES Modules instead.
The following JavaScript language features are disabled, and will not work:
APIDescriptionevalEvaluates JavaScript code represented as a stringnew Function(evalString)Creates a new function with the code provided as an argumentWebAssembly.compileCompiles a WebAssembly module from a buffer sourceWebAssembly.instantiateCompiles and instantiates a WebAssembly module from a buffer source


In rare cases, your code could contain (or import) some dynamic code evaluation statements which can not be reached at runtime and which can not be removed by treeshaking.
You can relax the check to allow specific files with your Middleware or Edge API Route exported configuration:
 export const config = {
  runtime: 'edge', // for Edge API Routes only
  unstable_allowDynamic: [
    // allows a single file
    '/lib/utilities.js',
    // use a glob to allow anything in the function-bind 3rd party module
    '/node_modules/function-bind/**',
  ],
}
unstable_allowDynamic is a glob, or an array of globs, ignoring dynamic code evaluation for specific files. The globs are relative to your application root folder.
Be warned that if these statements are executed on the Edge, they will throw and cause a runtime error.


fetchNext.js extends the native Web fetch() API to allow each request on the server to set its own persistent caching semantics.
In the browser, the cache option indicates how a fetch request will interact with the browser's HTTP cache. With this extension, cache indicates how a server-side fetch request will interact with the framework's persistent HTTP cache.
You can call fetch with async and await directly within Server Components.
app/page.tsx export default async function Page() {
  // This request should be cached until manually invalidated.
  // Similar to `getStaticProps`.
  // `force-cache` is the default and can be omitted.
  const staticData = await fetch(`https://...`, { cache: 'force-cache' })

  // This request should be refetched on every request.
  // Similar to `getServerSideProps`.
  const dynamicData = await fetch(`https://...`, { cache: 'no-store' })


// This request should be cached with a lifetime of 10 seconds.
  // Similar to `getStaticProps` with the `revalidate` option.
  const revalidatedData = await fetch(`https://...`, {
    next: { revalidate: 10 },
  })

  return <div>...</div>
}
fetch(url, options)
Since Next.js extends the Web fetch() API, you can use any of the native options available.
Further, Next.js polyfills fetch on both the client and the server, so you can use fetch in both Server and Client Components.
options.cache
Configure how the request should interact with Next.js HTTP cache.
 fetch(`https://...`, { cache: 'force-cache' | 'no-store' })
force-cache (default) - Next.js looks for a matching request in its HTTP cache.


force-cache (default) - Next.js looks for a matching request in its HTTP cache.
If there is a match and it is fresh, it will be returned from the cache.
If there is no match or a stale match, Next.js will fetch the resource from the remote server and update the cache with the downloaded resource.
no-store - Next.js fetches the resource from the remote server on every request without looking in the cache, and it will not update the cache with the downloaded resource.
Good to know:
If you don't provide a cache option, Next.js will default to force-cache, unless a dynamic function such as cookies() is used, in which case it will default to no-store.
The no-cache option behaves the same way as no-store in Next.js.
options.next.revalidate
 fetch(`https://...`, { next: { revalidate: false | 0 | number } })


Set the cache lifetime of a resource (in seconds).
false - Cache the resource indefinitely. Semantically equivalent to revalidate: Infinity. The HTTP cache may evict older resources over time.
0 - Prevent the resource from being cached.
number - (in seconds) Specify the resource should have a cache lifetime of at most n seconds.
Good to know:
If an individual fetch() request sets a revalidate number lower than the default revalidate of a route, the whole route revalidation interval will be decreased.
If two fetch requests with the same URL in the same route have different revalidate values, the lower value will be used.
As a convenience, it is not necessary to set the cache option if revalidate is set to a number since 0 implies cache: 'no-store' and a positive value implies cache: 'force-cache'.


Conflicting options such as { revalidate: 0, cache: 'force-cache' } or { revalidate: 10, cache: 'no-store' } will cause an error.
Version History
VersionChangesv13.0.0fetch 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.


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.


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() })
}


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.


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.


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.


generateImageMetadataYou can use generateImageMetadata to generate different versions of one image or return multiple images for one route segment. This is useful for when you want to avoid hard-coding metadata values, such as for icons.
Parameters
generateImageMetadata function accepts the following parameters:
params (optional)
An object containing the dynamic route parameters object from the root segment down to the segment generateImageMetadata is called from.
icon.tsx export function generateImageMetadata({
  params,
}: {
  params: { slug: string }
}) {
  // ...
}
RouteURLparamsapp/shop/icon.js/shopundefinedapp/shop/[slug]/icon.js/shop/1{ slug: '1' }app/shop/[tag]/[item]/icon.js/shop/1/2{ tag: '1', item: '2' }app/shop/[...slug]/icon.js/shop/1/2{ slug: ['1', '2'] }
Returns


Returns
The generateImageMetadata function should return an array of objects containing the image's metadata such as alt and size. In addition, each item must include an id value will be passed to the props of the image generating function.
Image Metadata ObjectTypeidstring (required)altstringsize{ width: number; height: number }contentTypestring
icon.tsx import { ImageResponse } from 'next/server'

export function generateImageMetadata() {
  return [
    {
      contentType: 'image/png',
      size: { width: 48, height: 48 },
      id: 'small',
    },
    {
      contentType: 'image/png',
      size: { width: 72, height: 72 },
      id: 'medium',
    },
  ]
}

export default function Icon({ id }: { id: string }) {
  return new ImageResponse(


return new ImageResponse(
    (
      <div
        style={{
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          fontSize: 88,
          background: '#000',
          color: '#fafafa',
        }}
      >
        Icon {id}
      </div>
    )
  )
}
Examples
Using external data
This example uses the params object and external data to generate multiple Open Graph images for a route segment.
app/products/[id]/opengraph-image.tsx import { ImageResponse } from 'next/server'
import { getCaptionForImage, getOGImages } from '@/app/utils/images'

export async function generateImageMetadata({
  params,
}: {
  params: { id: string }
}) {


params,
}: {
  params: { id: string }
}) {
  const images = await getOGImages(params.id)

  return images.map((image, idx) => ({
    id: idx,
    size: { width: 1200, height: 600 },
    alt: image.text,
    contentType: 'image/png',
  }))
}

export default async function Image({
  params,
  id,
}: {
  params: { id: string }
  id: number
}) {
  const productId = params.id
  const imageId = id
  const text = await getCaptionForImage(productId, imageId)

  return new ImageResponse(
    (
      <div
        style={
          {
            // ...
          }
        }
      >
        {text}
      </div>


}
        }
      >
        {text}
      </div>
    )
  )
}
Version History
VersionChangesv13.3.0generateImageMetadata introduced.


draftModeThe draftMode function allows you to detect Draft Mode inside a Server Component.
app/page.js import { draftMode } from 'next/headers'

export default function Page() {
  const { isEnabled } = draftMode()
  return (

My Blog Post

Draft Mode is currently {isEnabled ? 'Enabled' : 'Disabled'}

  )
}
Version History
VersionChangesv13.4.0draftMode 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.


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.


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.


Metadata Object and generateMetadata OptionsThis page covers all Config-based Metadata options with generateMetadata and the static metadata object.
layout.tsx / page.tsx import { Metadata } from 'next'

// either Static metadata
export const metadata: Metadata = {
  title: '...',
}

// or Dynamic metadata
export async function generateMetadata({ params }) {
  return {
    title: '...',
  }
}
Good to know:
The metadata object and generateMetadata function exports are only supported in Server Components.
You cannot export both the metadata object and generateMetadata function from the same route segment.
The metadata object
To define static metadata, export a Metadata object from a layout.js or page.js file.
layout.tsx / page.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: '...',
  description: '...',
}


title: '...',
  description: '...',
}

export default function Page() {}
See the Metadata Fields for a complete list of supported options.
generateMetadata function
Dynamic metadata depends on dynamic information, such as the current route parameters, external data, or metadata in parent segments, can be set by exporting a generateMetadata function that returns a Metadata object.
app/products/[id]/page.tsx import { Metadata, ResolvingMetadata } from 'next'

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

export async function generateMetadata(
  { params, searchParams }: Props,
  parent: ResolvingMetadata
): Promise<Metadata> {
  // read route params
  const id = params.id

  // fetch data


// read route params
  const id = params.id

  // fetch data
  const product = await fetch(`https://.../${id}`).then((res) => res.json())

  // optionally access and extend (rather than replace) parent metadata
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: product.title,
    openGraph: {
      images: ['/some-specific-page-image.jpg', ...previousImages],
    },
  }
}

export default function Page({ params, searchParams }: Props) {}
Parameters
generateMetadata function accepts the following parameters:
props - An object containing the parameters of the current route:
params - An object containing the dynamic route parameters object from the root segment down to the segment generateMetadata is called from. Examples:


RouteURLparamsapp/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'] }
searchParams - An object containing the current URL's search params. Examples:
URLsearchParams/shop?a=1{ a: '1' }/shop?a=1&b=2{ a: '1', b: '2' }/shop?a=1&a=2{ a: ['1', '2'] }
parent - A promise of the resolved metadata from parent route segments.
Returns
generateMetadata should return a Metadata object containing one or more metadata fields.
Good to know:


generateMetadata should return a Metadata object containing one or more metadata fields.
Good to know:
If metadata doesn't depend on runtime information, it should be defined using the static metadata object rather than generateMetadata.
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.
searchParams are only available in page.js segments.
The redirect() and notFound() Next.js methods can also be used inside generateMetadata.
Metadata Fields
title
The title attribute is used to set the title of the document. It can be defined as a simple string or an optional template object.
String
layout.js / page.js export const metadata = {
  title: 'Next.js',
}
<head> output <title>Next.js</title>
Template object


}
<head> output <title>Next.js</title>
Template object
app/layout.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '...',
    default: '...',
    absolute: '...',
  },
}
Default
title.default can be used to provide a fallback title to child route segments that don't define a title.
app/layout.tsx import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    default: 'Acme',
  },
}
app/about/page.tsx import type { Metadata } from 'next'

export const metadata: Metadata = {}

// Output: <title>Acme</title>
Template
title.template can be used to add a prefix or a suffix to titles defined in child route segments.


app/layout.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
    default: 'Acme', // a default is required when creating a template
  },
}
app/about/page.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'About',
}

// Output: <title>About | Acme</title>
Good to know:
title.template applies to child route segments and not the segment it's defined in. This means:
title.default is required when you add a title.template.
title.template defined in layout.js will not apply to a title defined in a page.js of the same route segment.
title.template defined in page.js has no effect because a page is always the terminating segment (it doesn't have any children route segments).


title.template has no effect if a route has not defined a title or title.default.
Absolute
title.absolute can be used to provide a title that ignores title.template set in parent segments.
app/layout.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | Acme',
  },
}
app/about/page.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    absolute: 'About',
  },
}

// Output: <title>About</title>
Good to know:
layout.js
title (string) and title.default define the default title for child segments (that do not define their own title). It will augment title.template from the closest parent segment if it exists.
title.absolute defines the default title for child segments. It ignores title.template from parent segments.


title.absolute defines the default title for child segments. It ignores title.template from parent segments.
title.template defines a new title template for child segments.
page.js
If a page does not define its own title the closest parents resolved title will be used.
title (string) defines the routes title. It will augment title.template from the closest parent segment if it exists.
title.absolute defines the route title. It ignores title.template from parent segments.
title.template has no effect in page.js because a page is always the terminating segment of a route.
description
layout.js / page.js export const metadata = {
  description: 'The React Framework for the Web',
}
<head> output <meta name="description" content="The React Framework for the Web" />
Basic Fields
layout.js / page.js export const metadata = {
  generator: 'Next.js',
  applicationName: 'Next.js',


generator: 'Next.js',
  applicationName: 'Next.js',
  referrer: 'origin-when-cross-origin',
  keywords: ['Next.js', 'React', 'JavaScript'],
  authors: [{ name: 'Seb' }, { name: 'Josh', url: 'https://nextjs.org' }],
  colorScheme: 'dark',
  creator: 'Jiachi Liu',
  publisher: 'Sebastian Markbåge',
  formatDetection: {
    email: false,
    address: false,
    telephone: false,
  },
}
<head> output <meta name="application-name" content="Next.js" />
<meta name="author" content="Seb" />
<link rel="author" href="https://nextjs.org" />
<meta name="author" content="Josh" />
<meta name="generator" content="Next.js" />


<meta name="generator" content="Next.js" />
<meta name="keywords" content="Next.js,React,JavaScript" />
<meta name="referrer" content="origin-when-cross-origin" />
<meta name="color-scheme" content="dark" />
<meta name="creator" content="Jiachi Liu" />
<meta name="publisher" content="Sebastian Markbåge" />
<meta name="format-detection" content="telephone=no, address=no, email=no" />
metadataBase
metadataBase is a convenience option to set a base URL prefix for metadata fields that require a fully qualified URL.
metadataBase allows URL-based metadata fields defined in the current route segment and below to use a relative path instead of an otherwise required absolute URL.
The field's relative path will be composed with metadataBase to form a fully qualified URL.
If not configured, metadataBase is automatically populated with a default value.


If not configured, metadataBase is automatically populated with a default value.
layout.js / page.js export const metadata = {
  metadataBase: new URL('https://acme.com'),
  alternates: {
    canonical: '/',
    languages: {
      'en-US': '/en-US',
      'de-DE': '/de-DE',
    },
  },
  openGraph: {
    images: '/og-image.png',
  },
}
<head> output <link rel="canonical" href="https://acme.com" />
<link rel="alternate" hreflang="en-US" href="https://acme.com/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://acme.com/de-DE" />
<meta property="og:image" content="https://acme.com/og-image.png" />
Good to know:


Good to know:
metadataBase is typically set in root app/layout.js to apply to URL-based metadata fields across all routes.
All URL-based metadata fields that require absolute URLs can be configured with a metadataBase option.
metadataBase can contain a subdomain e.g. https://app.acme.com or base path e.g. https://acme.com/start/from/here
If a metadata field provides an absolute URL, metadataBase will be ignored.
Using a relative path in a URL-based metadata field without configuring a metadataBase will cause a build error.
Next.js will normalize duplicate slashes between metadataBase (e.g. https://acme.com/) and a relative field (e.g. /path) to a single slash (e.g. https://acme.com/path)
Default value
If not configured, metadataBase has a default value


Default value
If not configured, metadataBase has a default value
When VERCEL_URL is detected: https://${process.env.VERCEL_URL} otherwise it falls back to http://localhost:${process.env.PORT || 3000}.
When overriding the default, we recommend using environment variables to compute the URL. This allows configuring a URL for local development, staging, and production environments.
URL Composition
URL composition favors developer intent over default directory traversal semantics.
Trailing slashes between metadataBase and metadata fields are normalized.
An "absolute" path in a metadata field (that typically would replace the whole URL path) is treated as a "relative" path (starting from the end of metadataBase).
For example, given the following metadataBase:
app/layout.tsx import { Metadata } from 'next'

export const metadata: Metadata = {
  metadataBase: new URL('https://acme.com'),
}


metadataBase: new URL('https://acme.com'),
}
Any metadata fields that inherit the above metadataBase and set their own value will be resolved as follows:
metadata fieldResolved URL/https://acme.com./https://acme.compaymentshttps://acme.com/payments/paymentshttps://acme.com/payments./paymentshttps://acme.com/payments../paymentshttps://acme.com/paymentshttps://beta.acme.com/paymentshttps://beta.acme.com/payments
openGraph
layout.js / page.js export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    url: 'https://nextjs.org',
    siteName: 'Next.js',
    images: [
      {
        url: 'https://nextjs.org/og.png',
        width: 800,


width: 800,
        height: 600,
      },
      {
        url: 'https://nextjs.org/og-alt.png',
        width: 1800,
        height: 1600,
        alt: 'My custom alt',
      },
    ],
    locale: 'en_US',
    type: 'website',
  },
}
<head> output <meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:url" content="https://nextjs.org/" />
<meta property="og:site_name" content="Next.js" />
<meta property="og:locale" content="en_US" />
<meta property="og:image:url" content="https://nextjs.org/og.png" />
<meta property="og:image:width" content="800" />


<meta property="og:image:width" content="800" />
<meta property="og:image:height" content="600" />
<meta property="og:image:url" content="https://nextjs.org/og-alt.png" />
<meta property="og:image:width" content="1800" />
<meta property="og:image:height" content="1600" />
<meta property="og:image:alt" content="My custom alt" />
<meta property="og:type" content="website" />
layout.js / page.js export const metadata = {
  openGraph: {
    title: 'Next.js',
    description: 'The React Framework for the Web',
    type: 'article',
    publishedTime: '2023-01-01T00:00:00.000Z',
    authors: ['Seb', 'Josh'],
  },
}


authors: ['Seb', 'Josh'],
  },
}
<head> output <meta property="og:title" content="Next.js" />
<meta property="og:description" content="The React Framework for the Web" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2023-01-01T00:00:00.000Z" />
<meta property="article:author" content="Seb" />
<meta property="article:author" content="Josh" />
Good to know:
It may be more convenient to use the file-based Metadata API for Open Graph images. Rather than having to sync the config export with actual files, the file-based API will automatically generate the correct metadata for you.
robots
 import type { Metadata } from 'next'

export const metadata: Metadata = {
  robots: {
    index: false,


export const metadata: Metadata = {
  robots: {
    index: false,
    follow: true,
    nocache: true,
    googleBot: {
      index: true,
      follow: false,
      noimageindex: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
}
<head> output <meta name="robots" content="noindex, follow, nocache" />
<meta
  name="googlebot"
  content="index, nofollow, noimageindex, max-video-preview:-1, max-image-preview:large, max-snippet:-1"
/>
icons


/>
icons
Good to know: We recommend using the file-based Metadata API for icons where possible. Rather than having to sync the config export with actual files, the file-based API will automatically generate the correct metadata for you.
layout.js / page.js export const metadata = {
  icons: {
    icon: '/icon.png',
    shortcut: '/shortcut-icon.png',
    apple: '/apple-icon.png',
    other: {
      rel: 'apple-touch-icon-precomposed',
      url: '/apple-touch-icon-precomposed.png',
    },
  },
}
<head> output <link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>


href="/apple-touch-icon-precomposed.png"
/>
layout.js / page.js export const metadata = {
  icons: {
    icon: [{ url: '/icon.png' }, new URL('/icon.png', 'https://example.com')],
    shortcut: ['/shortcut-icon.png'],
    apple: [
      { url: '/apple-icon.png' },
      { url: '/apple-icon-x3.png', sizes: '180x180', type: 'image/png' },
    ],
    other: [
      {
        rel: 'apple-touch-icon-precomposed',
        url: '/apple-touch-icon-precomposed.png',
      },
    ],
  },
}
<head> output <link rel="shortcut icon" href="/shortcut-icon.png" />
<link rel="icon" href="/icon.png" />
<link rel="apple-touch-icon" href="/apple-icon.png" />
<link


<link rel="apple-touch-icon" href="/apple-icon.png" />
<link
  rel="apple-touch-icon-precomposed"
  href="/apple-touch-icon-precomposed.png"
/>
<link rel="icon" href="https://example.com/icon.png" />
<link
  rel="apple-touch-icon"
  href="/apple-icon-x3.png"
  sizes="180x180"
  type="image/png"
/>
Good to know: The msapplication-* meta tags are no longer supported in Chromium builds of Microsoft Edge, and thus no longer needed.
themeColor
Learn more about theme-color.
Simple theme color
layout.js / page.js export const metadata = {
  themeColor: 'black',
}
<head> output <meta name="theme-color" content="black" />
With media attribute
layout.js / page.js export const metadata = {
  themeColor: [


layout.js / page.js export const metadata = {
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: 'cyan' },
    { media: '(prefers-color-scheme: dark)', color: 'black' },
  ],
}
<head> output <meta name="theme-color" media="(prefers-color-scheme: light)" content="cyan" />
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />
manifest
A web application manifest, as defined in the Web Application Manifest specification.
layout.js / page.js export const metadata = {
  manifest: 'https://nextjs.org/manifest.json',
}
<head> output <link rel="manifest" href="https://nextjs.org/manifest.json" />
twitter
Learn more about the Twitter Card markup reference.
layout.js / page.js export const metadata = {


layout.js / page.js export const metadata = {
  twitter: {
    card: 'summary_large_image',
    title: 'Next.js',
    description: 'The React Framework for the Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: ['https://nextjs.org/og.png'],
  },
}
<head> output <meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />


<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
layout.js / page.js export const metadata = {
  twitter: {
    card: 'app',
    title: 'Next.js',
    description: 'The React Framework for the Web',
    siteId: '1467726470533754880',
    creator: '@nextjs',
    creatorId: '1467726470533754880',
    images: {
      url: 'https://nextjs.org/og.png',
      alt: 'Next.js Logo',
    },
    app: {
      name: 'twitter_app',
      id: {
        iphone: 'twitter_app://iphone',
        ipad: 'twitter_app://ipad',


ipad: 'twitter_app://ipad',
        googleplay: 'twitter_app://googleplay',
      },
      url: {
        iphone: 'https://iphone_url',
        ipad: 'https://ipad_url',
      },
    },
  },
}
<head> output <meta name="twitter:site:id" content="1467726470533754880" />
<meta name="twitter:creator" content="@nextjs" />
<meta name="twitter:creator:id" content="1467726470533754880" />
<meta name="twitter:title" content="Next.js" />
<meta name="twitter:description" content="The React Framework for the Web" />
<meta name="twitter:card" content="app" />
<meta name="twitter:image" content="https://nextjs.org/og.png" />
<meta name="twitter:image:alt" content="Next.js Logo" />


<meta name="twitter:image:alt" content="Next.js Logo" />
<meta name="twitter:app:name:iphone" content="twitter_app" />
<meta name="twitter:app:id:iphone" content="twitter_app://iphone" />
<meta name="twitter:app:id:ipad" content="twitter_app://ipad" />
<meta name="twitter:app:id:googleplay" content="twitter_app://googleplay" />
<meta name="twitter:app:url:iphone" content="https://iphone_url" />
<meta name="twitter:app:url:ipad" content="https://ipad_url" />
<meta name="twitter:app:name:ipad" content="twitter_app" />
<meta name="twitter:app:name:googleplay" content="twitter_app" />
viewport


<meta name="twitter:app:name:googleplay" content="twitter_app" />
viewport
Good to know: The viewport meta tag is automatically set with the following default values. Usually, manual configuration is unnecessary as the default is sufficient. However, the information is provided for completeness.
layout.js / page.js export const metadata = {
  viewport: {
    width: 'device-width',
    initialScale: 1,
    maximumScale: 1,
  },
}
<head> output <meta
  name="viewport"
  content="width=device-width, initial-scale=1, maximum-scale=1"
/>
verification
layout.js / page.js export const metadata = {
  verification: {
    google: 'google',
    yandex: 'yandex',
    yahoo: 'yahoo',
    other: {
      me: ['my-email', 'my-link'],
    },
  },


me: ['my-email', 'my-link'],
    },
  },
}
<head> output <meta name="google-site-verification" content="google" />
<meta name="y_key" content="yahoo" />
<meta name="yandex-verification" content="yandex" />
<meta name="me" content="my-email" />
<meta name="me" content="my-link" />
appleWebApp
layout.js / page.js export const metadata = {
  itunes: {
    appId: 'myAppStoreID',
    appArgument: 'myAppArgument',
  },
  appleWebApp: {
    title: 'Apple Web App',
    statusBarStyle: 'black-translucent',
    startupImage: [
      '/assets/startup/apple-touch-startup-image-768x1004.png',
      {


{
        url: '/assets/startup/apple-touch-startup-image-1536x2008.png',
        media: '(device-width: 768px) and (device-height: 1024px)',
      },
    ],
  },
}
<head> output <meta
  name="apple-itunes-app"
  content="app-id=myAppStoreID, app-argument=myAppArgument"
/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-title" content="Apple Web App" />
<link
  href="/assets/startup/apple-touch-startup-image-768x1004.png"
  rel="apple-touch-startup-image"
/>
<link
  href="/assets/startup/apple-touch-startup-image-1536x2008.png"


href="/assets/startup/apple-touch-startup-image-1536x2008.png"
  media="(device-width: 768px) and (device-height: 1024px)"
  rel="apple-touch-startup-image"
/>
<meta
  name="apple-mobile-web-app-status-bar-style"
  content="black-translucent"
/>
alternates
layout.js / page.js export const metadata = {
  alternates: {
    canonical: 'https://nextjs.org',
    languages: {
      'en-US': 'https://nextjs.org/en-US',
      'de-DE': 'https://nextjs.org/de-DE',
    },
    media: {
      'only screen and (max-width: 600px)': 'https://nextjs.org/mobile',
    },
    types: {
      'application/rss+xml': 'https://nextjs.org/rss',


types: {
      'application/rss+xml': 'https://nextjs.org/rss',
    },
  },
}
<head> output <link rel="canonical" href="https://nextjs.org" />
<link rel="alternate" hreflang="en-US" href="https://nextjs.org/en-US" />
<link rel="alternate" hreflang="de-DE" href="https://nextjs.org/de-DE" />
<link
  rel="alternate"
  media="only screen and (max-width: 600px)"
  href="https://nextjs.org/mobile"
/>
<link
  rel="alternate"
  type="application/rss+xml"
  href="https://nextjs.org/rss"
/>
appLinks
layout.js / page.js export const metadata = {
  appLinks: {
    ios: {
      url: 'https://nextjs.org/ios',


ios: {
      url: 'https://nextjs.org/ios',
      app_store_id: 'app_store_id',
    },
    android: {
      package: 'com.example.android/package',
      app_name: 'app_name_android',
    },
    web: {
      url: 'https://nextjs.org/web',
      should_fallback: true,
    },
  },
}
<head> output <meta property="al:ios:url" content="https://nextjs.org/ios" />
<meta property="al:ios:app_store_id" content="app_store_id" />
<meta property="al:android:package" content="com.example.android/package" />
<meta property="al:android:app_name" content="app_name_android" />
<meta property="al:web:url" content="https://nextjs.org/web" />


<meta property="al:web:url" content="https://nextjs.org/web" />
<meta property="al:web:should_fallback" content="true" />
archives
Describes a collection of records, documents, or other materials of historical interest (source).
layout.js / page.js export const metadata = {
  archives: ['https://nextjs.org/13'],
}
<head> output <link rel="archives" href="https://nextjs.org/13" />
assets
layout.js / page.js export const metadata = {
  assets: ['https://nextjs.org/assets'],
}
<head> output <link rel="assets" href="https://nextjs.org/assets" />
bookmarks
layout.js / page.js export const metadata = {
  bookmarks: ['https://nextjs.org/13'],
}


bookmarks: ['https://nextjs.org/13'],
}
<head> output <link rel="bookmarks" href="https://nextjs.org/13" />
category
layout.js / page.js export const metadata = {
  category: 'technology',
}
<head> output <meta name="category" content="technology" />
other
All metadata options should be covered using the built-in support. However, there may be custom metadata tags specific to your site, or brand new metadata tags just released. You can use the other option to render any custom metadata tag.
layout.js / page.js export const metadata = {
  other: {
    custom: 'meta',
  },
}
<head> output <meta name="custom" content="meta" />
Unsupported Metadata
The following metadata types do not currently have built-in support. However, they can still be rendered in the layout or page itself.


MetadataRecommendation<meta http-equiv="...">Use appropriate HTTP Headers via redirect(), Middleware, Security Headers<base>Render the tag in the layout or page itself.<noscript>Render the tag in the layout or page itself.<style>Learn more about styling in Next.js.<script>Learn more about using scripts.<link rel="stylesheet" />import stylesheets directly in the layout or page itself.<link rel="preload />Use ReactDOM preload method<link rel="preconnect" />Use ReactDOM preconnect method<link rel="dns-prefetch" />Use ReactDOM prefetchDNS method
Resource hints
The <link> element has a number of rel keywords that can be used to hint to the browser that a external resource is likely to be needed. The browser uses this information to apply preloading optimizations depending on the keyword.
While the Metadata API doesn't directly support these hints, you can use new ReactDOM methods to safely insert them into the <head> of the document.


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.


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() })
}


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.


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.


cookiesThe cookies function allows you to read the HTTP incoming request cookies from a Server Component or write outgoing request cookies in a Server Action or Route Handler.
Good to know: cookies() 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.
cookies().get(name)
A method that takes a cookie name and returns an object with name and value. If a cookie with name isn't found, it returns undefined. If multiple cookies match, it will only return the first match.
app/page.js import { cookies } from 'next/headers'

export default function Page() {
  const cookieStore = cookies()
  const theme = cookieStore.get('theme')
  return '...'
}
cookies().getAll()


return '...'
}
cookies().getAll()
A method that is similar to get, but returns a list of all the cookies with a matching name. If name is unspecified, it returns all the available cookies.
app/page.js import { cookies } from 'next/headers'

export default function Page() {
  const cookieStore = cookies()
  return cookieStore.getAll().map((cookie) => (

Name: {cookie.name}

Value: {cookie.value}

  ))
}
cookies().has(name)
A method that takes a cookie name and returns a boolean based on if the cookie exists (true) or not (false).
app/page.js import { cookies } from 'next/headers'

export default function Page() {
  const cookiesList = cookies()


export default function Page() {
  const cookiesList = cookies()
  const hasCookie = cookiesList.has('theme')
  return '...'
}
cookies().set(name, value, options)
A method that takes a cookie name, value, and options and sets the outgoing request cookie.
Good to know: .set() is only available in a Server Action or Route Handler.
app/actions.js 'use server'

import { cookies } from 'next/headers'

async function create(data) {
  cookies().set('name', 'lee')
  // or
  cookies().set('name', 'lee', { secure: true })
  // or
  cookies().set({
    name: 'name',
    value: 'lee',
    httpOnly: true,
    path: '/',
  })
}
Deleting cookies


httpOnly: true,
    path: '/',
  })
}
Deleting cookies
To "delete" a cookie, you must set a new cookie with the same name and an empty value. You can also set the maxAge to 0 to expire the cookie immediately.
Good to know: .set() is only available in a Server Action or Route Handler.
app/actions.js 'use server'

import { cookies } from 'next/headers'

async function create(data) {
  cookies().set({
    name: 'name',
    value: '',
    expires: new Date('2016-10-05'),
    path: '/', // For all paths
  })
}
You can only set cookies that belong to the same domain from which .set() is called. Additionally, the code must be executed on the same protocol (HTTP or HTTPS) as the cookie you want to update.


Version History
VersionChangesv13.0.0cookies 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.


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