A callback function that is invoked when the image is loaded.
The load event might occur before the image placeholder is removed and the image is fully decoded. If you want to wait until the image has fully loaded, use onLoadingComplete instead.
Good to know: Using props like onLoad, which accept a function, require using Client Components to serialize the provided function.
onError
 <Image onError={(e) => console.error(e.target.id)} />
A callback function that is invoked if the image fails to load.
Good to know: Using props like onError, which accept a function, require using Client Components to serialize the provided function.
loading
Recommendation: This property is only meant for advanced use cases. Switching an image to load with eager will normally hurt performance. We recommend using the priority property instead, which will eagerly preload the image.
 loading = 'lazy' // {lazy} | {eager}


loading = 'lazy' // {lazy} | {eager}
The loading behavior of the image. Defaults to lazy.
When lazy, defer loading the image until it reaches a calculated distance from
the viewport.
When eager, load the image immediately.
Learn more about the loading attribute.
blurDataURL
A Data URL to
be used as a placeholder image before the src image successfully loads. Only takes effect when combined
with placeholder="blur".
Must be a base64-encoded image. It will be enlarged and blurred, so a very small image (10px or
less) is recommended. Including larger images as placeholders may harm your application performance.
Try it out:
Demo the default blurDataURL prop
Demo the shimmer effect with blurDataURL prop
Demo the color effect with blurDataURL prop
You can also generate a solid color Data URL to match the image.
unoptimized


You can also generate a solid color Data URL to match the image.
unoptimized
 unoptimized = {false} // {false} | {true}
When true, the source image will be served as-is instead of changing quality,
size, or format. Defaults to false.
 import Image from 'next/image'

const UnoptimizedImage = (props) => {
  return <Image {...props} unoptimized />
}
Since Next.js 12.3.0, this prop can be assigned to all images by updating next.config.js with the following configuration:
next.config.js module.exports = {
  images: {
    unoptimized: true,
  },
}
Other Props
Other properties on the <Image /> component will be passed to the underlying
img element with the exception of the following:
srcSet. Use Device Sizes instead.
decoding. It is always "async".
Configuration Options


decoding. It is always "async".
Configuration Options
In addition to props, you can configure the Image Component in next.config.js. The following options are available:
remotePatterns
To protect your application from malicious users, configuration is required in order to use external images. This ensures that only external images from your account can be served from the Next.js Image Optimization API. These external images can be configured with the remotePatterns property in your next.config.js file, as shown below:
next.config.js module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/account123/**',
      },
    ],
  },
}


pathname: '/account123/**',
      },
    ],
  },
}
Good to know: The example above will ensure the src property of next/image must start with https://example.com/account123/. Any other protocol, hostname, port, or unmatched path will respond with 400 Bad Request.
Below is another example of the remotePatterns property in the next.config.js file:
next.config.js module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: '**.example.com',
      },
    ],
  },
}
Good to know: The example above will ensure the src property of next/image must start with https://img1.example.com or https://me.avatar.example.com or any number of subdomains. Any other protocol or unmatched hostname will respond with 400 Bad Request.


Wildcard patterns can be used for both pathname and hostname and have the following syntax:
* match a single path segment or subdomain
** match any number of path segments at the end or subdomains at the beginning
The ** syntax does not work in the middle of the pattern.
domains
Warning: We recommend configuring strict remotePatterns instead of domains in order to protect your application from malicious users. Only use domains if you own all the content served from the domain.
Similar to remotePatterns, the domains configuration can be used to provide a list of allowed hostnames for external images.
However, the domains configuration does not support wildcard pattern matching and it cannot restrict protocol, port, or pathname.
Below is an example of the domains property in the next.config.js file:
next.config.js module.exports = {
  images: {
    domains: ['assets.acme.com'],
  },
}
loaderFile


domains: ['assets.acme.com'],
  },
}
loaderFile
If you want to use a cloud provider to optimize images instead of using the Next.js built-in Image Optimization API, you can configure the loaderFile in your next.config.js like the following:
next.config.js module.exports = {
  images: {
    loader: 'custom',
    loaderFile: './my/image/loader.js',
  },
}
This must point to a file relative to the root of your Next.js application. The file must export a default function that returns a string, for example:
 'use client'

export default function myImageLoader({ src, width, quality }) {
  return `https://example.com/${src}?w=${width}&q=${quality || 75}`
}
Alternatively, you can use the loader prop to configure each instance of next/image.
Examples:
Custom Image Loader Configuration


Examples:
Custom Image Loader Configuration
Good to know: Customizing the image loader file, which accepts a function, require using Client Components to serialize the provided function.
Advanced
The following configuration is for advanced use cases and is usually not necessary. If you choose to configure the properties below, you will override any changes to the Next.js defaults in future updates.
deviceSizes
If you know the expected device widths of your users, you can specify a list of device width breakpoints using the deviceSizes property in next.config.js. These widths are used when the next/image component uses sizes prop to ensure the correct image is served for user's device.
If no configuration is provided, the default below is used.
next.config.js module.exports = {
  images: {
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
  },
}


},
}
imageSizes
You can specify a list of image widths using the images.imageSizes property in your next.config.js file. These widths are concatenated with the array of device sizes to form the full array of sizes used to generate image srcsets.
The reason there are two separate lists is that imageSizes is only used for images which provide a sizes prop, which indicates that the image is less than the full width of the screen. Therefore, the sizes in imageSizes should all be smaller than the smallest size in deviceSizes.
If no configuration is provided, the default below is used.
next.config.js module.exports = {
  images: {
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
  },
}
formats
The default Image Optimization API will automatically detect the browser's supported image formats via the request's Accept header.


If the Accept head matches more than one of the configured formats, the first match in the array is used. Therefore, the array order matters. If there is no match (or the source image is animated), the Image Optimization API will fallback to the original image's format.
If no configuration is provided, the default below is used.
next.config.js module.exports = {
  images: {
    formats: ['image/webp'],
  },
}
You can enable AVIF support with the following configuration.
next.config.js module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}
Good to know:
AVIF generally takes 20% longer to encode but it compresses 20% smaller compared to WebP. This means that the first time an image is requested, it will typically be slower and then subsequent requests that are cached will be faster.


If you self-host with a Proxy/CDN in front of Next.js, you must configure the Proxy to forward the Accept header.
Caching Behavior
The following describes the caching algorithm for the default loader. For all other loaders, please refer to your cloud provider's documentation.
Images are optimized dynamically upon request and stored in the <distDir>/cache/images directory. The optimized image file will be served for subsequent requests until the expiration is reached. When a request is made that matches a cached but expired file, the expired image is served stale immediately. Then the image is optimized again in the background (also called revalidation) and saved to the cache with the new expiration date.
The cache status of an image can be determined by reading the value of the x-nextjs-cache response header. The possible values are the following:
MISS - the path is not in the cache (occurs at most once, on the first visit)


STALE - the path is in the cache but exceeded the revalidate time so it will be updated in the background
HIT - the path is in the cache and has not exceeded the revalidate time
The expiration (or rather Max Age) is defined by either the minimumCacheTTL configuration or the upstream image Cache-Control header, whichever is larger. Specifically, the max-age value of the Cache-Control header is used. If both s-maxage and max-age are found, then s-maxage is preferred. The max-age is also passed-through to any downstream clients including CDNs and browsers.
You can configure minimumCacheTTL to increase the cache duration when the upstream image does not include Cache-Control header or the value is very low.
You can configure deviceSizes and imageSizes to reduce the total number of possible generated images.
You can configure formats to disable multiple formats in favor of a single image format.
minimumCacheTTL


minimumCacheTTL
You can configure the Time to Live (TTL) in seconds for cached optimized images. In many cases, it's better to use a Static Image Import which will automatically hash the file contents and cache the image forever with a Cache-Control header of immutable.
next.config.js module.exports = {
  images: {
    minimumCacheTTL: 60,
  },
}
The expiration (or rather Max Age) of the optimized image is defined by either the minimumCacheTTL or the upstream image Cache-Control header, whichever is larger.
If you need to change the caching behavior per image, you can configure headers to set the Cache-Control header on the upstream image (e.g. /some-asset.jpg, not /_next/image itself).


There is no mechanism to invalidate the cache at this time, so its best to keep minimumCacheTTL low. Otherwise you may need to manually change the src prop or delete <distDir>/cache/images.
disableStaticImages
The default behavior allows you to import static files such as import icon from './icon.png and then pass that to the src property.
In some cases, you may wish to disable this feature if it conflicts with other plugins that expect the import to behave differently.
You can disable static image imports inside your next.config.js:
next.config.js module.exports = {
  images: {
    disableStaticImages: true,
  },
}
dangerouslyAllowSVG


disableStaticImages: true,
  },
}
dangerouslyAllowSVG
The default loader does not optimize SVG images for a few reasons. First, SVG is a vector format meaning it can be resized losslessly. Second, SVG has many of the same features as HTML/CSS, which can lead to vulnerabilities without proper Content Security Policy (CSP) headers.
If you need to serve SVG images with the default Image Optimization API, you can set dangerouslyAllowSVG inside your next.config.js:
next.config.js module.exports = {
  images: {
    dangerouslyAllowSVG: true,
    contentDispositionType: 'attachment',
    contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
  },
}
In addition, it is strongly recommended to also set contentDispositionType to force the browser to download the image, as well as contentSecurityPolicy to prevent scripts embedded in the image from executing.
Animated Images


Animated Images
The default loader will automatically bypass Image Optimization for animated images and serve the image as-is.
Auto-detection for animated files is best-effort and supports GIF, APNG, and WebP. If you want to explicitly bypass Image Optimization for a given animated image, use the unoptimized prop.
Known Browser Bugs
This next/image component uses browser native lazy loading, which may fallback to eager loading for older browsers before Safari 15.4. When using the blur-up placeholder, older browsers before Safari 12 will fallback to empty placeholder. When using styles with width/height of auto, it is possible to cause Layout Shift on older browsers before Safari 15 that don't preserve the aspect ratio. For more details, see this MDN video.
Safari 15 and 16 display a gray border while loading. Safari 16.4 fixed this issue. Possible solutions:


Use CSS @supports (font: -apple-system-body) and (-webkit-appearance: none) { img[loading="lazy"] { clip-path: inset(0.6px) } }
Use priority if the image is above the fold
Firefox 67+ displays a white background while loading. Possible solutions:
Enable AVIF formats
Use placeholder="blur"
Version History


VersionChangesv13.2.0contentDispositionType configuration added.v13.0.6ref prop added.v13.0.0The next/image import was renamed to next/legacy/image. The next/future/image import was renamed to next/image. A codemod is available to safely and automatically rename your imports. <span> wrapper removed. layout, objectFit, objectPosition, lazyBoundary, lazyRoot props removed. alt is required. onLoadingComplete receives reference to img element. Built-in loader config removed.v12.3.0remotePatterns and unoptimized configuration is stable.v12.2.0Experimental remotePatterns and experimental unoptimized configuration added. layout="raw" removed.v12.1.1style prop added. Experimental support for layout="raw" added.v12.1.0dangerouslyAllowSVG and contentSecurityPolicy configuration added.v12.0.9lazyRoot prop added.v12.0.0formats configuration added.AVIF support


prop added.v12.0.0formats configuration added.AVIF support added.Wrapper <div> changed to <span>.v11.1.0onLoadingComplete and lazyBoundary props added.v11.0.0src prop support for static import.placeholder prop added.blurDataURL prop added.v10.0.5loader prop added.v10.0.1layout prop added.v10.0.0next/image introduced.


<Link>
Examples
Hello World
Active className on Link
<Link> is a React component that extends the HTML <a> element to provide prefetching and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.
app/page.tsx import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}
Props
Here's a summary of the props available for the Link Component:
PropExampleTypeRequiredhrefhref="/dashboard"String or ObjectYesreplacereplace={false}Boolean-prefetchprefetch={false}Boolean-
Good to know: <a> tag attributes such as className or target="_blank" can be added to <Link> as props and will be passed to the underlying <a> element.
href (required)
The path or URL to navigate to.
 <Link href="/dashboard">Dashboard</Link>


The path or URL to navigate to.
 <Link href="/dashboard">Dashboard</Link>
href can also accept an object, for example:
 // Navigate to /about?name=test
<Link
  href={{
    pathname: '/about',
    query: { name: 'test' },
  }}
>
  About
</Link>
replace
Defaults to false. When true, next/link will replace the current history state instead of adding a new URL into the browser’s history stack.
app/page.tsx import Link from 'next/link'

export default function Page() {
  return (
    <Link href="/dashboard" replace>
      Dashboard
    </Link>
  )
}
prefetch


Dashboard
    </Link>
  )
}
prefetch
Defaults to true. When true, next/link will prefetch the page (denoted by the href) in the background. This is useful for improving the performance of client-side navigations. Any <Link /> in the viewport (initially or through scroll) will be preloaded.
Prefetch can be disabled by passing prefetch={false}. Prefetching is only enabled in production.
app/page.tsx import Link from 'next/link'

export default function Page() {
  return (
    <Link href="/dashboard" prefetch={false}>
      Dashboard
    </Link>
  )
}
Examples
Linking to Dynamic Routes
For dynamic routes, it can be handy to use template literals to create the link's path.


For dynamic routes, it can be handy to use template literals to create the link's path.
For example, you can generate a list of links to the dynamic route app/blog/[slug]/page.js:app/blog/page.js import Link from 'next/link'

function Page({ posts }) {
  return (

      {posts.map((post) => (

          <Link href={`/blog/${post.slug}`}>{post.title}</Link>

      ))}

  )
}
Middleware


))}
    </ul>
  )
}
Middleware
It's common to use Middleware for authentication or other purposes that involve rewriting the user to a different page. In order for the <Link /> component to properly prefetch links with rewrites via Middleware, you need to tell Next.js both the URL to display and the URL to prefetch. This is required to avoid un-necessary fetches to middleware to know the correct route to prefetch.
For example, if you want to serve a /dashboard route that has authenticated and visitor views, you may add something similar to the following in your Middleware to redirect the user to the correct page:
middleware.js export function middleware(req) {
  const nextUrl = req.nextUrl
  if (nextUrl.pathname === '/dashboard') {
    if (req.cookies.authToken) {
      return NextResponse.rewrite(new URL('/auth/dashboard', req.url))
    } else {


} else {
      return NextResponse.rewrite(new URL('/public/dashboard', req.url))
    }
  }
}
In this case, you would want to use the following code in your <Link /> component:
 import Link from 'next/link'
import useIsAuthed from './hooks/useIsAuthed'

export default function Page() {
  const isAuthed = useIsAuthed()
  const path = isAuthed ? '/auth/dashboard' : '/dashboard'
  return (
    <Link as="/dashboard" href={path}>
      Dashboard
    </Link>
  )
}
Version History


Dashboard
    </Link>
  )
}
Version History
VersionChangesv13.0.0No longer requires a child <a> tag. A codemod is provided to automatically update your codebase.v10.0.0href props pointing to a dynamic route are automatically resolved and no longer require an as prop.v8.0.0Improved prefetching performance.v1.0.0next/link introduced.


Font Module
This API reference will help you understand how to use next/font/google and next/font/local. For features and usage, please see the Optimizing Fonts page.
Font Function Arguments
For usage, review Google Fonts and Local Fonts.
Keyfont/googlefont/localTypeRequiredsrcString or Array of ObjectsYesweightString or ArrayRequired/OptionalstyleString or Array-subsetsArray of Strings-axesArray of Strings-displayString-preloadBoolean-fallbackArray of Strings-adjustFontFallbackBoolean or String-variableString-declarationsArray of Objects-
src
The path of the font file as a string or an array of objects (with type Array<{path: string, weight?: string, style?: string}>) relative to the directory where the font loader function is called.
Used in next/font/local
Required
Examples:
src:'./fonts/my-font.woff2' where my-font.woff2 is placed in a directory named fonts inside the app directory


src:[{path: './inter/Inter-Thin.ttf', weight: '100',},{path: './inter/Inter-Regular.ttf',weight: '400',},{path: './inter/Inter-Bold-Italic.ttf', weight: '700',style: 'italic',},]
if the font loader function is called in app/page.tsx using src:'../styles/fonts/my-font.ttf', then my-font.ttf is placed in styles/fonts at the root of the project
weight
The font weight with the following possibilities:
A string with possible values of the weights available for the specific font or a range of values if it's a variable font
An array of weight values if the font is not a variable google font. It applies to next/font/google only.
Used in next/font/google and next/font/local
Required if the font being used is not variable
Examples:


Required if the font being used is not variable
Examples:
weight: '400': A string for a single weight value - for the font Inter, the possible values are '100', '200', '300', '400', '500', '600', '700', '800', '900' or 'variable' where 'variable' is the default)
weight: '100 900': A string for the range between 100 and 900 for a variable font
weight: ['100','400','900']: An array of 3 possible values for a non variable font
style
The font style with the following possibilities:
A string value with default value of 'normal'
An array of style values if the font is not a variable google font. It applies to next/font/google only.
Used in next/font/google and next/font/local
Optional
Examples:
style: 'italic': A string - it can be normal or italic for next/font/google


style: 'italic': A string - it can be normal or italic for next/font/google
style: 'oblique': A string - it can take any value for next/font/local but is expected to come from standard font styles
style: ['italic','normal']: An array of 2 values for next/font/google - the values are from normal and italic
subsets
The font subsets defined by an array of string values with the names of each subset you would like to be preloaded. Fonts specified via subsets will have a link preload tag injected into the head when the preload option is true, which is the default.
Used in next/font/google
Optional
Examples:
subsets: ['latin']: An array with the subset latin
You can find a list of all subsets on the Google Fonts page for your font.
axes


You can find a list of all subsets on the Google Fonts page for your font.
axes
Some variable fonts have extra axes that can be included. By default, only the font weight is included to keep the file size down. The possible values of axes depend on the specific font.
Used in next/font/google
Optional
Examples:
axes: ['slnt']: An array with value slnt for the Inter variable font which has slnt as additional axes as shown here. You can find the possible axes values for your font by using the filter on the Google variable fonts page and looking for axes other than wght
display
The font display with possible string values of 'auto', 'block', 'swap', 'fallback' or 'optional' with default value of 'swap'.
Used in next/font/google and next/font/local
Optional
Examples:
display: 'optional': A string assigned to the optional value
preload


Optional
Examples:
display: 'optional': A string assigned to the optional value
preload
A boolean value that specifies whether the font should be preloaded or not. The default is true.
Used in next/font/google and next/font/local
Optional
Examples:
preload: false
fallback
The fallback font to use if the font cannot be loaded. An array of strings of fallback fonts with no default.
Optional
Used in next/font/google and next/font/local
Examples:
fallback: ['system-ui', 'arial']: An array setting the fallback fonts to system-ui or arial
adjustFontFallback
For next/font/google: A boolean value that sets whether an automatic fallback font should be used to reduce Cumulative Layout Shift. The default is true.


For next/font/local: A string or boolean false value that sets whether an automatic fallback font should be used to reduce Cumulative Layout Shift. The possible values are 'Arial', 'Times New Roman' or false. The default is 'Arial'.
Used in next/font/google and next/font/local
Optional
Examples:
adjustFontFallback: false: for ``next/font/google`
adjustFontFallback: 'Times New Roman': for next/font/local
variable
A string value to define the CSS variable name to be used if the style is applied with the CSS variable method.
Used in next/font/google and next/font/local
Optional
Examples:
variable: '--my-font': The CSS variable --my-font is declared
declarations
An array of font face descriptor key-value pairs that define the generated @font-face further.
Used in next/font/local
Optional
Examples:
declarations: [{ prop: 'ascent-override', value: '90%' }]


declarations: [{ prop: 'ascent-override', value: '90%' }]
Applying Styles
You can apply the font styles in three ways:
className
style
CSS Variables
className
Returns a read-only CSS className for the loaded font to be passed to an HTML element.

Hello, Next.js!

style
Returns a read-only CSS style object for the loaded font to be passed to an HTML element, including style.fontFamily to access the font family name and fallback fonts.

Hello World

CSS Variables
If you would like to set your styles in an external style sheet and specify additional options there, use the CSS variable method.
In addition to importing the font, also import the CSS file where the CSS variable is defined and set the variable option of the font loader object as follows:


app/page.tsx import { Inter } from 'next/font/google'
import styles from '../styles/component.module.css'

const inter = Inter({
  variable: '--font-inter',
})
To use the font, set the className of the parent container of the text you would like to style to the font loader's variable value and the className of the text to the styles property from the external CSS file.
app/page.tsx

Hello World

Define the text selector class in the component.module.css CSS file as follows:
styles/component.module.css .text {
  font-family: var(--font-inter);
  font-weight: 200;
  font-style: italic;
}


font-weight: 200;
  font-style: italic;
}
In the example above, the text Hello World is styled using the Inter font and the generated font fallback with font-weight: 200 and font-style: italic.
Using a font definitions file
Every time you call the localFont or Google font function, that font will be hosted as one instance in your application. Therefore, if you need to use the same font in multiple places, you should load it in one place and import the related font object where you need it. This is done using a font definitions file.
For example, create a fonts.ts file in a styles folder at the root of your app directory.
Then, specify your font definitions as follows:
styles/fonts.ts import { Inter, Lora, Source_Sans_Pro } from 'next/font/google'
import localFont from 'next/font/local'

// define your variable fonts
const inter = Inter()


// define your variable fonts
const inter = Inter()
const lora = Lora()
// define 2 weights of a non-variable font
const sourceCodePro400 = Source_Sans_Pro({ weight: '400' })
const sourceCodePro700 = Source_Sans_Pro({ weight: '700' })
// define a custom local font where GreatVibes-Regular.ttf is stored in the styles folder
const greatVibes = localFont({ src: './GreatVibes-Regular.ttf' })

export { inter, lora, sourceCodePro400, sourceCodePro700, greatVibes }
You can now use these definitions in your code as follows:
app/page.tsx import { inter, lora, sourceCodePro700, greatVibes } from '../styles/fonts'

export default function Page() {
  return (
    <div>


export default function Page() {
  return (

Hello world using Inter font

Hello world using Lora font

        Hello world using Source_Sans_Pro font with weight 700

My title in Great Vibes font

  )
}
To make it easier to access the font definitions in your code, you can define a path alias in your tsconfig.json or jsconfig.json files as follows:
tsconfig.json {
  "compilerOptions": {
    "paths": {
      "@/fonts": ["./styles/fonts"]
    }
  }
}
You can now import any font definition as follows:


}
  }
}
You can now import any font definition as follows:
app/about/page.tsx import { greatVibes, sourceCodePro400 } from '@/fonts'
Version Changes
VersionChangesv13.2.0@next/font renamed to next/font. Installation no longer required.v13.0.0@next/font was added.


loading.jsA loading file can create instant loading states built on Suspense.
By default, this file is a Server Component - but can also be used as a Client Component through the "use client" directive.
app/feed/loading.tsx export default function Loading() {
  // Or a custom loading skeleton component
  return <p>'Loading...'</p>
}
Loading UI components do not accept any parameters.
Good to know
While designing loading UI, you may find it helpful to use the React Developer Tools to manually toggle Suspense boundaries.
Version History
VersionChangesv13.0.0loading introduced.


page.jsA page is UI that is unique to a route.
app/blog/[slug]/page.tsx export default function Page({
  params,
  searchParams,
}: {
  params: { slug: string }
  searchParams: { [key: string]: string | string[] | undefined }
}) {
  return
My Page

}
Props
params (optional)
An object containing the dynamic route parameters from the root segment down to that page. For example:
ExampleURLparamsapp/shop/[slug]/page.js/shop/1{ slug: '1' }app/shop/[category]/[item]/page.js/shop/1/2{ category: '1', item: '2' }app/shop/[...slug]/page.js/shop/1/2{ slug: ['1', '2'] }
searchParams (optional)


searchParams (optional)
An object containing the search parameters of the current URL. For example:
URLsearchParams/shop?a=1{ a: '1' }/shop?a=1&b=2{ a: '1', b: '2' }/shop?a=1&a=2{ a: ['1', '2'] }
Good to know:
searchParams is a Dynamic API whose values cannot be known ahead of time. Using it will opt the page into dynamic rendering at request time.
searchParams returns a plain JavaScript object and not a URLSearchParams instance.
Version History
VersionChangesv13.0.0page introduced.


Route Segment ConfigThe Route Segment options allows you configure the behavior of a Page, Layout, or Route Handler by directly exporting the following variables:
OptionTypeDefaultdynamic'auto' | 'force-dynamic' | 'error' | 'force-static''auto'dynamicParamsbooleantruerevalidatefalse | 'force-cache' | 0 | numberfalsefetchCache'auto' | 'default-cache' | 'only-cache' | 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store''auto'runtime'nodejs' | 'edge''nodejs'preferredRegion'auto' | 'global' | 'home' | string | string[]'auto'maxDurationnumberSet by deployment platform
layout.tsx / page.tsx / route.ts export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'


export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
export const maxDuration = 5

export default function MyComponent() {}
Good to know:
The values of the config options currently need be statically analyzable. For example revalidate = 600 is valid, but revalidate = 60 * 10 is not.
Options
dynamic
Change the dynamic behavior of a layout or page to fully static or fully dynamic.
layout.tsx / page.tsx / route.ts export const dynamic = 'auto'
// 'auto' | 'force-dynamic' | 'error' | 'force-static'


// 'auto' | 'force-dynamic' | 'error' | 'force-static'
Good to know: The new model in the app directory favors granular caching control at the fetch request level over the binary all-or-nothing model of getServerSideProps and getStaticProps at the page-level in the pages directory. The dynamic option is a way to opt back in to the previous model as a convenience and provides a simpler migration path.
'auto' (default): The default option to cache as much as possible without preventing any components from opting into dynamic behavior.
'force-dynamic': Force dynamic rendering and dynamic data fetching of a layout or page by disabling all caching of fetch requests and always revalidating. This option is equivalent to:
getServerSideProps() in the pages directory.
Setting the option of every fetch() request in a layout or page to { cache: 'no-store', next: { revalidate: 0 } }.


Setting the segment config to export const fetchCache = 'force-no-store'
'error': Force static rendering and static data fetching of a layout or page by causing an error if any components use dynamic functions or dynamic fetches. This option is equivalent to:
getStaticProps() in the pages directory.
Setting the option of every fetch() request in a layout or page to { cache: 'force-cache' }.
Setting the segment config to fetchCache = 'only-cache', dynamicParams = false.
dynamic = 'error' changes the default of dynamicParams from true to false. You can opt back into dynamically rendering pages for dynamic params not generated by generateStaticParams by manually setting dynamicParams = true.
'force-static': Force static rendering and static data fetching of a layout or page by forcing cookies(), headers() and useSearchParams() to return empty values.
Good to know:


Good to know:
Instructions on how to migrate from getServerSideProps and getStaticProps to dynamic: 'force-dynamic' and dynamic: 'error' can be found in the upgrade guide.
dynamicParams
Control what happens when a dynamic segment is visited that was not generated with generateStaticParams.
layout.tsx / page.tsx export const dynamicParams = true // true | false,
true (default): Dynamic segments not included in generateStaticParams are generated on demand.
false: Dynamic segments not included in generateStaticParams will return a 404.
Good to know:
This option replaces the fallback: true | false | blocking option of getStaticPaths in the pages directory.
When dynamicParams = true, the segment uses Streaming Server Rendering.
If the dynamic = 'error' and dynamic = 'force-static' are used, it'll change the default of dynamicParams to false.
revalidate


revalidate
Set the default revalidation time for a layout or page. This option does not override the revalidate value set by individual fetch requests.
layout.tsx / page.tsx / route.ts export const revalidate = false
// false | 'force-cache' | 0 | number
false: (default) The default heuristic to cache any fetch requests that set their cache option to 'force-cache' or are discovered before a dynamic function is used. Semantically equivalent to revalidate: Infinity which effectively means the resource should be cached indefinitely. It is still possible for individual fetch requests to use cache: 'no-store' or revalidate: 0 to avoid being cached and make the route dynamically rendered. Or set revalidate to a positive number lower than the route default to increase the revalidation frequency of a route.


0: Ensure a layout or page is always dynamically rendered even if no dynamic functions or dynamic data fetches are discovered. This option changes the default of fetch requests that do not set a cache option to 'no-store' but leaves fetch requests that opt into 'force-cache' or use a positive revalidate as is.
number: (in seconds) Set the default revalidation frequency of a layout or page to n seconds.
Revalidation Frequency
The lowest revalidate across each layout and page of a single route will determine the revalidation frequency of the entire route. This ensures that child pages are revalidated as frequently as their parent layouts.
Individual fetch requests can set a lower revalidate than the route's default revalidate to increase the revalidation frequency of the entire route. This allows you to dynamically opt-in to more frequent revalidation for certain routes based on some criteria.
fetchCache


fetchCache
This is an advanced option that should only be used if you specifically need to override the default behavior.By default, Next.js will cache any fetch() requests that are reachable before any dynamic functions are used and will not cache fetch requests that are discovered after dynamic functions are used.fetchCache allows you to override the default cache option of all fetch requests in a layout or page.layout.tsx / page.tsx / route.ts export const fetchCache = 'auto'
// 'auto' | 'default-cache' | 'only-cache'
// 'force-cache' | 'force-no-store' | 'default-no-store' | 'only-no-store'
'auto' (default)- The default option to cache fetch requests before dynamic functions with the cache option they provide and not cache fetch requests after dynamic functions.


'default-cache': Allow any cache option to be passed to fetch but if no option is provided then set the cache option to 'force-cache'. This means that even fetch requests after dynamic functions are considered static.
'only-cache': Ensure all fetch requests opt into caching by changing the default to cache: 'force-cache' if no option is provided and causing an error if any fetch requests use cache: 'no-store'.
'force-cache': Ensure all fetch requests opt into caching by setting the cache option of all fetch requests to 'force-cache'.
'default-no-store': Allow any cache option to be passed to fetch but if no option is provided then set the cache option to 'no-store'. This means that even fetch requests before dynamic functions are considered dynamic.


'only-no-store': Ensure all fetch requests opt out of caching by changing the default to cache: 'no-store' if no option is provided and causing an error if any fetch requests use cache: 'force-cache'
'force-no-store': Ensure all fetch requests opt out of caching by setting the cache option of all fetch requests to 'no-store'. This forces all fetch requests to be re-fetched every request even if they provide a 'force-cache' option.
Cross-route segment behavior
Any options set across each layout and page of a single route need to be compatible with each other.
If both the 'only-cache' and 'force-cache' are provided, then 'force-cache' wins. If both 'only-no-store' and 'force-no-store' are provided, then 'force-no-store' wins. The force option changes the behavior across the route so a single segment with 'force-*' would prevent any errors caused by 'only-*'.


The intention of the 'only-*' and force-*' options is to guarantee the whole route is either fully static or fully dynamic. This means:
A combination of 'only-cache' and 'only-no-store' in a single route is not allowed.
A combination of 'force-cache' and 'force-no-store' in a single route is not allowed.
A parent cannot provide 'default-no-store' if a child provides 'auto' or '*-cache' since that could make the same fetch have different behavior.
It is generally recommended to leave shared parent layouts as 'auto' and customize the options where child segments diverge.
runtime
layout.tsx / page.tsx / route.ts export const runtime = 'nodejs'
// 'edge' | 'nodejs'
nodejs (default)
edge
Learn more about the Edge and Node.js runtimes.
preferredRegion


edge
Learn more about the Edge and Node.js runtimes.
preferredRegion
layout.tsx / page.tsx / route.ts export const preferredRegion = 'auto'
// 'auto' | 'global' | 'home' | ['iad1', 'sfo1']
Support for preferredRegion, and regions supported, is dependent on your deployment platform.
Good to know:
If a preferredRegion is not specified, it will inherit the option of the nearest parent layout.
The root layout defaults to all regions.
maxDuration
Based on your deployment platform, you may be able to use a higher default execution time for your function.
This setting allows you to opt into a higher execution time within your plans limit.
Note: This settings requires Next.js 13.4.10 or higher.
layout.tsx / page.tsx / route.ts export const maxDuration = 5
Good to know:


Good to know:
If a maxDuration is not specified, the default value is dependent on your deployment platform and plan.
generateStaticParams
The generateStaticParams function can be used in combination with dynamic route segments to define the list of route segment parameters that will be statically generated at build time instead of on-demand at request time.
See the API reference for more details.


not-found.jsThe not-found file is used to render UI when the notFound function is thrown within a route segment. Along with serving a custom UI, Next.js will also return a 404 HTTP status code.
app/blog/not-found.tsx import Link from 'next/link'

export default function NotFound() {
  return (

Not Found

Could not find requested resource

        View <Link href="/blog">all posts</Link>

  )
}
Good to know: In addition to catching expected notFound() errors, the root app/not-found.js file also handles any unmatched URLs for your whole application. This means users that visit a URL that is not handled by your app will be shown the UI exported by the app/not-found.js file.
Props


Props
not-found.js components do not accept any props.
Version History
VersionChangesv13.3.0Root app/not-found handles global unmatched URLs.v13.0.0not-found introduced.


default.jsThis documentation is still being written. Please check back later.


layout.jsA layout is UI that is shared between routes.
app/dashboard/layout.tsx export default function DashboardLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return
{children}

}
A root layout is the top-most layout in the root app directory. It is used to define the  and  tags and other globally shared UI.
app/layout.tsx export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (

      {children}

  )
}
Props
children (required)


</html>
  )
}
Props
children (required)
Layout components should accept and use a children prop. During rendering, children will be populated with the route segments the layout is wrapping. These will primarily be the component of a child Layout (if it exists) or Page, but could also be other special files like Loading or Error when applicable.
params (optional)
The dynamic route parameters object from the root segment down to that layout.
ExampleURLparamsapp/dashboard/[team]/layout.js/dashboard/1{ team: '1' }app/shop/[tag]/[item]/layout.js/shop/1/2{ tag: '1', item: '2' }app/blog/[...slug]/layout.js/blog/1/2{ slug: ['1', '2'] }
For example:
app/shop/[tag]/[item]/layout.tsx export default function ShopLayout({
  children,
  params,
}: {


children,
  params,
}: {
  children: React.ReactNode
  params: {
    tag: string
    item: string
  }
}) {
  // URL -> /shop/shoes/nike-air-max-97
  // `params` -> { tag: 'shoes', item: 'nike-air-max-97' }
  return <section>{children}</section>
}
Good to know
Layout's do not receive searchParams
Unlike Pages, Layout 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.
When using client-side navigation, Next.js automatically only renders the part of the page below the common layout between two routes.
For example, in the following directory structure, dashboard/layout.tsx is the common layout for both /dashboard/settings and /dashboard/analytics:
 app


app
└── dashboard
    ├── layout.tsx
    ├── settings
    │   └── page.tsx
    └── analytics
        └── page.js
When navigating from /dashboard/settings to /dashboard/analytics, page.tsx in /dashboard/analytics will be rendered on the server because it is UI that changed, while dashboard/layout.tsx will not be re-rendered because it is a common UI between the two routes.
This performance optimization allows navigation between pages that share a layout to be quicker as only the data fetching and rendering for the page has to run, instead of the entire route that could include shared layouts that fetch their own data.
Because dashboard/layout.tsx doesn't re-render, the searchParams prop in the layout Server Component might become stale after navigation.
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.


Root Layouts
The app directory must include a root app/layout.js.
The root layout must define <html> and <body> tags.
You should not manually add <head> tags such as <title> and <meta> to root layouts. Instead, you should use the Metadata API which automatically handles advanced requirements such as streaming and de-duplicating <head> elements.
You can use route groups to create multiple root layouts.
Navigating across multiple root layouts will cause a full page load (as opposed to a client-side navigation). For example, navigating from /cart that uses app/(shop)/layout.js to /blog that uses app/(marketing)/layout.js will cause a full page load. This only applies to multiple root layouts.
Version History
VersionChangesv13.0.0layout introduced.


error.jsAn error file defines an error UI boundary for a route segment.
It is useful for catching unexpected errors that occur in Server Components and Client Components and displaying a fallback UI.
app/dashboard/error.tsx 'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  useEffect(() => {
    // Log the error to an error reporting service
    console.error(error)
  }, [error])

  return (

Something went wrong!

      <button
        onClick={
          // Attempt to recover by trying to re-render the segment
          () => reset()
        }
      >
        Try again
      </button>


}
      >
        Try again
      </button>
    </div>
  )
}
Props
error
An instance of an Error object forwarded to the error.js Client Component.
error.message
The error message.
For errors forwarded from Client Components, this will be the original Error's message.
For errors forwarded from Server Components, this will be a generic error message to avoid leaking sensitive details. errors.digest can be used to match the corresponding error in server-side logs.
error.digest
An automatically generated hash of the error thrown in a Server Component. It can be used to match the corresponding error in server-side logs.
reset
A function to reset the error boundary. When executed, the function will try to re-render the Error boundary's contents. If successful, the fallback error component is replaced with the result of the re-render.
Can be used to prompt the user to attempt to recover from the error.


Can be used to prompt the user to attempt to recover from the error.
Good to know:
error.js boundaries must be Client Components.
In Production builds, errors forwarded from Server Components will be stripped of specific error details to avoid leaking sensitive information.
An error.js boundary will not handle errors thrown in a layout.js component in the same segment because the error boundary is nested inside that layouts component.
To handle errors for a specific layout, place an error.js file in the layouts parent segment.
To handle errors within the root layout or template, use a variation of error.js called app/global-error.js.
global-error.js
To specifically handle errors in root layout.js, use a variation of error.js called app/global-error.js located in the root app directory.
app/global-error.tsx 'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error & { digest?: string }


reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (

Something went wrong!

        <button onClick={() => reset()}>Try again</button>

  )
}
Good to know:
global-error.js replaces the root layout.js when active and so must define its own  and  tags.
While designing error UI, you may find it helpful to use the React Developer Tools to manually toggle Error boundaries.
Version History
VersionChangesv13.1.0global-error introduced.v13.0.0error introduced.


route.jsRoute Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
HTTP Methods
A route file allows you to create custom request handlers for a given route. The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS.
route.ts export async function GET(request: Request) {}

export async function HEAD(request: Request) {}

export async function POST(request: Request) {}

export async function PUT(request: Request) {}

export async function DELETE(request: Request) {}

export async function PATCH(request: Request) {}

// If `OPTIONS` is not defined, Next.js will automatically implement `OPTIONS` and  set the appropriate Response `Allow` header depending on the other methods defined in the route handler.
export async function OPTIONS(request: Request) {}


export async function OPTIONS(request: Request) {}
Good to know: Route Handlers are only available inside the app directory. You do not need to use API Routes (pages) and Route Handlers (app) together, as Route Handlers should be able to handle all use cases.
Parameters
request (optional)
The request object is a NextRequest object, which is an extension of the Web Request API. NextRequest gives you further control over the incoming request, including easily accessing cookies and an extended, parsed, URL object nextUrl.
context (optional)
app/dashboard/[team]/route.js export async function GET(request, context: { params }) {
  const team = params.team // '1'
}
Currently, the only value of context is params, which is an object containing the dynamic route parameters for the current route.


ExampleURLparamsapp/dashboard/[team]/route.js/dashboard/1{ team: '1' }app/shop/[tag]/[item]/route.js/shop/1/2{ tag: '1', item: '2' }app/blog/[...slug]/route.js/blog/1/2{ slug: ['1', '2'] }
NextResponse
Route Handlers can extend the Web Response API by returning a NextResponse object. This allows you to easily set cookies, headers, redirect, and rewrite. View the API reference.
Version History
VersionChangesv13.2.0Route handlers are introduced.


template.jsThis documentation is still being written. Please check back later.


sitemap.xmlAdd or generate a sitemap.xml file that matches the Sitemaps XML format in the root of app directory to help search engine crawlers crawl your site more efficiently.
Static sitemap.xml
app/sitemap.xml <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://acme.com</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
  <url>
    <loc>https://acme.com/about</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
  <url>
    <loc>https://acme.com/blog</loc>


<url>
    <loc>https://acme.com/blog</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
</urlset>
Generate a Sitemap
Add a sitemap.js or sitemap.ts file that returns Sitemap.
app/sitemap.ts import { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: 'https://acme.com',
      lastModified: new Date(),
    },
    {
      url: 'https://acme.com/about',
      lastModified: new Date(),
    },
    {
      url: 'https://acme.com/blog',
      lastModified: new Date(),
    },
  ]
}
Output:


lastModified: new Date(),
    },
  ]
}
Output:
acme.com/sitemap.xml <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://acme.com</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
  <url>
    <loc>https://acme.com/about</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
  <url>
    <loc>https://acme.com/blog</loc>
    <lastmod>2023-04-06T15:02:24.021Z</lastmod>
  </url>
</urlset>


</url>
</urlset>
Sitemap Return Type
 type Sitemap = Array<{
  url: string
  lastModified?: string | Date
}>
Good to know
In the future, we will support multiple sitemaps and sitemap indexes.
Version History
VersionChangesv13.3.0sitemap introduced.


opengraph-image and twitter-imageThe opengraph-image and twitter-image file conventions allow you to set Open Graph and Twitter images for a route segment.
They are useful for setting the images that appear on social networks and messaging apps when a user shares a link to your site.
There are two ways to set Open Graph and Twitter images:
Using image files (.jpg, .png, .gif)
Using code to generate images (.js, .ts, .tsx)
Image files (.jpg, .png, .gif)
Use an image file to set a route segment's shared image by placing an opengraph-image or twitter-image image file in the segment.
Next.js will evaluate the file and automatically add the appropriate tags to your app's <head> element.


File conventionSupported file typesopengraph-image.jpg, .jpeg, .png, .giftwitter-image.jpg, .jpeg, .png, .gifopengraph-image.alt.txttwitter-image.alt.txt
opengraph-image
Add an opengraph-image.(jpg|jpeg|png|gif) image file to any route segment.
<head> output <meta property="og:image" content="<generated>" />
<meta property="og:image:type" content="<generated>" />
<meta property="og:image:width" content="<generated>" />
<meta property="og:image:height" content="<generated>" />
twitter-image
Add a twitter-image.(jpg|jpeg|png|gif) image file to any route segment.
<head> output <meta name="twitter:image" content="<generated>" />
<meta name="twitter:image:type" content="<generated>" />
<meta name="twitter:image:width" content="<generated>" />


<meta name="twitter:image:width" content="<generated>" />
<meta name="twitter:image:height" content="<generated>" />
opengraph-image.alt.txt
Add an accompanying opengraph-image.alt.txt file in the same route segment as the opengraph-image.(jpg|jpeg|png|gif) image it's alt text.
opengraph-image.alt.txt About Acme
<head> output <meta property="og:image:alt" content="About Acme" />
twitter-image.alt.txt
Add an accompanying twitter-image.alt.txt file in the same route segment as the twitter-image.(jpg|jpeg|png|gif) image it's alt text.
twitter-image.alt.txt About Acme
<head> output <meta property="og:image:alt" content="About Acme" />
Generate images using code (.js, .ts, .tsx)
In addition to using literal image files, you can programmatically generate images using code.


In addition to using literal image files, you can programmatically generate images using code.
Generate a route segment's shared image by creating an opengraph-image or twitter-image route that default exports a function.
File conventionSupported file typesopengraph-image.js, .ts, .tsxtwitter-image.js, .ts, .tsx
Good to know
By default, generated images are statically optimized (generated at build time and cached) unless they use dynamic functions or dynamic data fetching.
You can generate multiple Images in the same file using generateImageMetadata.
The easiest way to generate an image is to use the ImageResponse API from next/server.
app/about/opengraph-image.tsx import { ImageResponse } from 'next/server'

// Route segment config
export const runtime = 'edge'

// Image metadata
export const alt = 'About Acme'
export const size = {
  width: 1200,


export const size = {
  width: 1200,
  height: 630,
}

export const contentType = 'image/png'

// Font
const interSemiBold = fetch(
  new URL('./Inter-SemiBold.ttf', import.meta.url)
).then((res) => res.arrayBuffer())

// Image generation
export default async function Image() {
  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 128,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        About Acme
      </div>
    ),
    // ImageResponse options
    {


</div>
    ),
    // ImageResponse options
    {
      // For convenience, we can re-use the exported opengraph-image
      // size config to also set the ImageResponse's width and height.
      ...size,
      fonts: [
        {
          name: 'Inter',
          data: await interSemiBold,
          style: 'normal',
          weight: 400,
        },
      ],
    }
  )
}
<head> output <meta property="og:image" content="<generated>" />
<meta property="og:image:alt" content="About Acme" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
Props
The default export function receives the following props:
params (optional)


Props
The default export function receives the following props:
params (optional)
An object containing the dynamic route parameters object from the root segment down to the segment opengraph-image or twitter-image is colocated in.
app/shop/[slug]/opengraph-image.tsx export default function Image({ params }: { params: { slug: string } }) {
  // ...
}
RouteURLparamsapp/shop/opengraph-image.js/shopundefinedapp/shop/[slug]/opengraph-image.js/shop/1{ slug: '1' }app/shop/[tag]/[item]/opengraph-image.js/shop/1/2{ tag: '1', item: '2' }app/shop/[...slug]/opengraph-image.js/shop/1/2{ slug: ['1', '2'] }
Returns
The default export function should return a Blob | ArrayBuffer | TypedArray | DataView | ReadableStream | Response.


Good to know: ImageResponse satisfies this return type.
Config exports
You can optionally configure the image's metadata by exporting alt, size, and contentType variables from opengraph-image or twitter-image route.
OptionTypealtstringsize{ width: number; height: number }contentTypestring - image MIME type
alt
opengraph-image.tsx / twitter-image.tsx export const alt = 'My images alt text'

export default function Image() {}
<head> output <meta property="og:image:alt" content="My images alt text" />
size
opengraph-image.tsx / twitter-image.tsx export const size = { width: 1200, height: 630 }

export default function Image() {}
<head> output <meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
contentType


<meta property="og:image:height" content="630" />
contentType
opengraph-image.tsx / twitter-image.tsx export const contentType = 'image/png'

export default function Image() {}
<head> output <meta property="og:image:type" content="image/png" />
Route Segment Config
opengraph-image and twitter-image are specialized Route Handlers that can use the same route segment configuration options as Pages and Layouts.
OptionTypeDefaultdynamic'auto' | 'force-dynamic' | 'error' | 'force-static''auto'revalidatefalse | 'force-cache' | 0 | numberfalseruntime'nodejs' | 'edge''nodejs'preferredRegion'auto' | 'global' | 'home' | string | string[]'auto'
app/opengraph-image.tsx export const runtime = 'edge'

export default function Image() {}
Examples
Using external data


export default function Image() {}
Examples
Using external data
This example uses the params object and external data to generate the image.
Good to know:
By default, this generated image will be statically optimized. You can configure the individual fetch options or route segments options to change this behavior.
app/posts/[slug]/opengraph-image.tsx import { ImageResponse } from 'next/server'

export const runtime = 'edge'

export const alt = 'About Acme'
export const size = {
  width: 1200,
  height: 630,
}
export const contentType = 'image/png'

export default async function Image({ params }: { params: { slug: string } }) {
  const post = await fetch(`https://.../posts/${params.slug}`).then((res) =>
    res.json()
  )

  return new ImageResponse(


res.json()
  )

  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 48,
          background: 'white',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
        }}
      >
        {post.title}
      </div>
    ),
    {
      ...size,
    }
  )
}
Version History
VersionChangesv13.3.0opengraph-image and twitter-image introduced.


favicon, icon, and apple-iconThe favicon, icon, or apple-icon file conventions allow you to set icons for your application.
They are useful for adding app icons that appear in places like web browser tabs, phone home screens, and search engine results.
There are two ways to set app icons:
Using image files (.ico, .jpg, .png)
Using code to generate an icon (.js, .ts, .tsx)
Image files (.ico, .jpg, .png)
Use an image file to set an app icon by placing a favicon, icon, or apple-icon image file within your /app directory.
The favicon image can only be located in the top level of app/.
Next.js will evaluate the file and automatically add the appropriate tags to your app's <head> element.


File conventionSupported file typesValid locationsfavicon.icoapp/icon.ico, .jpg, .jpeg, .png, .svgapp/**/*apple-icon.jpg, .jpeg, .pngapp/**/*
favicon
Add a favicon.ico image file to the root /app route segment.
<head> output <link rel="icon" href="/favicon.ico" sizes="any" />
icon
Add an icon.(ico|jpg|jpeg|png|svg) image file.
<head> output <link
  rel="icon"
  href="/icon?<generated>"
  type="image/<generated>"
  sizes="<generated>"
/>
apple-icon
Add an apple-icon.(jpg|jpeg|png) image file.
<head> output <link
  rel="apple-touch-icon"
  href="/apple-icon?<generated>"
  type="image/<generated>"
  sizes="<generated>"
/>
Good to know


type="image/<generated>"
  sizes="<generated>"
/>
Good to know
You can set multiple icons by adding a number suffix to the file name. For example, icon1.png, icon2.png, etc. Numbered files will sort lexically.
Favicons can only be set in the root /app segment. If you need more granularity, you can use icon.
The appropriate <link> tags and attributes such as rel, href, type, and sizes are determined by the icon type and metadata of the evaluated file.
For example, a 32 by 32px .png file will have type="image/png" and sizes="32x32" attributes.
sizes="any" is added to favicon.ico output to avoid a browser bug where an .ico icon is favored over .svg.
Generate icons using code (.js, .ts, .tsx)


Generate icons using code (.js, .ts, .tsx)
In addition to using literal image files, you can programmatically generate icons using code.
Generate an app icon by creating an icon or apple-icon route that default exports a function.
File conventionSupported file typesicon.js, .ts, .tsxapple-icon.js, .ts, .tsx
The easiest way to generate an icon is to use the ImageResponse API from next/server.
app/icon.tsx import { ImageResponse } from 'next/server'

// Route segment config
export const runtime = 'edge'

// Image metadata
export const size = {
  width: 32,
  height: 32,
}
export const contentType = 'image/png'

// Image generation
export default function Icon() {
  return new ImageResponse(
    (
      // ImageResponse JSX element
      <div
        style={{


(
      // ImageResponse JSX element
      <div
        style={{
          fontSize: 24,
          background: 'black',
          width: '100%',
          height: '100%',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'center',
          color: 'white',
        }}
      >
        A
      </div>
    ),
    // ImageResponse options
    {
      // For convenience, we can re-use the exported icons size metadata
      // config to also set the ImageResponse's width and height.
      ...size,
    }
  )
}
<head> output <link rel="icon" href="/icon?<generated>" type="image/png" sizes="32x32" />
Good to know


Good to know
By default, generated icons are statically optimized (generated at build time and cached) unless they use dynamic functions or dynamic data fetching.
You can generate multiple icons in the same file using generateImageMetadata.
You cannot generate a favicon icon. Use icon or a favicon.ico file instead.
Props
The default export function receives the following props:
params (optional)
An object containing the dynamic route parameters object from the root segment down to the segment icon or apple-icon is colocated in.
app/shop/[slug]/icon.tsx export default function Icon({ 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
The default export function should return a Blob | ArrayBuffer | TypedArray | DataView | ReadableStream | Response.
Good to know: ImageResponse satisfies this return type.
Config exports
You can optionally configure the icon's metadata by exporting size and contentType variables from the icon or apple-icon route.
OptionTypesize{ width: number; height: number }contentTypestring - image MIME type
size
icon.tsx / apple-icon.tsx export const size = { width: 32, height: 32 }

export default function Icon() {}


export default function Icon() {}
<head> output <link rel="icon" sizes="32x32" />
contentType
icon.tsx / apple-icon.tsx export const contentType = 'image/png'

export default function Icon() {}
<head> output <link rel="icon" type="image/png" />
Route Segment Config
icon and apple-icon are specialized Route Handlers that can use the same route segment configuration options as Pages and Layouts.
OptionTypeDefaultdynamic'auto' | 'force-dynamic' | 'error' | 'force-static''auto'revalidatefalse | 'force-cache' | 0 | numberfalseruntime'nodejs' | 'edge''nodejs'preferredRegion'auto' | 'global' | 'home' | string | string[]'auto'
app/icon.tsx export const runtime = 'edge'

export default function Icon() {}
Version History


export default function Icon() {}
Version History
VersionChangesv13.3.0favicon icon and apple-icon introduced


robots.txtAdd or generate a robots.txt file that matches the Robots Exclusion Standard in the root of app directory to tell search engine crawlers which URLs they can access on your site.
Static robots.txt
app/robots.txt User-Agent: *
Allow: /
Disallow: /private/
Sitemap: https://acme.com/sitemap.xml
Generate a Robots file
Add a robots.js or robots.ts file that returns a Robots object.
app/robots.ts import { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
      disallow: '/private/',
    },
    sitemap: 'https://acme.com/sitemap.xml',
  }
}
Output:
 User-Agent: *
Allow: /
Disallow: /private/
Sitemap: https://acme.com/sitemap.xml


Disallow: /private/
Sitemap: https://acme.com/sitemap.xml
Robots object
 type Robots = {
  rules:
    | {
        userAgent?: string | string[]
        allow?: string | string[]
        disallow?: string | string[]
        crawlDelay?: number
      }
    | Array<{
        userAgent: string | string[]
        allow?: string | string[]
        disallow?: string | string[]
        crawlDelay?: number
      }>
  sitemap?: string | string[]
  host?: string
}
Version History
VersionChangesv13.3.0robots introduced.


Building Your Application
Next.js provides the building blocks to create flexible, full-stack web applications. The guides in Building Your Application explain how to use these features and how to customize your application's behavior.
The sections and pages are organized sequentially, from basic to advanced, so you can follow them step-by-step when building your Next.js application. However, you can read them in any order or skip to the pages that apply to your use case.
If you're new to Next.js, we recommend starting with the Routing, Rendering, Data Fetching and Styling sections, as they introduce the fundamental Next.js and web concepts to help you get started. Then, you can dive deeper into the other sections such as Optimizing and Configuring. Finally, once you're ready, checkout the Deploying and Upgrading sections.


Error HandlingThe error.js file convention allows you to gracefully handle unexpected runtime errors in nested routes.
Automatically wrap a route segment and its nested children in a React Error Boundary.
Create error UI tailored to specific segments using the file-system hierarchy to adjust granularity.
Isolate errors to affected segments while keeping the rest of the application functional.
Add functionality to attempt to recover from an error without a full page reload.
Create error UI by adding an error.js file inside a route segment and exporting a React component:
app/dashboard/error.tsx 'use client' // Error components must be Client Components

import { useEffect } from 'react'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  useEffect(() => {
    // Log the error to an error reporting service
    console.error(error)
  }, [error])


console.error(error)
  }, [error])

  return (

Something went wrong!

      <button
        onClick={
          // Attempt to recover by trying to re-render the segment
          () => reset()
        }
      >
        Try again
      </button>

  )
}
How error.js Works
error.js automatically creates an React Error Boundary that wraps a nested child segment or page.js component.
The React component exported from the error.js file is used as the fallback component.
If an error is thrown within the error boundary, the error is contained, and the fallback component is rendered.
When the fallback error component is active, layouts above the error boundary maintain their state and remain interactive, and the error component can display functionality to recover from the error.
Recovering From Errors


Recovering From Errors
The cause of an error can sometimes be temporary. In these cases, simply trying again might resolve the issue.
An error component can use the reset() function to prompt the user to attempt to recover from the error. When executed, the function will try to re-render the Error boundary's contents. If successful, the fallback error component is replaced with the result of the re-render.
app/dashboard/error.tsx 'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (

Something went wrong!

      <button onClick={() => reset()}>Try again</button>

  )
}
Nested Routes
React components created through special files are rendered in a specific nested hierarchy.


}
Nested Routes
React components created through special files are rendered in a specific nested hierarchy.
For example, a nested route with two segments that both include layout.js and error.js files are rendered in the following simplified component hierarchy:
The nested component hierarchy has implications for the behavior of error.js files across a nested route:
Errors bubble up to the nearest parent error boundary. This means an error.js file will handle errors for all its nested child segments. More or less granular error UI can be achieved by placing error.js files at different levels in the nested folders of a route.
An error.js boundary will not handle errors thrown in a layout.js component in the same segment because the error boundary is nested inside that layouts component.
Handling Errors in Layouts


Handling Errors in Layouts
error.js boundaries do not catch errors thrown in layout.js or template.js components of the same segment. This intentional hierarchy keeps important UI that is shared between sibling routes (such as navigation) visible and functional when an error occurs.
To handle errors within a specific layout or template, place an error.js file in the layouts parent segment.
To handle errors within the root layout or template, use a variation of error.js called global-error.js.
Handling Errors in Root Layouts
The root app/error.js boundary does not catch errors thrown in the root app/layout.js or app/template.js component.
To specifically handle errors in these root components, use a variation of error.js called app/global-error.js located in the root app directory.


Unlike the root error.js, the global-error.js error boundary wraps the entire application, and its fallback component replaces the root layout when active. Because of this, it is important to note that global-error.js must define its own <html> and <body> tags.
global-error.js is the least granular error UI and can be considered "catch-all" error handling for the whole application. It is unlikely to be triggered often as root components are typically less dynamic, and other error.js boundaries will catch most errors.
Even if a global-error.js is defined, it is still recommended to define a root error.js whose fallback component will be rendered within the root layout, which includes globally shared UI and branding.
app/global-error.tsx 'use client'

export default function GlobalError({
  error,
  reset,
}: {
  error: Error
  reset: () => void
}) {
  return (
    <html>


reset: () => void
}) {
  return (

Something went wrong!

        <button onClick={() => reset()}>Try again</button>

  )
}
Handling Server Errors
If an error is thrown inside a Server Component, Next.js will forward an Error object (stripped of sensitive error information in production) to the nearest error.js file as the error prop.
Securing Sensitive Error Information
During production, the Error object forwarded to the client only includes a generic message and digest property.
This is a security precaution to avoid leaking potentially sensitive details included in the error to the client.
The message property contains a generic message about the error and the digest property contains an automatically generated hash of the error that can be used to match the corresponding error in server-side logs.


During development, the Error object forwarded to the client will be serialized and include the message of the original error for easier debugging.


Route HandlersRoute Handlers allow you to create custom request handlers for a given route using the Web Request and Response APIs.
Good to know: Route Handlers are only available inside the app directory. They are the equivalent of API Routes inside the pages directory meaning you do not need to use API Routes and Route Handlers together.
Convention
Route Handlers are defined in a route.js|ts file inside the app directory:
app/api/route.ts export async function GET(request: Request) {}
Route Handlers can be nested inside the app directory, similar to page.js and layout.js. But there cannot be a route.js file at the same route segment level as page.js.
Supported HTTP Methods
The following HTTP methods are supported: GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS. If an unsupported method is called, Next.js will return a 405 Method Not Allowed response.
Extended NextRequest and NextResponse APIs


Extended NextRequest and NextResponse APIs
In addition to supporting native Request and Response. Next.js extends them with
NextRequest and NextResponse to provide convenient helpers for advanced use cases.
Behavior
Static Route Handlers
Route Handlers are statically evaluated by default when using the GET method with the Response object.
app/items/route.ts import { NextResponse } from 'next/server'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const data = await res.json()

  return NextResponse.json({ data })
}
TypeScript Warning: Although Response.json() is valid, native TypeScript types currently shows an error, you can use NextResponse.json() for typed responses instead.
Dynamic Route Handlers


Dynamic Route Handlers
Route handlers are evaluated dynamically when:
Using the Request object with the GET method.
Using any of the other HTTP methods.
Using Dynamic Functions like cookies and headers.
The Segment Config Options manually specifies dynamic mode.
For example:
app/products/api/route.ts import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const id = searchParams.get('id')
  const res = await fetch(`https://data.mongodb-api.com/product/${id}`, {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  })
  const product = await res.json()

  return NextResponse.json({ product })
}
Similarly, the POST method will cause the Route Handler to be evaluated dynamically.


}
Similarly, the POST method will cause the Route Handler to be evaluated dynamically.
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
    body: JSON.stringify({ time: new Date().toISOString() }),
  })

  const data = await res.json()

  return NextResponse.json(data)
}
Good to know: Like API Routes, Route Handlers can be used for cases like handling form submissions. A new abstraction for handling forms and mutations that integrates deeply with React is being worked on.
Route Resolution
You can consider a route the lowest level routing primitive.


Route Resolution
You can consider a route the lowest level routing primitive.
They do not participate in layouts or client-side navigations like page.
There cannot be a route.js file at the same route as page.js.
PageRouteResultapp/page.jsapp/route.js Conflictapp/page.jsapp/api/route.js Validapp/[user]/page.jsapp/api/route.js Valid
Each route.js or page.js file takes over all HTTP verbs for that route.
app/page.js export default function Page() {
  return
Hello, Next.js!

}

// ❌ Conflict
// `app/route.js`
export async function POST(request) {}
Examples
The following examples show how to combine Route Handlers with other Next.js APIs and features.
Revalidating Static Data
You can revalidate static data fetches using the next.revalidate option:


You can revalidate static data fetches using the next.revalidate option:
app/items/route.ts import { NextResponse } from 'next/server'

export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    next: { revalidate: 60 }, // Revalidate every 60 seconds
  })
  const data = await res.json()

  return NextResponse.json(data)
}
Alternatively, you can use the revalidate segment config option:
 export const revalidate = 60
Dynamic Functions
Route Handlers can be used with dynamic functions from Next.js, like cookies and headers.
Cookies
You can read cookies with cookies from next/headers. This server function can be called directly in a Route Handler, or nested inside of another function.


This cookies instance is read-only. To set cookies, you need to return a new Response using the Set-Cookie header.
app/api/route.ts import { cookies } from 'next/headers'

export async function GET(request: Request) {
  const cookieStore = cookies()
  const token = cookieStore.get('token')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token.value}` },
  })
}
Alternatively, you can use abstractions on top of the underlying Web APIs to read cookies (NextRequest):
app/api/route.ts import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const token = request.cookies.get('token')
}
Headers


const token = request.cookies.get('token')
}
Headers
You can read headers with headers from next/headers. This server function can be called directly in a Route Handler, or nested inside of another function.
This headers instance is read-only. To set headers, you need to return a new Response with new headers.
app/api/route.ts import { headers } from 'next/headers'

export async function GET(request: Request) {
  const headersList = headers()
  const referer = headersList.get('referer')

  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { referer: referer },
  })
}
Alternatively, you can use abstractions on top of the underlying Web APIs to read headers (NextRequest):
app/api/route.ts import { type NextRequest } from 'next/server'


app/api/route.ts import { type NextRequest } from 'next/server'

export async function GET(request: NextRequest) {
  const requestHeaders = new Headers(request.headers)
}
Redirects
app/api/route.ts import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  redirect('https://nextjs.org/')
}
Dynamic Route Segments
We recommend reading the Defining Routes page before continuing.
Route Handlers can use Dynamic Segments to create request handlers from dynamic data.
app/items/[slug]/route.ts export async function GET(
  request: Request,
  { params }: { params: { slug: string } }
) {
  const slug = params.slug // 'a', 'b', or 'c'
}


const slug = params.slug // 'a', 'b', or 'c'
}
RouteExample URLparamsapp/items/[slug]/route.js/items/a{ slug: 'a' }app/items/[slug]/route.js/items/b{ slug: 'b' }app/items/[slug]/route.js/items/c{ slug: 'c' }
Streaming
Streaming is commonly used in combination with Large Language Models (LLMs), such an OpenAI, for AI-generated content. Learn more about the AI SDK.
app/api/completion/route.ts import { Configuration, OpenAIApi } from 'openai-edge'
import { OpenAIStream, StreamingTextResponse } from 'ai'

const config = new Configuration({
  apiKey: process.env.OPENAI_API_KEY,
})
const openai = new OpenAIApi(config)

export const runtime = 'edge'


export const runtime = 'edge'

export async function POST(req: Request) {
  const { prompt } = await req.json()
  const response = await openai.createCompletion({
    model: 'text-davinci-003',
    stream: true,
    temperature: 0.6,
    prompt: 'What is Next.js?',
  })

  const stream = OpenAIStream(response)
  return new StreamingTextResponse(stream)
}
These abstractions use the Web APIs to create a stream. You can also use the underlying Web APIs directly.
app/api/route.ts // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#convert_async_iterator_to_stream
function iteratorToStream(iterator: any) {
  return new ReadableStream({
    async pull(controller) {
      const { value, done } = await iterator.next()


const { value, done } = await iterator.next()

      if (done) {
        controller.close()
      } else {
        controller.enqueue(value)
      }
    },
  })
}

function sleep(time: number) {
  return new Promise((resolve) => {
    setTimeout(resolve, time)
  })
}

const encoder = new TextEncoder()

async function* makeIterator() {
  yield encoder.encode('
One
')
  await sleep(200)
  yield encoder.encode('
Two
')
  await sleep(200)
  yield encoder.encode('
Three
')
}

export async function GET() {
  const iterator = makeIterator()
  const stream = iteratorToStream(iterator)

  return new Response(stream)
}
Request Body


return new Response(stream)
}
Request Body
You can read the Request body using the standard Web API methods:
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const res = await request.json()
  return NextResponse.json({ res })
}
Request Body FormData
You can read the FormData using the the request.formData() function:
app/items/route.ts import { NextResponse } from 'next/server'

export async function POST(request: Request) {
  const formData = await request.formData()
  const name = formData.get('name')
  const email = formData.get('email')
  return NextResponse.json({ name, email })
}
Since formData data are all strings, you may want to use zod-form-data to validate the request and retrieve data in the format you prefer (e.g. number).


CORS
You can set CORS headers on a Response using the standard Web API methods:
app/api/route.ts export async function GET(request: Request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}
Edge and Node.js Runtimes
Route Handlers have an isomorphic Web API to support both Edge and Node.js runtimes seamlessly, including support for streaming. Since Route Handlers use the same route segment configuration as Pages and Layouts, they support long-awaited features like general-purpose statically regenerated Route Handlers.
You can use the runtime segment config option to specify the runtime:
 export const runtime = 'edge' // 'nodejs' is the default


export const runtime = 'edge' // 'nodejs' is the default
Non-UI Responses
You can use Route Handlers to return non-UI content. Note that sitemap.xml, robots.txt, app icons, and open graph images all have built-in support.
app/rss.xml/route.ts export async function GET() {
  return new Response(`<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">

<channel>
  <title>Next.js Documentation</title>
  <link>https://nextjs.org/docs</link>
  <description>The React Framework for the Web</description>
</channel>

</rss>`)
}
Segment Config Options
Route Handlers use the same route segment configuration as pages and layouts.
app/items/route.ts export const dynamic = 'auto'
export const dynamicParams = true


app/items/route.ts export const dynamic = 'auto'
export const dynamicParams = true
export const revalidate = false
export const fetchCache = 'auto'
export const runtime = 'nodejs'
export const preferredRegion = 'auto'
See the API reference for more details.


InternationalizationNext.js enables you to configure the routing and rendering of content to support multiple languages. Making your site adaptive to different locales includes translated content (localization) and internationalized routes.
Terminology
Locale: An identifier for a set of language and formatting preferences. This usually includes the preferred language of the user and possibly their geographic region.
en-US: English as spoken in the United States
nl-NL: Dutch as spoken in the Netherlands
nl: Dutch, no specific region
Routing Overview
It’s recommended to use the user’s language preferences in the browser to select which locale to use. Changing your preferred language will modify the incoming Accept-Language header to your application.
For example, using the following libraries, you can look at an incoming Request to determine which locale to select, based on the Headers, locales you plan to support, and the default locale.
middleware.js import { match } from '@formatjs/intl-localematcher'


middleware.js import { match } from '@formatjs/intl-localematcher'
import Negotiator from 'negotiator'

let headers = { 'accept-language': 'en-US,en;q=0.5' }
let languages = new Negotiator({ headers }).languages()
let locales = ['en-US', 'nl-NL', 'nl']
let defaultLocale = 'en-US'

match(languages, locales, defaultLocale) // -> 'en-US'
Routing can be internationalized by either the sub-path (/fr/products) or domain (my-site.fr/products). With this information, you can now redirect the user based on the locale inside Middleware.
middleware.js import { NextResponse } from 'next/server'

let locales = ['en-US', 'nl-NL', 'nl']

// Get the preferred locale, similar to above or using a library
function getLocale(request) { ... }


function getLocale(request) { ... }

export function middleware(request) {
  // Check if there is any supported locale in the pathname
  const pathname = request.nextUrl.pathname
  const pathnameIsMissingLocale = locales.every(
    (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
  )

  // Redirect if there is no locale
  if (pathnameIsMissingLocale) {
    const locale = getLocale(request)

    // e.g. incoming request is /products
    // The new URL is now /en-US/products
    return NextResponse.redirect(
      new URL(`/${locale}/${pathname}`, request.url)
    )
  }
}

export const config = {
  matcher: [
    // Skip all internal paths (_next)
    '/((?!_next).*)',


// Skip all internal paths (_next)
    '/((?!_next).*)',
    // Optional: only run on root (/) URL
    // '/'
  ],
}
Finally, ensure all special files inside app/ are nested under app/[lang]. This enables the Next.js router to dynamically handle different locales in the route, and forward the lang parameter to every layout and page. For example:
app/[lang]/page.js // You now have access to the current locale
// e.g. /en-US/products -> `lang` is "en-US"
export default async function Page({ params: { lang } }) {
  return ...
}
The root layout can also be nested in the new folder (e.g. app/[lang]/layout.js).
Localization


Localization
Changing displayed content based on the user’s preferred locale, or localization, is not something specific to Next.js. The patterns described below would work the same with any web application.
Let’s assume we want to support both English and Dutch content inside our application. We might maintain two different “dictionaries”, which are objects that give us a mapping from some key to a localized string. For example:
dictionaries/en.json {
  "products": {
    "cart": "Add to Cart"
  }
}
dictionaries/nl.json {
  "products": {
    "cart": "Toevoegen aan Winkelwagen"
  }
}
We can then create a getDictionary function to load the translations for the requested locale:
app/[lang]/dictionaries.js import 'server-only'

const dictionaries = {


app/[lang]/dictionaries.js import 'server-only'

const dictionaries = {
  en: () => import('./dictionaries/en.json').then((module) => module.default),
  nl: () => import('./dictionaries/nl.json').then((module) => module.default),
}

export const getDictionary = async (locale) => dictionaries[locale]()
Given the currently selected language, we can fetch the dictionary inside of a layout or page.
app/[lang]/page.js import { getDictionary } from './dictionaries'

export default async function Page({ params: { lang } }) {
  const dict = await getDictionary(lang) // en
  return <button>{dict.products.cart}</button> // Add to Cart
}


return <button>{dict.products.cart}</button> // Add to Cart
}
Because all layouts and pages in the app/ directory default to Server Components, we do not need to worry about the size of the translation files affecting our client-side JavaScript bundle size. This code will only run on the server, and only the resulting HTML will be sent to the browser.
Static Generation
To generate static routes for a given set of locales, we can use generateStaticParams with any page or layout. This can be global, for example, in the root layout:
app/[lang]/layout.js export async function generateStaticParams() {
  return [{ lang: 'en-US' }, { lang: 'de' }]
}

export default function Root({ children, params }) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  )
}
Examples


</html>
  )
}
Examples
Minimal i18n routing and translations
next-intl


Loading UI and StreamingThe special file loading.js helps you create meaningful Loading UI with React Suspense. With this convention, you can show an instant loading state from the server while the content of a route segment loads. The new content is automatically swapped in once rendering is complete.
Instant Loading States
An instant loading state is fallback UI that is shown immediately upon navigation. You can pre-render loading indicators such as skeletons and spinners, or a small but meaningful part of future screens such as a cover photo, title, etc. This helps users understand the app is responding and provides a better user experience.
Create a loading state by adding a loading.js file inside a folder.
app/dashboard/loading.tsx export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return <LoadingSkeleton />
}


return <LoadingSkeleton />
}
In the same folder, loading.js will be nested inside layout.js. It will automatically wrap the page.js file and any children below in a <Suspense> boundary.
Good to know:
Navigation is immediate, even with server-centric routing.
Navigation is interruptible, meaning changing routes does not need to wait for the content of the route to fully load before navigating to another route.
Shared layouts remain interactive while new route segments load.
Recommendation: Use the loading.js convention for route segments (layouts and pages) as Next.js optimizes this functionality.
Streaming with Suspense
In addition to loading.js, you can also manually create Suspense Boundaries for your own UI components. The App Router supports streaming with Suspense for both Node.js and Edge runtimes.
What is Streaming?


What is Streaming?
To learn how Streaming works in React and Next.js, it's helpful to understand Server-Side Rendering (SSR) and its limitations.
With SSR, there's a series of steps that need to be completed before a user can see and interact with a page:
First, all data for a given page is fetched on the server.
The server then renders the HTML for the page.
The HTML, CSS, and JavaScript for the page are sent to the client.
A non-interactive user interface is shown using the generated HTML, and CSS.
Finally, React hydrates the user interface to make it interactive.
These steps are sequential and blocking, meaning the server can only render the HTML for a page once all the data has been fetched. And, on the client, React can only hydrate the UI once the code for all components in the page has been downloaded.


SSR with React and Next.js helps improve the perceived loading performance by showing a non-interactive page to the user as soon as possible.
However, it can still be slow as all data fetching on server needs to be completed before the page can be shown to the user.
Streaming allows you to break down the page's HTML into smaller chunks and progressively send those chunks from the server to the client.
This enables parts of the page to be displayed sooner, without waiting for all the data to load before any UI can be rendered.
Streaming works well with React's component model because each component can be considered a chunk. Components that have higher priority (e.g. product information) or that don't rely on data can be sent first (e.g. layout), and React can start hydration earlier. Components that have lower priority (e.g. reviews, related products) can be sent in the same server request after their data has been fetched.


Streaming is particularly beneficial when you want to prevent long data requests from blocking the page from rendering as it can reduce the Time To First Byte (TTFB) and First Contentful Paint (FCP). It also helps improve Time to Interactive (TTI), especially on slower devices.
Example
<Suspense> works by wrapping a component that performs an asynchronous action (e.g. fetch data), showing fallback UI (e.g. skeleton, spinner) while it's happening, and then swapping in your component once the action completes.
app/dashboard/page.tsx import { Suspense } from 'react'
import { PostFeed, Weather } from './Components'

export default function Posts() {
  return (

      <Suspense fallback={
Loading feed...
}>
        <PostFeed />
      </Suspense>
      <Suspense fallback={
Loading weather...
}>
        <Weather />


<Suspense fallback={
Loading weather...
}>
        <Weather />
      </Suspense>

  )
}
By using Suspense, you get the benefits of:
Streaming Server Rendering - Progressively rendering HTML from the server to the client.
Selective Hydration - React prioritizes what components to make interactive first based on user interaction.
For more Suspense examples and use cases, please see the React Documentation.
SEO
Next.js will wait for data fetching inside generateMetadata to complete before streaming UI to the client. This guarantees the first part of a streamed response includes  tags.
Since streaming is server-rendered, it does not impact SEO. You can use the Mobile Friendly Test tool from Google to see how your page appears to Google's web crawlers and view the serialized HTML (source).


Defining Routes
We recommend reading the Routing Fundamentals page before continuing.
This page will guide you through how to define and organize routes in your Next.js application.
Creating Routes
Next.js uses a file-system based router where folders are used to define routes.
Each folder represents a route segment that maps to a URL segment. To create a nested route, you can nest folders inside each other.
A special page.js file is used to make route segments publicly accessible.
In this example, the /dashboard/analytics URL path is not publicly accessible because it does not have a corresponding page.js file. This folder could be used to store components, stylesheets, images, or other colocated files.
Good to know: .js, .jsx, or .tsx file extensions can be used for special files.
Creating UI


Creating UI
Special file conventions are used to create UI for each route segment. The most common are pages to show UI unique to a route, and layouts to show UI that is shared across multiple routes.
For example, to create your first page, add a page.js file inside the app directory and export a React component:
app/page.tsx export default function Page() {
  return
Hello, Next.js!

}


Linking and NavigatingThe Next.js router uses server-centric routing with client-side navigation. It supports instant loading states and concurrent rendering. This means navigation maintains client-side state, avoids expensive re-renders, is interruptible, and doesn't cause race conditions.
There are two ways to navigate between routes:
<Link> Component
useRouter Hook
This page will go through how to use <Link>, useRouter(), and dive deeper into how navigation works.
<Link> Component
<Link> is a React component that extends the HTML <a> element to provide prefetching and client-side navigation between routes. It is the primary way to navigate between routes in Next.js.
To use <Link>, import it from next/link, and pass a href prop to the component:
app/page.tsx import Link from 'next/link'

export default function Page() {
  return <Link href="/dashboard">Dashboard</Link>
}


return <Link href="/dashboard">Dashboard</Link>
}
There are optional props you can pass to <Link>. See the API reference for more information.
Examples
Linking to Dynamic Segments
When linking to dynamic segments, you can use template literals and interpolation to generate a list of links. For example, to generate a list of blog posts:
app/blog/PostList.js import Link from 'next/link'

export default function PostList({ posts }) {
  return (

      {posts.map((post) => (

          <Link href={`/blog/${post.slug}`}>{post.title}</Link>

      ))}

  )
}
Checking Active Links


))}
    </ul>
  )
}
Checking Active Links
You can use usePathname() to determine if a link is active. For example, to add a class to the active link, you can check if the current pathname matches the href of the link:
app/ui/Navigation.js 'use client'

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

export function Navigation({ navLinks }) {
  const pathname = usePathname()

  return (
    <>
      {navLinks.map((link) => {
        const isActive = pathname.startsWith(link.href)

        return (
          <Link
            className={isActive ? 'text-blue' : 'text-black'}
            href={link.href}
            key={link.name}
          >
            {link.name}
          </Link>
        )


>
            {link.name}
          </Link>
        )
      })}
    </>
  )
}
Scrolling to an id
The default behavior of <Link> is to scroll to the top of the route segment that has changed. When there is an id defined in href, it will scroll to the specific id, similarly to a normal <a> tag.
useRouter() Hook
The useRouter hook allows you to programmatically change routes inside Client Components.
To use useRouter, import it from next/navigation, and call the hook inside your Client Component:
app/page.js 'use client'

import { useRouter } from 'next/navigation'

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

  return (
    <button type="button" onClick={() => router.push('/dashboard')}>
      Dashboard
    </button>
  )
}