Next.js Curriculum
MediumMetadata & SEO100% Free25 min read

Static vs Dynamic Metadata Generation

The 30-Second Interview Answer

Next.js provides two ways to define SEO tags: static metadata via the export const metadata object, and dynamic metadata via the generateMetadata async function. Metadata merges hierarchically from root layouts down to nested pages, with leaf pages overriding parent properties while inheriting un-overridden defaults.

Learning Objectives

Define static metadata with title templates and base descriptions.

Implement async generateMetadata() to fetch product or article metadata dynamically.

Explain metadata inheritance and cascading merge rules across layouts and pages.

Ensure data fetch requests in generateMetadata are deduplicated with page queries.

Prerequisites & Background Knowledge
HTML <head> metadata tagsAsync JavaScriptRoute hierarchy

Why Interviewers Care

Every production application requires dynamic SEO metadata for search engine indexing and social sharing cards.

The Challenge

Contrast static metadata with dynamic generateMetadata. Implement a product detail page that dynamically generates SEO titles, descriptions, and OpenGraph tags, and explain how Next.js handles request deduplication.

Code Architecture & Implementation

1// app/products/[slug]/page.tsx
2import { Metadata } from 'next';
3import { notFound } from 'next/navigation';
4
5interface ProductPageProps {
6 // In Next.js 15+, params is a Promise!
7 params: Promise<{ slug: string }>;
8}
9
10// Automatically called by Next.js to populate <head> tags
11export async function generateMetadata({ params }: ProductPageProps): Promise<Metadata> {
12 const { slug } = await params;
13
14 // This fetch is automatically deduplicated with the fetch inside the page component!
15 const product = await fetch(`https://api.store.com/products/${slug}`).then(res => res.json());
16
17 if (!product) {
18 return { title: 'Product Not Found' };
19 }
20
21 return {
22 title: product.name,
23 description: product.description.slice(0, 160),
24 openGraph: {
25 title: product.name,
26 description: product.description,
27 images: [{ url: product.featuredImage, width: 1200, height: 630 }],
28 },
29 alternates: {
30 canonical: `/products/${slug}`,
31 },
32 };
33}
34
35export default async function ProductDetailPage({ params }: ProductPageProps) {
36 const { slug } = await params;
37 const product = await fetch(`https://api.store.com/products/${slug}`).then(res => res.json());
38
39 if (!product) notFound();
40
41 return <div><h1>{product.name}</h1></div>;
42}

Architectural Explanation

Search crawlers expect <title>, <meta name="description">, and OpenGraph tags in the initial HTML document. generateMetadata allows you to fetch CMS data and return a strongly typed Metadata object. Thanks to Next.js request memoization, if both generateMetadata and page.tsx call fetch("https://api.store.com/products/123"), Next.js only executes one network call, caching the result in-memory for the render pass.

Common Mistakes & Anti-Patterns

Exporting both `metadata` AND `generateMetadata` from the same file, which causes a build error.

Forgetting that `generateMetadata` can only be exported from Server Components (pages or layouts), not Client Components.

Not using title templates (`%s`), leading to inconsistent branding across pages.

Interview Follow-Up Traps

The interviewer asks: "Does calling cookies() inside generateMetadata make the whole page dynamic?" Yes! Dynamic functions inside generateMetadata trigger dynamic rendering for the route.

Frequently Asked Questions

Can Client Components generate dynamic metadata?

No. Metadata is evaluated on the server before client hydration. Client Components cannot export metadata.

`metadataBase` defines the base URL (e.g. `https://example.com`) for resolving relative OpenGraph image URLs.

You can call `notFound()` or return a fallback `{ title: "Not Found" }`.