Metadata API & SEO in App Router
Export static and dynamic metadata objects to set page titles, descriptions, and OG tags.
Metadata API & SEO in App Router is a free React Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Metadata Matters
Good metadata (title, description, OG tags) improves SEO rankings and social share previews. Next.js App Router provides a type-safe Metadata API that generates <head> tags server-side.
Static Metadata Export
Export a metadata object from any page.tsx or layout.tsx to set static tags for that segment.
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'My App',
description: 'The best app ever built',
keywords: ['react', 'nextjs', 'typescript'],
};
export default function Page() { return <main>Hello</main>; }Title Templates
Use title.template in a layout so child pages automatically get a formatted title without repeating the site name.
// app/layout.tsx
export const metadata: Metadata = {
title: {
template: '%s | My App',
default: 'My App',
},
};
// app/about/page.tsx
export const metadata: Metadata = {
title: 'About', // renders as "About | My App"
};Dynamic Metadata with generateMetadata
Export an async generateMetadata function for routes that need data-driven tags — it receives params and the parent metadata.
export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
const product = await getProduct(params.id);
return {
title: product.name,
description: product.summary,
openGraph: {
title: product.name,
images: [product.imageUrl],
},
};
}Open Graph Tags
The openGraph key sets OG tags for social sharing on Facebook, LinkedIn, and Slack.
export const metadata: Metadata = {
openGraph: {
title: 'My Product',
description: 'Buy now!',
url: 'https://example.com/product',
siteName: 'My App',
images: [{ url: 'https://example.com/og.png', width: 1200, height: 630 }],
type: 'website',
locale: 'en_US',
},
};Twitter Card Tags
The twitter key sets Twitter-specific card metadata for rich previews in tweets.
twitter: {
card: 'summary_large_image',
title: 'My Product',
description: 'Buy now!',
images: ['https://example.com/twitter.png'],
creator: '@myhandle',
},Robots and Canonical
Control crawling with robots and set canonical URLs to prevent duplicate content penalties.
export const metadata: Metadata = {
robots: { index: true, follow: true, googleBot: { index: true } },
alternates: { canonical: 'https://example.com/products' },
};Favicons and Icons
Place icon files in app/ with reserved names (icon.png, apple-icon.png, favicon.ico) or declare them in metadata.icons.
// Convention: place app/icon.png → auto-detected as favicon
// Or declare explicitly:
export const metadata: Metadata = {
icons: {
icon: '/icon.png',
apple: '/apple-icon.png',
shortcut: '/shortcut-icon.png',
},
};Generating OG Images with ImageResponse
Use ImageResponse from next/og in a route.ts to generate dynamic OG images with JSX rendered to PNG.
// app/og/route.ts
import { ImageResponse } from 'next/og';
export async function GET(req: Request) {
const { searchParams } = new URL(req.url);
const title = searchParams.get('title') ?? 'Default';
return new ImageResponse(
<div style={{ fontSize: 48, background: '#fff', width: '100%', height: '100%' }}>
{title}
</div>,
{ width: 1200, height: 630 }
);
}Structured Data (JSON-LD)
Add JSON-LD structured data by injecting a <script> tag in the page's JSX — this is not part of the Metadata API but works alongside it.
export default function ProductPage({ product }) {
const jsonLd = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
price: product.price,
};
return (
<>
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
<h1>{product.name}</h1>
</>
);
}Verifying Metadata
Use browser DevTools (Network tab, view HTML source) or tools like opengraph.xyz to verify your metadata renders correctly in the server HTML.
Quick Check
Which Next.js Metadata API feature lets child pages inherit and customize a shared title suffix like 'About | My App'?
Recap
Export metadata for static tags or generateMetadata() for dynamic ones. Use title.template in layouts for DRY titles, set openGraph and twitter for social previews, and use ImageResponse in a route handler to serve dynamic OG images.
Frequently asked questions
Is the “Metadata API & SEO in App Router” lesson free?
Yes — the full text of “Metadata API & SEO in App Router” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Metadata API & SEO in App Router”?
Export static and dynamic metadata objects to set page titles, descriptions, and OG tags. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Metadata API & SEO in App Router” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- App Router File Conventions
- Server vs Client Components in Next.js
- Dynamic Routes & Route Groups
- Metadata API & SEO in App Router