Next.js
Beginner
1 min read
Static and Dynamic Metadata with the Metadata API
Example
// app/layout.tsx — root metadata with title template
import type { Metadata } from 'next';
export const metadata: Metadata = {
// Title template: child pages set title, root appends '| Acme'
title: {
template: '%s | Acme',
default: 'Acme — Build faster',
},
description: 'Acme helps you ship software faster.',
metadataBase: new URL('https://acme.com'), // required for absolute OG URLs
openGraph: {
siteName: 'Acme',
locale: 'en_US',
type: 'website',
},
robots: {
index: true,
follow: true,
googleBot: { index: true, follow: true },
},
};
// app/blog/[slug]/page.tsx — dynamic metadata
import type { Metadata } from 'next';
async function getPost(slug: string) {
const res = await fetch(`https://api.example.com/posts/${slug}`, {
next: { revalidate: 3600 },
});
if (!res.ok) return null;
return res.json();
}
export async function generateMetadata({
params,
}: {
params: { slug: string };
}): Promise<Metadata> {
const post = await getPost(params.slug); // deduplicated with page fetch
if (!post) return { title: 'Post not found' };
return {
title: post.title, // rendered as "Post Title | Acme"
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
images: [{ url: post.coverImageUrl, width: 1200, height: 630 }],
type: 'article',
publishedTime: post.publishedAt,
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.coverImageUrl],
},
};
}