Metadata and SEO
metadata, generateMetadata, Open Graph, sitemap and robots.
Updated
What metadata is
Metadata is information about the page, in <head>: the title in the tab, the description in Google, the image that shows up when you share a link. It isn't visible on the page, but it decides how the site looks in search results and on social networks.
SEO (Search Engine Optimization) = everything you do so that search engines understand and display your pages well.
Kinds of metadata
| Kind | Where it shows | The field in Next |
|---|---|---|
| title | the tab, the Google result | title |
| description | under the title in Google | description |
| Open Graph | the preview when sharing (Facebook, LinkedIn, Slack) | openGraph |
| canonical | which URL is the "original" (avoids duplicate content) | alternates.canonical |
| robots | index / don't index | robots |
| icon | the tab's icon | the icon.png file |
Static metadata
// app/layout.tsx
export const metadata: Metadata = {
title: { default: 'learn.js', template: '%s · learn.js' }, // children: "Functions · learn.js"
description: 'Short lessons on HTML, JS and Next.js.',
metadataBase: new URL('https://learn-js.vercel.app'), // for absolute URLs in OG
}Dynamic metadata
For pages that depend on data:
export async function generateMetadata({ params }: PageProps<'/blog/[slug]'>): Promise<Metadata> {
const post = await getPost((await params).slug) // the same cached function as in the page
return {
title: post.title,
description: post.excerpt,
openGraph: { title: post.title, images: [post.cover] },
alternates: { canonical: `/blog/${post.slug}` },
}
}Special metadata files
| File | Generates |
|---|---|
app/sitemap.ts |
/sitemap.xml — the list of every page, for the crawler |
app/robots.ts |
/robots.txt — what the crawler may index |
opengraph-image.tsx |
an OG image generated with ImageResponse |
icon.png, favicon.ico, apple-icon.png |
icons |
// app/sitemap.ts
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts()
return posts.map(p => ({ url: `https://site.com/blog/${p.slug}`, lastModified: p.updatedAt }))
}SEO — what really matters
The full topic — how Google works, technical SEO, keywords, Analytics, audits — is in SEO.
| Factor | How you handle it |
|---|---|
| content rendered on the server | Server Components — the crawler sees complete HTML |
| structure | semantic HTML, one <h1>, the right lang |
| a unique title + description on every page | generateMetadata |
| speed (Core Web Vitals) | next/image, next/font, little JS — see How the browser renders |
| rich results (stars, prices) | JSON-LD |
| clean, stable URLs | /blog/article-title, not ?id=123 |
Summary
- Metadata = the title, description, OG, canonical — in
<head>, invisible on the page. - Static
metadataorgenerateMetadatafrom data;sitemap.ts,robots.ts. - SEO = content on the server + semantic HTML + unique metadata + speed.