The Next.js Metadata API lets you define <title>, <meta>, and Open Graph social tags using exported TypeScript objects or async functions inside layout.tsx and page.tsx. Next.js merges parent and child metadata automatically and injects valid tags into the document <head>.
You no longer need manual <Head> components in every route. Type checking catches invalid property names in your editor before deployment.
Export a metadata constant typed with Metadata from next for pages with fixed titles and descriptions.
// app/pricing/page.tsx
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'Pricing Plans | DevCloud',
description: 'Compare starter, team, and enterprise hosting tiers on DevCloud.',
openGraph: {
title: 'Pricing Plans | DevCloud',
description: 'Simple monthly pricing for growing engineering teams.',
images: ['/images/pricing-og.png'],
},
};
export default function PricingPage() {
return (
<section className="p-6">
<h2 className="text-2xl font-bold">Simple Transparent Pricing</h2>
</section>
);
}
For product pages or blog posts, export an async generateMetadata function that fetches the item and builds a unique title and description.
// app/blog/[slug]/page.tsx
import type { Metadata } from 'next';
interface Props {
params: Promise<{ slug: string }>;
}
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params;
const post = await fetch(`https://api.example.com/posts/${slug}`).then((res) =>
res.json()
);
return {
title: `${post.title} | Engineering Blog`,
description: post.excerpt,
openGraph: {
title: post.title,
images: [post.coverImage],
},
};
}
export default async function BlogPostPage({ params }: Props) {
const { slug } = await params;
return <article className="p-6">Reading: {slug}</article>;
}
app/sitemap.ts)Generate an XML sitemap straight from your database or CMS by exporting a sitemap function from app/sitemap.ts.
// app/sitemap.ts
import type { MetadataRoute } from 'next';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
return [
{ url: 'https://devcloud.example.com', lastModified: new Date() },
{ url: 'https://devcloud.example.com/pricing', lastModified: new Date() },
];
}
metadataBase in app/layout.tsx: Without metadataBase: new URL('https://yoursite.com'), relative Open Graph image paths like /og.png fail to resolve cleanly.metadata from a 'use client' file: Static metadata and generateMetadata only work in Server Components.fetch() requests inside generateMetadata and page.tsx are memoized during a single render when options match.Set title: { template: '%s | Brand', default: 'Brand' } in app/layout.tsx, and child pages only need to export title: 'Pricing'.
Yes, add alternates: { canonical: '/pricing' } inside metadata or generateMetadata, and Next.js resolves it using metadataBase.
Export robots: { index: false, follow: false } in app/layout.tsx when running in staging environments.
Sign in to track your learning journey, earn industry-recognized certificates, and join our elite developer community.
Quick Access With