Movatterモバイル変換


[0]ホーム

URL:


Skip to content
Important
Security Advisory: React2Shell & two new vulnerabilities
Find out more
API ReferenceFunctionsgenerateMetadata

generateMetadata

Last updated October 17, 2025

You can use themetadata object or thegenerateMetadata function to define metadata.

Themetadata object

To define static metadata, export aMetadata object from alayout.js orpage.js file.

layout.tsx | page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title:'...',  description:'...',}exportdefaultfunctionPage() {}

See theMetadata Fields for a complete list of supported options.

generateMetadata function

Dynamic metadata depends ondynamic information, such as the current route parameters, external data, ormetadata in parent segments, can be set by exporting agenerateMetadata function that returns aMetadata object.

ResolvinggenerateMetadata is part of rendering the page. If the page can be pre-rendered andgenerateMetadata doesn't introduce dynamic behavior, the resulting metadata is included in the page’s initial HTML.

Otherwise the metadata resolved fromgenerateMetadatacan be streamed after sending the initial UI.

app/products/[id]/page.tsx
importtype { Metadata, ResolvingMetadata }from'next'typeProps= {  params:Promise<{ id:string }>  searchParams:Promise<{ [key:string]:string|string[]|undefined }>}exportasyncfunctiongenerateMetadata(  { params, searchParams }:Props,  parent:ResolvingMetadata):Promise<Metadata> {// read route paramsconst {id }=await params// fetch dataconstproduct=awaitfetch(`https://.../${id}`).then((res)=>res.json())// optionally access and extend (rather than replace) parent metadataconstpreviousImages= (await parent).openGraph?.images|| []return {    title:product.title,    openGraph: {      images: ['/some-specific-page-image.jpg',...previousImages],    },  }}exportdefaultfunctionPage({ params, searchParams }:Props) {}

For type completion ofparams andsearchParams, you can type the first argument withPageProps<'/route'> orLayoutProps<'/route'> for pages and layouts respectively.

Good to know:

  • Metadata can be added tolayout.js andpage.js files.
  • Next.js will automatically resolve the metadata, and create the relevant<head> tags for the page.
  • Themetadata object andgenerateMetadata function exports areonly supported in Server Components.
  • You cannot export both themetadata object andgenerateMetadata function from the same route segment.
  • fetch requests insidegenerateMetadata are automaticallymemoized for the same data acrossgenerateMetadata,generateStaticParams, Layouts, Pages, and Server Components.
  • Reactcache can be used iffetch is unavailable.
  • File-based metadata has the higher priority and will override themetadata object andgenerateMetadata function.

Reference

Parameters

generateMetadata function accepts the following parameters:

  • props - An object containing the parameters of the current route:

    • params - An object containing thedynamic route parameters object from the root segment down to the segmentgenerateMetadata is called from. Examples:

      RouteURLparams
      app/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'ssearch 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 aMetadata object containing one or more metadata fields.

Good to know:

  • If metadata doesn't depend on runtime information, it should be defined using the staticmetadata object rather thangenerateMetadata.
  • fetch requests are automaticallymemoized for the same data acrossgenerateMetadata,generateStaticParams, Layouts, Pages, and Server Components. Reactcache can be used iffetch is unavailable.
  • searchParams are only available inpage.js segments.
  • Theredirect() andnotFound() Next.js methods can also be used insidegenerateMetadata.

Metadata Fields

The following fields are supported:

title

Thetitle attribute is used to set the title of the document. It can be defined as a simplestring or an optionaltemplate object.

String
layout.js | page.js
exportconstmetadata= {  title:'Next.js',}
<head> output
<title>Next.js</title>
default

title.default can be used to provide afallback title to child route segments that don't define atitle.

app/layout.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title: {    default:'Acme',  },}
app/about/page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {}// Output: <title>Acme</title>
template

title.template can be used to add a prefix or a suffix totitles defined inchild route segments.

app/layout.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title: {    template:'%s | Acme',    default:'Acme',// a default is required when creating a template  },}
app/about/page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title:'About',}// Output: <title>About | Acme</title>

Good to know:

  • title.template applies tochild route segments andnot the segment it's defined in. This means:
    • title.default isrequired when you add atitle.template.
    • title.template defined inlayout.js will not apply to atitle defined in apage.js of the same route segment.
    • title.template defined inpage.js has no effect because a page is always the terminating segment (it doesn't have any children route segments).
  • title.template hasno effect if a route has not defined atitle ortitle.default.
absolute

title.absolute can be used to provide a title thatignorestitle.template set in parent segments.

app/layout.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title: {    template:'%s | Acme',  },}
app/about/page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title: {    absolute:'About',  },}// Output: <title>About</title>

Good to know:

  • layout.js
    • title (string) andtitle.default define the default title for child segments (that do not define their owntitle). It will augmenttitle.template from the closest parent segment if it exists.
    • title.absolute defines the default title for child segments. It ignorestitle.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 augmenttitle.template from the closest parent segment if it exists.
    • title.absolute defines the route title. It ignorestitle.template from parent segments.
    • title.template has no effect inpage.js because a page is always the terminating segment of a route.

description

layout.js | page.js
exportconstmetadata= {  description:'The React Framework for the Web',}
<head> output
<metaname="description"content="The React Framework for the Web" />

Other fields

layout.js | page.js
exportconstmetadata= {  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' }],  creator:'Jiachi Liu',  publisher:'Sebastian Markbåge',  formatDetection: {    email:false,    address:false,    telephone:false,  },}
<head> output
<metaname="application-name"content="Next.js" /><metaname="author"content="Seb" /><linkrel="author"href="https://nextjs.org" /><metaname="author"content="Josh" /><metaname="generator"content="Next.js" /><metaname="keywords"content="Next.js,React,JavaScript" /><metaname="referrer"content="origin-when-cross-origin" /><metaname="color-scheme"content="dark" /><metaname="creator"content="Jiachi Liu" /><metaname="publisher"content="Sebastian Markbåge" /><metaname="format-detection"content="telephone=no, address=no, email=no" />

metadataBase

metadataBase is a convenience option to set a base URL prefix formetadata fields that require a fully qualified URL.

  • metadataBase allows URL-basedmetadata fields defined in thecurrent route segment and below to use arelative path instead of an otherwise required absolute URL.
  • The field's relative path will be composed withmetadataBase to form a fully qualified URL.
layout.js | page.js
exportconstmetadata= {  metadataBase:newURL('https://acme.com'),  alternates: {    canonical:'/',    languages: {'en-US':'/en-US','de-DE':'/de-DE',    },  },  openGraph: {    images:'/og-image.png',  },}
<head> output
<linkrel="canonical"href="https://acme.com" /><linkrel="alternate"hreflang="en-US"href="https://acme.com/en-US" /><linkrel="alternate"hreflang="de-DE"href="https://acme.com/de-DE" /><metaproperty="og:image"content="https://acme.com/og-image.png" />

Good to know:

  • metadataBase is typically set in rootapp/layout.js to apply to URL-basedmetadata fields across all routes.
  • All URL-basedmetadata fields that require absolute URLs can be configured with ametadataBase option.
  • metadataBase can contain a subdomain e.g.https://app.acme.com or base path e.g.https://acme.com/start/from/here
  • If ametadata field provides an absolute URL,metadataBase will be ignored.
  • Using a relative path in a URL-basedmetadata field without configuring ametadataBase will cause a build error.
  • Next.js will normalize duplicate slashes betweenmetadataBase (e.g.https://acme.com/) and a relative field (e.g./path) to a single slash (e.g.https://acme.com/path)

URL Composition

URL composition favors developer intent over default directory traversal semantics.

  • Trailing slashes betweenmetadataBase andmetadata fields are normalized.
  • An "absolute" path in ametadata field (that typically would replace the whole URL path) is treated as a "relative" path (starting from the end ofmetadataBase).

For example, given the followingmetadataBase:

app/layout.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  metadataBase:newURL('https://acme.com'),}

Anymetadata fields that inherit the abovemetadataBase and set their own value will be resolved as follows:

metadata fieldResolved URL
/https://acme.com
./https://acme.com
paymentshttps://acme.com/payments
/paymentshttps://acme.com/payments
./paymentshttps://acme.com/payments
../paymentshttps://acme.com/payments
https://beta.acme.com/paymentshttps://beta.acme.com/payments

openGraph

layout.js | page.js
exportconstmetadata= {  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',// Must be an absolute URL        width:800,        height:600,      },      {        url:'https://nextjs.org/og-alt.png',// Must be an absolute URL        width:1800,        height:1600,        alt:'My custom alt',      },    ],    videos: [      {        url:'https://nextjs.org/video.mp4',// Must be an absolute URL        width:800,        height:600,      },    ],    audio: [      {        url:'https://nextjs.org/audio.mp3',// Must be an absolute URL      },    ],    locale:'en_US',    type:'website',  },}
<head> output
<metaproperty="og:title"content="Next.js" /><metaproperty="og:description"content="The React Framework for the Web" /><metaproperty="og:url"content="https://nextjs.org/" /><metaproperty="og:site_name"content="Next.js" /><metaproperty="og:locale"content="en_US" /><metaproperty="og:image"content="https://nextjs.org/og.png" /><metaproperty="og:image:width"content="800" /><metaproperty="og:image:height"content="600" /><metaproperty="og:image"content="https://nextjs.org/og-alt.png" /><metaproperty="og:image:width"content="1800" /><metaproperty="og:image:height"content="1600" /><metaproperty="og:image:alt"content="My custom alt" /><metaproperty="og:video"content="https://nextjs.org/video.mp4" /><metaproperty="og:video:width"content="800" /><metaproperty="og:video:height"content="600" /><metaproperty="og:audio"content="https://nextjs.org/audio.mp3" /><metaproperty="og:type"content="website" />
layout.js | page.js
exportconstmetadata= {  openGraph: {    title:'Next.js',    description:'The React Framework for the Web',    type:'article',    publishedTime:'2023-01-01T00:00:00.000Z',    authors: ['Seb','Josh'],  },}
<head> output
<metaproperty="og:title"content="Next.js" /><metaproperty="og:description"content="The React Framework for the Web" /><metaproperty="og:type"content="article" /><metaproperty="article:published_time"content="2023-01-01T00:00:00.000Z" /><metaproperty="article:author"content="Seb" /><metaproperty="article:author"content="Josh" />

Good to know:

  • It may be more convenient to use thefile-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

layout.tsx | page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  robots: {    index:true,    follow:true,    nocache:false,    googleBot: {      index:true,      follow:true,      noimageindex:false,'max-video-preview':-1,'max-image-preview':'large','max-snippet':-1,    },  },}
<head> output
<metaname="robots"content="index, follow" /><metaname="googlebot"content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"/>

icons

Good to know: We recommend using thefile-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
exportconstmetadata= {  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
<linkrel="shortcut icon"href="/shortcut-icon.png" /><linkrel="icon"href="/icon.png" /><linkrel="apple-touch-icon"href="/apple-icon.png" /><linkrel="apple-touch-icon-precomposed"href="/apple-touch-icon-precomposed.png"/>
layout.js | page.js
exportconstmetadata= {  icons: {    icon: [      { url:'/icon.png' },newURL('/icon.png','https://example.com'),      { url:'/icon-dark.png', media:'(prefers-color-scheme: dark)' },    ],    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
<linkrel="shortcut icon"href="/shortcut-icon.png" /><linkrel="icon"href="/icon.png" /><linkrel="icon"href="https://example.com/icon.png" /><linkrel="icon"href="/icon-dark.png"media="(prefers-color-scheme: dark)" /><linkrel="apple-touch-icon"href="/apple-icon.png" /><linkrel="apple-touch-icon-precomposed"href="/apple-touch-icon-precomposed.png"/><linkrel="apple-touch-icon"href="/apple-icon-x3.png"sizes="180x180"type="image/png"/>

Good to know: Themsapplication-* meta tags are no longer supported in Chromium builds of Microsoft Edge, and thus no longer needed.

themeColor

Deprecated: ThethemeColor option inmetadata is deprecated as of Next.js 14. Please use theviewport configuration instead.

colorScheme

Deprecated: ThecolorScheme option inmetadata is deprecated as of Next.js 14. Please use theviewport configuration instead.

manifest

A web application manifest, as defined in theWeb Application Manifest specification.

layout.js | page.js
exportconstmetadata= {  manifest:'https://nextjs.org/manifest.json',}
<head> output
<linkrel="manifest"href="https://nextjs.org/manifest.json" />

twitter

The Twitter specification is (surprisingly) used for more than just X (formerly known as Twitter).

Learn more about theTwitter Card markup reference.

layout.js | page.js
exportconstmetadata= {  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'],// Must be an absolute URL  },}
<head> output
<metaname="twitter:card"content="summary_large_image" /><metaname="twitter:site:id"content="1467726470533754880" /><metaname="twitter:creator"content="@nextjs" /><metaname="twitter:creator:id"content="1467726470533754880" /><metaname="twitter:title"content="Next.js" /><metaname="twitter:description"content="The React Framework for the Web" /><metaname="twitter:image"content="https://nextjs.org/og.png" />
layout.js | page.js
exportconstmetadata= {  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',        googleplay:'twitter_app://googleplay',      },      url: {        iphone:'https://iphone_url',        ipad:'https://ipad_url',      },    },  },}
<head> output
<metaname="twitter:site:id"content="1467726470533754880" /><metaname="twitter:creator"content="@nextjs" /><metaname="twitter:creator:id"content="1467726470533754880" /><metaname="twitter:title"content="Next.js" /><metaname="twitter:description"content="The React Framework for the Web" /><metaname="twitter:card"content="app" /><metaname="twitter:image"content="https://nextjs.org/og.png" /><metaname="twitter:image:alt"content="Next.js Logo" /><metaname="twitter:app:name:iphone"content="twitter_app" /><metaname="twitter:app:id:iphone"content="twitter_app://iphone" /><metaname="twitter:app:id:ipad"content="twitter_app://ipad" /><metaname="twitter:app:id:googleplay"content="twitter_app://googleplay" /><metaname="twitter:app:url:iphone"content="https://iphone_url" /><metaname="twitter:app:url:ipad"content="https://ipad_url" /><metaname="twitter:app:name:ipad"content="twitter_app" /><metaname="twitter:app:name:googleplay"content="twitter_app" />

viewport

Deprecated: Theviewport option inmetadata is deprecated as of Next.js 14. Please use theviewport configuration instead.

verification

layout.js | page.js
exportconstmetadata= {  verification: {    google:'google',    yandex:'yandex',    yahoo:'yahoo',    other: {      me: ['my-email','my-link'],    },  },}
<head> output
<metaname="google-site-verification"content="google" /><metaname="y_key"content="yahoo" /><metaname="yandex-verification"content="yandex" /><metaname="me"content="my-email" /><metaname="me"content="my-link" />

appleWebApp

layout.js | page.js
exportconstmetadata= {  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
<metaname="apple-itunes-app"content="app-id=myAppStoreID, app-argument=myAppArgument"/><metaname="mobile-web-app-capable"content="yes" /><metaname="apple-mobile-web-app-title"content="Apple Web App" /><linkhref="/assets/startup/apple-touch-startup-image-768x1004.png"rel="apple-touch-startup-image"/><linkhref="/assets/startup/apple-touch-startup-image-1536x2008.png"media="(device-width: 768px) and (device-height: 1024px)"rel="apple-touch-startup-image"/><metaname="apple-mobile-web-app-status-bar-style"content="black-translucent"/>

alternates

layout.js | page.js
exportconstmetadata= {  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',    },  },}
<head> output
<linkrel="canonical"href="https://nextjs.org" /><linkrel="alternate"hreflang="en-US"href="https://nextjs.org/en-US" /><linkrel="alternate"hreflang="de-DE"href="https://nextjs.org/de-DE" /><linkrel="alternate"media="only screen and (max-width: 600px)"href="https://nextjs.org/mobile"/><linkrel="alternate"type="application/rss+xml"href="https://nextjs.org/rss"/>

appLinks

layout.js | page.js
exportconstmetadata= {  appLinks: {    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
<metaproperty="al:ios:url"content="https://nextjs.org/ios" /><metaproperty="al:ios:app_store_id"content="app_store_id" /><metaproperty="al:android:package"content="com.example.android/package" /><metaproperty="al:android:app_name"content="app_name_android" /><metaproperty="al:web:url"content="https://nextjs.org/web" /><metaproperty="al:web:should_fallback"content="true" />

archives

Describes a collection of records, documents, or other materials of historical interest (source).

layout.js | page.js
exportconstmetadata= {  archives: ['https://nextjs.org/13'],}
<head> output
<linkrel="archives"href="https://nextjs.org/13" />

assets

layout.js | page.js
exportconstmetadata= {  assets: ['https://nextjs.org/assets'],}
<head> output
<linkrel="assets"href="https://nextjs.org/assets" />

bookmarks

layout.js | page.js
exportconstmetadata= {  bookmarks: ['https://nextjs.org/13'],}
<head> output
<linkrel="bookmarks"href="https://nextjs.org/13" />

category

layout.js | page.js
exportconstmetadata= {  category:'technology',}
<head> output
<metaname="category"content="technology" />

facebook

You can connect a Facebook app or Facebook account to your webpage for certain Facebook Social PluginsFacebook Documentation

Good to know: You can specify either appId or admins, but not both.

layout.js | page.js
exportconstmetadata= {  facebook: {    appId:'12345678',  },}
<head> output
<metaproperty="fb:app_id"content="12345678" />
layout.js | page.js
exportconstmetadata= {  facebook: {    admins:'12345678',  },}
<head> output
<metaproperty="fb:admins"content="12345678" />

If you want to generate multiple fb:admins meta tags you can use array value.

layout.js | page.js
exportconstmetadata= {  facebook: {    admins: ['12345678','87654321'],  },}
<head> output
<metaproperty="fb:admins"content="12345678" /><metaproperty="fb:admins"content="87654321" />

pinterest

You can enable or disablePinterest Rich Pins on your webpage.

layout.js | page.js
exportconstmetadata= {  pinterest: {    richPin:true,  },}
<head> output
<metaname="pinterest-rich-pin"content="true" />

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 theother option to render any custom metadata tag.

layout.js | page.js
exportconstmetadata= {  other: {    custom:'meta',  },}
<head> output
<metaname="custom"content="meta" />

If you want to generate multiple same key meta tags you can use array value.

layout.js | page.js
exportconstmetadata= {  other: {    custom: ['meta1','meta2'],  },}
<head> output
<metaname="custom"content="meta1" /> <metaname="custom"content="meta2" />

Types

You can add type safety to your metadata by using theMetadata type. If you are using thebuilt-in TypeScript plugin in your IDE, you do not need to manually add the type, but you can still explicitly add it if you want.

metadata object

layout.tsx | page.tsx
importtype { Metadata }from'next'exportconstmetadata:Metadata= {  title:'Next.js',}

generateMetadata function

Regular function
layout.tsx | page.tsx
importtype { Metadata }from'next'exportfunctiongenerateMetadata():Metadata {return {    title:'Next.js',  }}
Async function
layout.tsx | page.tsx
importtype { Metadata }from'next'exportasyncfunctiongenerateMetadata():Promise<Metadata> {return {    title:'Next.js',  }}
With segment props
layout.tsx | page.tsx
importtype { Metadata }from'next'typeProps= {  params:Promise<{ id:string }>  searchParams:Promise<{ [key:string]:string|string[]|undefined }>}exportfunctiongenerateMetadata({ params, searchParams }:Props):Metadata {return {    title:'Next.js',  }}exportdefaultfunctionPage({ params, searchParams }:Props) {}
With parent metadata
layout.tsx | page.tsx
importtype { Metadata, ResolvingMetadata }from'next'exportasyncfunctiongenerateMetadata(  { params, searchParams }:Props,  parent:ResolvingMetadata):Promise<Metadata> {return {    title:'Next.js',  }}
JavaScript Projects

For JavaScript projects, you can use JSDoc to add type safety.

layout.js | page.js
/**@type{import("next").Metadata} */exportconstmetadata= {  title:'Next.js',}

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 viaredirect(),Proxy,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 aboutstyling in Next.js.
<script>Learn more aboutusing scripts.
<link rel="stylesheet" />import stylesheets directly in the layout or page itself.
<link rel="preload />UseReactDOM preload method
<link rel="preconnect" />UseReactDOM preconnect method
<link rel="dns-prefetch" />UseReactDOM prefetchDNS method

Resource hints

The<link> element has a number ofrel keywords that can be used to hint to the browser that an 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 newReactDOM methods to safely insert them into the<head> of the document.

app/preload-resources.tsx
'use client'import ReactDOMfrom'react-dom'exportfunctionPreloadResources() {ReactDOM.preload('...', { as:'...' })ReactDOM.preconnect('...', { crossOrigin:'...' })ReactDOM.prefetchDNS('...')return'...'}

<link rel="preload">

Start loading a resource early in the page rendering (browser) lifecycle.MDN Docs.

ReactDOM.preload(href: string, options: { as: string })
<head> output
<linkrel="preload"href="..."as="..." />
<link rel="preconnect">

Preemptively initiate a connection to an origin.MDN Docs.

ReactDOM.preconnect(href: string, options?: { crossOrigin?: string })
<head> output
<linkrel="preconnect"href="..."crossorigin />

<link rel="dns-prefetch">

Attempt to resolve a domain name before resources get requested.MDN Docs.

ReactDOM.prefetchDNS(href: string)
<head> output
<linkrel="dns-prefetch"href="..." />

Good to know:

  • These methods are currently only supported in Client Components, which are still Server Side Rendered on initial page load.
  • Next.js in-built features such asnext/font,next/image andnext/script automatically handle relevant resource hints.

Behavior

Default Fields

There are two defaultmeta tags that are always added even if a route doesn't define metadata:

  • Themeta charset tag sets the character encoding for the website.
  • Themeta viewport tag sets the viewport width and scale for the website to adjust for different devices.
<metacharset="utf-8" /><metaname="viewport"content="width=device-width, initial-scale=1" />

Good to know: You can overwrite the defaultviewport meta tag.

Streaming metadata

Streaming metadata allows Next.js to render and send the initial UI to the browser, without waiting forgenerateMetadata to complete.

WhengenerateMetadata resolves, the resulting metadata tags are appended to the<body> tag. We have verified that metadata is interpreted correctly by bots that execute JavaScript and inspect the full DOM (e.g.Googlebot).

ForHTML-limited bots that can’t execute JavaScript (e.g.facebookexternalhit), metadata continues to block page rendering. The resulting metadata will be available in the<head> tag.

Next.js automatically detectsHTML-limited bots by looking at the User Agent header. You can use thehtmlLimitedBots option in your Next.js config file to override the defaultUser Agent list.

To fully disable streaming metadata:

next.config.ts
importtype { NextConfig }from'next'constconfig:NextConfig= {  htmlLimitedBots: /.*/,}exportdefault config

Streaming metadata improves perceived performance by reducingTTFB and can help loweringLCP time.

OverridinghtmlLimitedBots could lead to longer response times. Streaming metadata is an advanced feature, and the default should be sufficient for most cases.

Ordering

Metadata is evaluated in order, starting from the root segment down to the segment closest to the finalpage.js segment. For example:

  1. app/layout.tsx (Root Layout)
  2. app/blog/layout.tsx (Nested Blog Layout)
  3. app/blog/[slug]/page.tsx (Blog Page)

Merging

Following theevaluation order, Metadata objects exported from multiple segments in the same route areshallowly merged together to form the final metadata output of a route. Duplicate keys arereplaced based on their ordering.

This means metadata with nested fields such asopenGraph androbots that are defined in an earlier segment areoverwritten by the last segment to define them.

Overwriting fields

app/layout.js
exportconstmetadata= {  title:'Acme',  openGraph: {    title:'Acme',    description:'Acme is a...',  },}
app/blog/page.js
exportconstmetadata= {  title:'Blog',  openGraph: {    title:'Blog',  },}// Output:// <title>Blog</title>// <meta property="og:title" content="Blog" />

In the example above:

  • title fromapp/layout.js isreplaced bytitle inapp/blog/page.js.
  • AllopenGraph fields fromapp/layout.js arereplaced inapp/blog/page.js becauseapp/blog/page.js setsopenGraph metadata. Note the absence ofopenGraph.description.

If you'd like to share some nested fields between segments while overwriting others, you can pull them out into a separate variable:

app/shared-metadata.js
exportconstopenGraphImage= { images: ['http://...'] }
app/page.js
import { openGraphImage }from'./shared-metadata'exportconstmetadata= {  openGraph: {...openGraphImage,    title:'Home',  },}
app/about/page.js
import { openGraphImage }from'../shared-metadata'exportconstmetadata= {  openGraph: {...openGraphImage,    title:'About',  },}

In the example above, the OG image is shared betweenapp/layout.js andapp/about/page.js while the titles are different.

Inheriting fields

app/layout.js
exportconstmetadata= {  title:'Acme',  openGraph: {    title:'Acme',    description:'Acme is a...',  },}
app/about/page.js
exportconstmetadata= {  title:'About',}// Output:// <title>About</title>// <meta property="og:title" content="Acme" />// <meta property="og:description" content="Acme is a..." />

Notes

  • title fromapp/layout.js isreplaced bytitle inapp/about/page.js.
  • AllopenGraph fields fromapp/layout.js areinherited inapp/about/page.js becauseapp/about/page.js doesn't setopenGraph metadata.

Version History

VersionChanges
v15.2.0Introduced streaming support togenerateMetadata.
v13.2.0viewport,themeColor, andcolorScheme deprecated in favor of theviewport configuration.
v13.2.0metadata andgenerateMetadata introduced.

Next Steps

View all the Metadata API options.

Was this helpful?

supported.

[8]ページ先頭

©2009-2025 Movatter.jp