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.


<Script>
This API reference will help you understand how to use props available for the Script Component. For features and usage, please see the Optimizing Scripts page.
app/dashboard/page.tsx import Script from 'next/script'

export default function Dashboard() {
  return (
    <>
      <Script src="https://example.com/script.js" />
    </>
  )
}
Props
Here's a summary of the props available for the Script Component:
PropExampleTypeRequiredsrcsrc="http://example.com/script"StringRequired unless inline script is usedstrategystrategy="lazyOnload"String-onLoadonLoad={onLoadFunc}Function-onReadyonReady={onReadyFunc}Function-onErroronError={onErrorFunc}Function-
Required Props
The <Script /> component requires the following properties.
src


Required Props
The <Script /> component requires the following properties.
src
A path string specifying the URL of an external script. This can be either an absolute external URL or an internal path. The src property is required unless an inline script is used.
Optional Props
The <Script /> component accepts a number of additional properties beyond those which are required.
strategy
The loading strategy of the script. There are four different strategies that can be used:
beforeInteractive: Load before any Next.js code and before any page hydration occurs.
afterInteractive: (default) Load early but after some hydration on the page occurs.
lazyOnload: Load during browser idle time.
worker: (experimental) Load in a web worker.
beforeInteractive
Scripts that load with the beforeInteractive strategy are injected into the initial HTML from the server, downloaded before any Next.js module, and executed in the order they are placed before any hydration occurs on the page.


Scripts denoted with this strategy are preloaded and fetched before any first-party code, but their execution does not block page hydration from occurring.
beforeInteractive scripts must be placed inside the root layout (app/layout.tsx) and are designed to load scripts that are needed by the entire site (i.e. the script will load when any page in the application has been loaded server-side).
This strategy should only be used for critical scripts that need to be fetched before any part of the page becomes interactive.
app/layout.tsx import Script from 'next/script'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>{children}</body>
      <Script
        src="https://example.com/script.js"
        strategy="beforeInteractive"
      />
    </html>
  )
}


strategy="beforeInteractive"
      />
    </html>
  )
}
Good to know: Scripts with beforeInteractive will always be injected inside the head of the HTML document regardless of where it's placed in the component.
Some examples of scripts that should be loaded as soon as possible with beforeInteractive include:
Bot detectors
Cookie consent managers
afterInteractive
Scripts that use the afterInteractive strategy are injected into the HTML client-side and will load after some (or all) hydration occurs on the page. This is the default strategy of the Script component and should be used for any script that needs to load as soon as possible but not before any first-party Next.js code.
afterInteractive scripts can be placed inside of any page or layout and will only load and execute when that page (or group of pages) is opened in the browser.
app/page.js import Script from 'next/script'

export default function Page() {
  return (


export default function Page() {
  return (
    <>
      <Script src="https://example.com/script.js" strategy="afterInteractive" />
    </>
  )
}
Some examples of scripts that are good candidates for afterInteractive include:
Tag managers
Analytics
lazyOnload
Scripts that use the lazyOnload strategy are injected into the HTML client-side during browser idle time and will load after all resources on the page have been fetched. This strategy should be used for any background or low priority scripts that do not need to load early.
lazyOnload scripts can be placed inside of any page or layout and will only load and execute when that page (or group of pages) is opened in the browser.
app/page.js import Script from 'next/script'

export default function Page() {
  return (
    <>


export default function Page() {
  return (
    <>
      <Script src="https://example.com/script.js" strategy="lazyOnload" />
    </>
  )
}
Examples of scripts that do not need to load immediately and can be fetched with lazyOnload include:
Chat support plugins
Social media widgets
worker
Warning: The worker strategy is not yet stable and does not yet work with the app directory. Use with caution.
Scripts that use the worker strategy are off-loaded to a web worker in order to free up the main thread and ensure that only critical, first-party resources are processed on it. While this strategy can be used for any script, it is an advanced use case that is not guaranteed to support all third-party scripts.
To use worker as a strategy, the nextScriptWorkers flag must be enabled in next.config.js:
next.config.js module.exports = {
  experimental: {


next.config.js module.exports = {
  experimental: {
    nextScriptWorkers: true,
  },
}
worker scripts can only currently be used in the pages/ directory:
pages/home.tsx import Script from 'next/script'

export default function Home() {
  return (
    <>
      <Script src="https://example.com/script.js" strategy="worker" />
    </>
  )
}
onLoad
Warning: onLoad does not yet work with Server Components and can only be used in Client Components. Further, onLoad can't be used with beforeInteractive – consider using onReady instead.
Some third-party scripts require users to run JavaScript code once after the script has finished loading in order to instantiate content or call a function. If you are loading a script with either afterInteractive or lazyOnload as a loading strategy, you can execute code after it has loaded using the onLoad property.


Here's an example of executing a lodash method only after the library has been loaded.
app/page.tsx 'use client'

import Script from 'next/script'

export default function Page() {
  return (
    <>
      <Script
        src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"
        onLoad={() => {
          console.log(_.sample([1, 2, 3, 4]))
        }}
      />
    </>
  )
}
onReady
Warning: onReady does not yet work with Server Components and can only be used in Client Components.


Some third-party scripts require users to run JavaScript code after the script has finished loading and every time the component is mounted (after a route navigation for example). You can execute code after the script's load event when it first loads and then after every subsequent component re-mount using the onReady property.
Here's an example of how to re-instantiate a Google Maps JS embed every time the component is mounted:
app/page.tsx 'use client'

import { useRef } from 'react'
import Script from 'next/script'

export default function Page() {
  const mapRef = useRef()

  return (
    <>


onReady={() => {
          new google.maps.Map(mapRef.current, {
            center: { lat: -34.397, lng: 150.644 },
            zoom: 8,
          })
        }}
      />
    </>
  )
}
onError
Warning: onError does not yet work with Server Components and can only be used in Client Components. onError cannot be used with the beforeInteractive loading strategy.
Sometimes it is helpful to catch when a script fails to load. These errors can be handled with the onError property:
app/page.tsx 'use client'

import Script from 'next/script'

export default function Page() {
  return (
    <>
      <Script
        src="https://example.com/script.js"
        onError={(e: Error) => {
          console.error('Script failed to load', e)
        }}
      />


console.error('Script failed to load', e)
        }}
      />
    </>
  )
}
Version History
VersionChangesv13.0.0beforeInteractive and afterInteractive is modified to support app.v12.2.4onReady prop added.v12.2.2Allow next/script with beforeInteractive to be placed in _document.v11.0.0next/script introduced.


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


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.


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.


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.


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.


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.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.


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.


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


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


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.


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.


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.


cookiesThe cookies function allows you to read the HTTP incoming request cookies from a Server Component or write outgoing request cookies in a Server Action or Route Handler.
Good to know: cookies() is a Dynamic Function whose returned values cannot be known ahead of time. Using it in a layout or page will opt a route into dynamic rendering at request time.
cookies().get(name)
A method that takes a cookie name and returns an object with name and value. If a cookie with name isn't found, it returns undefined. If multiple cookies match, it will only return the first match.
app/page.js import { cookies } from 'next/headers'

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


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

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

Name: {cookie.name}

Value: {cookie.value}

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

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


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

import { cookies } from 'next/headers'

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


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

import { cookies } from 'next/headers'

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


Version History
VersionChangesv13.0.0cookies introduced.


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

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

My Blog Post

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

  )
}
Version History
VersionChangesv13.4.0draftMode introduced.


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

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


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

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


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


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


Conflicting options such as { revalidate: 0, cache: 'force-cache' } or { revalidate: 10, cache: 'no-store' } will cause an error.
Version History
VersionChangesv13.0.0fetch introduced.


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


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

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

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


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

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


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

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

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

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


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


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

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

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

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


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

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

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

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

  // fetch data


// read route params
  const id = params.id

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

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

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

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


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


generateMetadata should return a Metadata object containing one or more metadata fields.
Good to know:
If metadata doesn't depend on runtime information, it should be defined using the static metadata object rather than generateMetadata.
When rendering a route, Next.js will automatically deduplicate fetch requests for the same data across generateMetadata, generateStaticParams, Layouts, Pages, and Server Components. React cache can be used if fetch is unavailable.
searchParams are only available in page.js segments.
The redirect() and notFound() Next.js methods can also be used inside generateMetadata.
Metadata Fields
title
The title attribute is used to set the title of the document. It can be defined as a simple string or an optional template object.
String
layout.js / page.js export const metadata = {
  title: 'Next.js',
}
<head> output <title>Next.js</title>
Template object


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

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

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

export const metadata: Metadata = {}

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


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

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

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

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


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

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

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

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


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


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


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


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


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


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

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


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


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


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


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

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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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


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