In the Next.js App Router, the Metadata API provides a structured way to define title, description, canonical URLs, Open Graph data and Twitter card metadata. Prefer this over manually appending tags in client-side effects: social crawlers generally need metadata in the HTML response they fetch.
1. Set a metadata base URL
Define metadataBase in the root layout so relative metadata image paths can be resolved consistently. Use the production origin, not localhost, and ensure each route has an appropriate canonical URL.
import type { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://example.com'),
title: { default: 'My Site', template: '%s | My Site' },
description: 'A concise description of the website.',
openGraph: {
siteName: 'My Site',
type: 'website',
images: [{
url: '/og/default.jpg',
width: 1200,
height: 630,
alt: 'My Site — default share image',
}],
},
twitter: { card: 'summary_large_image' },
};2. Define metadata for each page
A global default is useful, but the metadata should reflect the individual page. For a blog article, set its title, description, canonical path, Open Graph type and article image in the route's metadata export or generateMetadata function.
import type { Metadata } from 'next';
export async function generateMetadata({
params,
}: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post.title,
description: post.excerpt,
alternates: { canonical: `/blog/${slug}/` },
openGraph: {
title: post.title,
description: post.excerpt,
url: `/blog/${slug}/`,
type: 'article',
images: [{ url: post.ogImage, width: 1200, height: 630, alt: post.imageAlt }],
},
twitter: { card: 'summary_large_image' },
};
}3. Generate dynamic Open Graph images when useful
Next.js supports file-based metadata routes such as opengraph-image.tsx. This can generate a consistent image for each route using the page title and brand system. Keep rendering fast, avoid embedding sensitive information and test the final image URL from a public network.
4. Verify the HTML that production serves
After deployment, open View Page Source and check that the expected tags are present. Then run a URL inspection and compare title, description, canonical URL, og:image and twitter:card. A successful TypeScript build alone does not prove the crawler-facing HTML is correct.
After deploying your Next.js route, inspect the live HTML and preview its social cards.
Open the free tool →