The App Router has a built-in Metadata API for SEO tags (<title>, <meta>, Open Graph, etc.) — you export metadata from a layout.tsx or page.tsx and Next.js renders the correct <head> tags.
The App Router has a built-in Metadata API for SEO tags (<title>, <meta>, Open Graph, etc.) — you export metadata from a layout.tsx or page.tsx and Next.js renders the correct <head> tags.
// app/about/page.tsx
import type { Metadata } from "next";
export const metadata: Metadata = {
title: "About Us",
description: "Learn about our company and team.",
openGraph: {
title: "About Us",
images: ["/og-about.png"],
},
};
export default function About() { return <h1>About</h1>; }
Next.js reads the exported metadata object and generates <title>, <meta name="description">, OG tags, etc. — no manual <head> editing.
For pages whose title depends on fetched content (a blog post, a product), export an async generateMetadata function:
// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug); // fetch the post
return {
title: post.title,
description: post.excerpt,
openGraph: { images: [post.coverImage] },
};
}
This runs on the server and lets each dynamic page have accurate, content-specific metadata — essential for SEO and social sharing of dynamic content.
// app/layout.tsx — defaults + a title template
export const metadata: Metadata = {
title: { default: "My Site", template: "%s | My Site" }, // child titles become "About | My Site"
};
Metadata defined in a layout is merged with (and can be overridden by) child pages — so you set site-wide defaults once and per-page values where needed. The template automatically appends the site name.
app/favicon.ico, app/opengraph-image.png, app/robots.ts, app/sitemap.ts
Special files generate the corresponding metadata/routes automatically.
Good metadata drives SEO and social-share previews.
The Metadata API makes it declarative and type-safe — static metadata for fixed pages, async generateMetadata for data-driven pages, and layout-level defaults with templates — replacing manual <head> management with a clean, server-rendered system.