MetadataRoute.Manifest type reference
The manifest object contains an extensive list of options that may be updated due to new web standards. The complete options are defined by the MetadataRoute.Manifest type and can be viewed in TypeScript IDE with the IDE Plugin feature or in the MDN Web Manifest documentation.
manifest.js function example
The following is a working example of a manifest.js file:
```js
export default function manifest() {
return {
name: 'Next.js App',
short_name: 'Next.js App',
description: 'Next.js App',
start_url: '/',
display: 'standalone',
background_color: '#fff',
theme_color: '#fff',
icons: [
{
src: '/favicon.ico',
sizes: 'any',
type: 'image/x-icon',
},
],
}
}
```
Generate manifest with manifest.js or manifest.ts
A dynamic manifest file can be generated by creating a manifest.js or manifest.ts file in the app directory that exports a default function returning a MetadataRoute.Manifest object.
Static manifest file example
A static manifest file can be created as app/manifest.json or app/manifest.webmanifest with JSON content containing fields like name, short_name, description, and start_url.
manifest.js is a special Route Handler with default caching
manifest.js is a special Route Handler that is cached by default unless it uses a Request-time API or dynamic config option.
manifest.json file location and format
A manifest.(json|webmanifest) file must be placed in the root of the app directory to provide information about the web application for the browser. It must match the Web Manifest Specification.
manifest.ts function example
The following is a working example of a manifest.ts file:
```ts
import type { MetadataRoute } from 'next'
export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Next.js App',
short_name: 'Next.js App',
description: 'Next.js App',
start_url: '/',
display: 'standalone',
background_color: '#fff',
theme_color: '#fff',
icons: [
{
src: '/favicon.ico',
sizes: 'any',
type: 'image/x-icon',
},
],
}
}
```
size config export for opengraph-image and twitter-image
Export a const size with an object containing width and height number properties to set the image dimensions. This generates the meta tags: <meta property="og:image:width" content="<width>" /> and <meta property="og:image:height" content="<height>" />.
alt config export for opengraph-image and twitter-image
Export a const alt with a string value to set the image's alt text. This generates the meta tag: <meta property="og:image:alt" content="<value>" />.
opengraph-image and twitter-image function props: params
The default export function in opengraph-image or twitter-image receives an optional params prop. The params prop is a promise that resolves to an object containing the dynamic route parameters from the root segment down to the segment where opengraph-image or twitter-image is colocated. If generateImageMetadata is used, the function will also receive an id prop that is a promise resolving to the id value from one of the items returned by generateImageMetadata.
Example: opengraph-image with dynamic params and external data
This example shows how to generate an opengraph-image using params and fetched external data:
import { ImageResponse } from 'next/og'
export const alt = 'About Acme'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
export default async function Image({
params,
}: {
params: Promise<{ slug: string }>
}) {
const { slug } = await params
const post = await fetch(`https://.../posts/${slug}`).then((res) =>
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,
}
)
}
opengraph-image and twitter-image params examples
For route app/shop/opengraph-image.js at URL /shop, params is undefined. For route app/shop/[slug]/opengraph-image.js at URL /shop/1, params is Promise<{ slug: '1' }>. For route app/shop/[tag]/[item]/opengraph-image.js at URL /shop/1/2, params is Promise<{ tag: '1', item: '2' }>.
opengraph-image and twitter-image file conventions overview
The 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 these images: using image files (.jpg, .png, .gif) or using code to generate images (.js, .ts, .tsx).
twitter-image.alt.txt alt text convention
Add an accompanying twitter-image.alt.txt file in the same route segment as the twitter-image.(jpg|jpeg|png|gif) image to set its alt text. This generates the meta tag: <meta name="twitter:image:alt" content="<content>" />.
opengraph-image and twitter-image 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.
contentType config export for opengraph-image and twitter-image
Export a const contentType with a string value (image MIME type) to set the image content type. This generates the meta tag: <meta property="og:image:type" content="<value>" />.
twitter-image meta tags generated
When a twitter-image file is placed in a route segment, Next.js automatically generates the following meta tags in the <head> element: <meta name="twitter:image" content="<generated>" />, <meta name="twitter:image:type" content="<generated>" />, <meta name="twitter:image:width" content="<generated>" />, <meta name="twitter:image:height" content="<generated>" />.
opengraph-image and twitter-image return type
The default export function should return a Response. ImageResponse satisfies this return type.
opengraph-image.alt.txt alt text convention
Add an accompanying opengraph-image.alt.txt file in the same route segment as the opengraph-image.(jpg|jpeg|png|gif) image to set its alt text. This generates the meta tag: <meta property="og:image:alt" content="<content>" />.
Example: opengraph-image with ImageResponse and custom font
This example shows how to generate an opengraph-image using ImageResponse from next/og with a custom font:
import { ImageResponse } from 'next/og'
import { readFile } from 'node:fs/promises'
import { join } from 'node:path'
export const alt = 'About Acme'
export const size = {
width: 1200,
height: 630,
}
export const contentType = 'image/png'
const interSemiBold = await readFile(
join(process.cwd(), 'assets/Inter-SemiBold.ttf')
)
export default async function Image() {
return new ImageResponse(
(
<div
style={{
fontSize: 128,
background: 'white',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
About Acme
</div>
),
{
...size,
fonts: [
{
name: 'Inter',
data: interSemiBold,
style: 'normal',
weight: 400,
},
],
}
)
}
Example: opengraph-image with local assets as base64
This example shows how to read a local image file and pass it as a base64 data URL to an img element in opengraph-image:
import { ImageResponse } from 'next/og'
import { join } from 'node:path'
import { readFile } from 'node:fs/promises'
const logoData = await readFile(join(process.cwd(), 'logo.png'), 'base64')
const logoSrc = `data:image/png;base64,${logoData}`
export default async function Image() {
return new ImageResponse(
(
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<img src={logoSrc} height="100" />
</div>
)
)
}
opengraph-image meta tags generated
When an opengraph-image file is placed in a route segment, Next.js automatically generates the following meta tags in the <head> element: <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>" />.
Generated images using code file types
To programmatically generate images, create an opengraph-image or twitter-image route that default exports a function. Supported file types are .js, .ts, .tsx for both opengraph-image and twitter-image.
ImageResponse API from next/og
The easiest way to generate an image for opengraph-image or twitter-image is to use the ImageResponse API from next/og.
Example: opengraph-image with local assets as ArrayBuffer
This example shows how to read a local image file and pass it as an ArrayBuffer to an img element in opengraph-image. Note that passing an ArrayBuffer to the src attribute of an img element is not part of the HTML spec, but the rendering engine used by next/og supports it. TypeScript definitions follow the spec, so a @ts-expect-error directive is needed:
import { ImageResponse } from 'next/og'
import { join } from 'node:path'
import { readFile } from 'node:fs/promises'
const logoData = await readFile(join(process.cwd(), 'logo.png'))
const logoSrc = Uint8Array.from(logoData).buffer
export default async function Image() {
return new ImageResponse(
(
<div
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{/* @ts-expect-error Satori accepts ArrayBuffer/typed arrays for <img src> at runtime */}
<img src={logoSrc} height="100" />
</div>
)
)
}
opengraph-image and twitter-image supported file types for static images
Static image files are supported with the following conventions and file types: opengraph-image supports .jpg, .jpeg, .png, .gif; twitter-image supports .jpg, .jpeg, .png, .gif; opengraph-image.alt supports .txt; twitter-image.alt supports .txt.
generateImageMetadata for multiple images
You can generate multiple images in the same file using generateImageMetadata.
opengraph-image and twitter-image version history
In version 13.3.0, opengraph-image and twitter-image were introduced. In version 16.0.0, params became a promise that resolves to an object (previously it was a direct object).
opengraph-image and twitter-image file size limits
The twitter-image file size must not exceed 5MB, and the opengraph-image file size must not exceed 8MB. If the image file size exceeds these limits, the build will fail.
Generated images static optimization behavior
By default, generated images from opengraph-image.js and twitter-image.js are statically optimized (generated at build time and cached) unless they use Request-time APIs or uncached data. These are special Route Handlers that are cached by default unless they use a Request-time API or dynamic config option.
opengraph-image and twitter-image config exports
You can optionally configure the image's metadata by exporting the following variables from opengraph-image or twitter-image route: alt (string), size ({ width: number; height: number }), contentType (string - image MIME type).
dynamicParams not available with Cache Components
dynamicParams is not available when Cache Components is enabled.
dynamicParams replaces getStaticPaths fallback option
The dynamicParams option replaces the fallback: true | false | blocking option of getStaticPaths in the pages directory.
dynamicParams false behavior
When dynamicParams is set to false, dynamic route segments not included in generateStaticParams will return a 404 response.
dynamicParams true behavior
When dynamicParams is set to true (the default), dynamic route segments not included in generateStaticParams are generated at request time.
dynamicParams route segment config option
The dynamicParams option controls what happens when a dynamic segment is visited that was not generated with generateStaticParams. It can be set to true (default) or false, and is exported from layout.tsx, page.tsx, layout.js, page.js, or route.js files.
maxDuration route segment config option
The maxDuration option is a number type route segment config option. Its default value is set by the deployment platform. This option can be exported from a Page, Layout, or Route Handler.
Route Segment Config changes in v16.0.0
In v16.0.0, when Cache Components is enabled, the following options were removed: dynamic, dynamicParams, revalidate, and fetchCache. These options are covered in the Caching and Revalidating (Previous Model) guide. Also in v16.0.0, export const experimental_ppr = true was removed; a codemod is available to migrate this.
runtime route segment config option
The runtime option accepts values 'nodejs' or 'edge' (deprecated). The default value is 'nodejs'. This option can be exported from a Page, Layout, or Route Handler.
Route Segment Config options available
Route Segment Config options allow you to configure the behavior of a Page, Layout, or Route Handler by directly exporting variables. The available options are: dynamicParams (boolean, default true), runtime ('nodejs' | 'edge' (deprecated), default 'nodejs'), preferredRegion ('auto' | 'global' | 'home' | string | string[] (deprecated), default 'auto'), and maxDuration (number, default set by deployment platform).
dynamicParams route segment config option
The dynamicParams option is a boolean route segment config option. It has a default value of true. This option can be exported from a Page, Layout, or Route Handler.
runtime experimental-edge deprecation
As of v15.0.0-RC, export const runtime = 'experimental-edge' is deprecated. A codemod is available to transform app router route segment config runtime value from experimental-edge to edge.
preferredRegion route segment config option
The preferredRegion option accepts values 'auto', 'global', 'home', string, or string[] (deprecated). The default value is 'auto'. This option can be exported from a Page, Layout, or Route Handler.
instant level option
The `level` option in the `instant` config object sets the severity at which validation runs for a segment. The value 'warning' validates in development only with errors appearing in the dev overlay; the build is unaffected.
instant validation scope and boundaries
The `instant` config triggers validation at every shared layout boundary in the route. Validation runs during development on page loads and HMR updates, surfacing errors in the dev error overlay. Each error identifies the component that would block navigation.
instant config values
The `instant` export accepts three types of values: true (validates at globally configured level with framework defaults of development only), false (opts segment out of validation), or an object with additional options like `level`.
instantInsights validationLevel options
The `experimental.instantInsights.validationLevel` config supports two levels: 'warning' (framework default) validates every Page and Default segment implicitly at warning level in dev only, and 'manual-warning' only validates segments with explicit `instant` config at warning level in dev only.
instant route segment config export
The `instant` route segment config controls how Next.js validates whether a navigation into a segment would produce an instant UI. It is exported as a constant from layout or page files.
instant config default validation level
By default with `validationLevel: 'warning'`, Cache Components apps validate every Page and Default segment in development. The `experimental.instantInsights.validationLevel` config in next.config.js tunes this behavior.
instant TypeScript type
The TypeScript type for the `instant` export is: `type InstantConfig = true | false | { level?: 'warning' }`
instant static shell validation
Cache Components validates that each page produces a non-empty static shell at prerender time. To opt a route out of this validation, ensure the highest `instant` config in the route's tree is `false` — a `false` higher in the tree takes precedence over any deeper `true` for the static-shell check.
instant false in ancestor layout example
Example showing `instant = false` in app/tabs/layout.tsx to allow blocking at the layout level, paired with `instant = true` in app/tabs/[tab]/page.tsx to validate navigations between tabs as instant.
instant config requires cacheComponents enabled
The `instant` export only works when the `cacheComponents` configuration option is enabled. Without it, the instant config has no effect.
instant cannot be used in Client Components
The `instant` export cannot be used in Client Components. Using it in a Client Component will throw an error.
instant export example
Example of using the instant route segment config: `export const instant = true` exported from a layout.tsx or page.tsx file, paired with the default export component.
instant false disables validation
Setting `instant = false` on a layout or page indicates that the segment is allowed to block when navigating to it. This is useful when a deeper page should be instant but an ancestor cannot be, allowing you to opt specific segments out of instant validation.
instant validation in development vs production
Next.js does not perform prefetches in development, so navigations may not feel as instant as they will in production. Validation reflects what will happen during `next start`, where prefetching is enabled.
instant level object example
Example of configuring instant with a level option: `export const instant = { level: 'warning' }` exported from a page.tsx file.
instant validation does not force descendants
A higher-up `instant = true` does not force its descendants to validate. Leaving an ancestor unconfigured is fine. Only reach for `instant = false` when a deeper page is configured as instant and you need to exempt navigations that pass through a blocking ancestor.
instant fixes usually involve use cache or Suspense
When instant validation identifies a component that would block navigation, the fix is usually to cache the data with `use cache` or wrap it in a `<Suspense>` boundary.