Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

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

FileWhat it gives
app/favicon.icoThe tab icon
app/opengraph-image.pngA preview image for social networks
app/robots.tsThe /robots.txt file
app/sitemap.tsThe /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.

Thanks for reading!

Donate to the site — we work hard for you.