Metadata and SEO
Metadata is information about a page that is not visible in its text: the tab title (title), a description for search engines (description), a preview image for social networks. In Next.js you do not write these tags by hand; you export a metadata object from a page or layout.
Site metadata
Add the object to the root layout:
// app/layout.tsx (fragment)
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'My blog',
description: 'Posts by Anna about web development',
};Next.js adds the title and meta tags to head itself. The browser tab shows "My blog". Metadata only works in server components.
Page metadata
A page can set its own values — they override the layout's:
// app/about/page.tsx (fragment)
import type { Metadata } from 'next';
export const metadata: Metadata = {
title: 'About the blog',
};On /about the tab shows "About the blog", and the description stays from the layout.
A title template
To append the site name to every title, the layout sets a template:
// app/layout.tsx (fragment)
export const metadata: Metadata = {
title: {
default: 'My blog',
template: '%s | My blog',
},
};The page title replaces %s: /about gets "About the blog | My blog". The home page, which has no title of its own, gets default.
generateMetadata for a post
Every post has its own title from the database. For that, instead of an object you export an asynchronous generateMetadata function:
// app/posts/[slug]/page.tsx (fragment)
import type { Metadata } from 'next';
import { getPost } from '@/lib/posts';
type Props = { params: Promise<{ slug: string }> };
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { slug } = await params;
const post = await getPost(slug);
return {
title: post?.title ?? 'Post not found',
description: post?.body.slice(0, 150),
openGraph: { title: post?.title, type: 'article' },
};
}The function receives the same params as the page. The /posts/hello-nextjs tab shows "Hello, Next.js | My blog". The openGraph field sets the preview when a link is shared in social networks and messengers.
Files for search engines
| File | What it gives |
|---|---|
app/favicon.ico | The tab icon |
app/opengraph-image.png | A preview image for social networks |
app/robots.ts | The /robots.txt file |
app/sitemap.ts | The /sitemap.xml site map |
Common mistake
Exporting metadata from a file with 'use client'. Next.js fails the build: metadata can only be set in server components. If a page needs to be interactive, keep page.tsx a server component with metadata and move the interactive part into a separate component.