The Metadata API is the App Router's built-in system for setting <title>, <meta>, and Open Graph tags per route, replacing the need to manually manage a <head> tag or a third-party library. This lesson covers static and dynamic metadata.
Static Metadata with the metadata Export
Any layout.tsx or page.tsx can export a metadata object containing a title, description, and many other fields. Next.js reads this object at build/render time and injects the corresponding tags into the document <head> automatically — you never write a <head> tag yourself in the App Router.
Metadata from nested layouts and pages merges together, with more specific (deeper) values taking priority — so a root layout might set a default title.template, while individual pages just set their own specific title.
// app/about/page.tsx
export const metadata = {
title: "About Us",
description: "Learn about our company's mission and team.",
};
export default function AboutPage() {
return <h1>About Us</h1>;
}
Next.js generates <title>About Us</title> and the matching <meta name="description"> tag automatically.
Static Metadata Object Shape
export const metadata = {
title: "Page Title",
description: "Page description for search engines.",
openGraph: {
title: "Page Title",
description: "Shown when shared on social media.",
images: ["/og-image.png"],
},
};
title and description are the most commonly used fields, mapping directly to <title>/<meta name="description">.
openGraph controls how the page appears when shared on social platforms like Facebook or LinkedIn.
Metadata exports must use plain, static values — for dynamic values, use generateMetadata instead.
A root layout can define a title.template (like "%s | My Site") that pages fill in automatically.
Metadata Fields Cheat Sheet
Commonly used fields in the metadata object.
Field
Purpose
title
Page <title> tag
description
<meta name="description">
openGraph
Social sharing preview data
twitter
Twitter/X-specific sharing card data
robots
Per-page indexing directives
alternates.canonical
Canonical URL for duplicate content
Title Templates in the Root Layout
Setting a title.template once in the root layout lets every page's own title get consistently formatted (e.g. appending your site name) without repeating that suffix in every single page's metadata export.
// app/layout.tsx
export const metadata = {
title: {
template: "%s | My Company",
default: "My Company",
},
};
// app/about/page.tsx
export const metadata = { title: "About" }; // renders as "About | My Company"
How Metadata Merges Across Layouts
Metadata fields merge shallowly: a page's metadata.openGraph entirely replaces a parent layout's openGraph object (rather than merging field by field), while unrelated fields like title are inherited independently. Understanding this shallow-merge behavior helps avoid surprises when a page seems to lose some inherited fields.
Common Mistakes
Exporting a metadata object with dynamic, per-request values instead of using generateMetadata.
Forgetting that nested openGraph (and similar object fields) replace, rather than merge with, a parent's values.
Not setting a title.template in the root layout, leading to inconsistent title formatting across pages.
Leaving default, generic metadata on every page instead of writing unique titles and descriptions.
Key Takeaways
The metadata export sets <title>, <meta>, and Open Graph tags declaratively, per route.
Metadata merges from the root layout down to the page, with deeper values taking priority.
title.template in the root layout standardizes title formatting across the whole site.
Object fields like openGraph replace (rather than merge into) a parent's value when overridden.
Use generateMetadata (covered next) for metadata that depends on dynamic data.
Pro Tip
Set a sensible title.template and a fallback description in your root layout on day one — this guarantees every route has reasonable metadata by default, even ones you haven't gotten around to customizing yet.
You now understand static metadata. Next, learn generateMetadata for dynamic, per-route metadata based on real content.