How do you handle SEO metadata in Next.js?
Take a moment.
Say your answer out loud or write it down first — retrieval is what makes it stick. Reveal when you're ready.
Short answer
App Router uses static metadata exports or generateMetadata functions per route — title, description, openGraph, canonical, robots. Pages Router used <Head> component per page. Dynamic routes generate metadata from fetched data.
Detailed explanation
Metadata determines how pages appear in search results and social cards. In the App Router you export a metadata object for static values, or generateMetadata({ params }) for dynamic ones — fetch the same data the page uses, return title/description/openGraph images. The framework deduplicates tags, resolves relative canonical URLs against your site config, and streams meta into HTML head. Layouts provide defaults (title.template composes '%s · Site Name'); pages override. For special cases: sitemap.ts generates sitemaps programmatically, robots.ts emits rules, opengraph-image.tsx renders OG images dynamically with edge-ready templating, jsonLd goes in script tags manually. Pages Router equivalents were next/head with manual tags. Interview angle: mention title templates, canonical handling on paginated/duplicate content, and structured data — these separate checklist-followers from practitioners.
Example
// app/products/[slug]/page.tsx
export async function generateMetadata({ params }) {
const product = await getProduct(params.slug);
return {
title: `${product.name} — Specs & Reviews`,
description: product.excerpt,
alternates: { canonical: `/products/${product.slug}` },
openGraph: {
title: product.name,
images: [product.image],
type: 'website',
},
};
}Interview tip
Show generateMetadata pulling real data, then name the extras (sitemap.ts, robots.ts, OG image generation) — breadth here is cheap to demonstrate and memorable.
Common mistakes
- Duplicating titles manually instead of using title.template.
- Forgetting canonical URLs on filtered/paginated listings.