Static Metadata Object
layout.tsx or page.tsx in the App Router can export a metadata object to control the page's <title>, meta description, Open Graph tags, icons, and more. Next.js reads it at build time (or request time for dynamic routes) and injects the right tags into <head> — you never touch <head> directly.app/about/page.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'About Us',
description: 'Learn about our mission, team, and history.',
}
export default function AboutPage() {
return <h1>About Us</h1>
}Common fields
Field | Purpose |
|---|---|
| The |
| The meta description search engines often show under your title |
| Rarely used by modern search engines, but still supported |
| Title, description, image, and type used when the page is shared on social platforms |
| Twitter/X-specific card metadata, falls back to |
| Favicon and apple-touch-icon references |
| Canonical URL and alternate-language versions of the page |
app/blog/[slug]/layout.tsx — a fuller example
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Our Blog',
description: 'Engineering notes and product updates.',
openGraph: {
title: 'Our Blog',
description: 'Engineering notes and product updates.',
images: ['/og/blog.png'],
type: 'website',
},
twitter: {
card: 'summary_large_image',
},
icons: {
icon: '/favicon.ico',
apple: '/apple-touch-icon.png',
},
}Title templates
title.template that child pages' titles get slotted into — handy for a consistent "Page Name | Site Name" format without repeating the site name on every page.app/layout.tsx
export const metadata: Metadata = {
title: {
template: '%s | Acme Docs',
default: 'Acme Docs',
},
}app/getting-started/page.tsx
export const metadata: Metadata = {
title: 'Getting Started', // renders as "Getting Started | Acme Docs"
}title fills the %s slot in the nearest ancestor's template, while fields like openGraph are shallow-merged, so it's worth checking rendered output when combining metadata across several nested layouts.metadata object whenever a page's title and description are known ahead of time — most marketing pages, static docs, and legal pages. Reach for generateMetadata (the async function, covered next) only when the metadata genuinely depends on data fetched at request time, like a blog post's title coming from a CMS.metadata export only works in Server Components. A file marked 'use client' can't export metadata — put metadata in a nearby layout instead if the page itself needs to be a Client Component.Export a static
metadata: Metadataobject from alayout.tsxorpage.tsxwhen the values are known at build time.Common fields:
title,description,openGraph,twitter,icons,alternates.title.templateon a layout lets child pages fill a%splaceholder for consistent branded titles.Metadata merges down the layout tree rather than fully replacing parent values.
The
metadataexport requires a Server Component — Client Components cannot export it.