A Complete Guide to Using metadata and generateMetadata in Next.js

In modern versions of Next.js, managing page metadata is more powerful and intuitive than ever. Metadata is automatically injected into the <head> of your pages and plays a vital role in SEO, social sharing, and user experience. This guide explains the two main ways to define metadata: using the static metadata object and the dynamic generateMetadata function.

metadatagenerateMetadataSEOOpen Graph

~3 min read • Updated Nov 1, 2025

1. Static Metadata with metadata


If your page metadata is static and doesn’t rely on runtime data, you can define it directly in layout.tsx or page.tsx:

export const metadata: Metadata = {
  title: 'Home Page',
  description: 'A brief description of this page',
}

Next.js will automatically render this metadata in the <head> of your page.


2. Dynamic Metadata with generateMetadata


If your metadata depends on route parameters, external APIs, or parent metadata, use the generateMetadata function:

export async function generateMetadata({ params }, parent) {
  const product = await fetch(`https://example.com/api/products/${params.id}`).then(res => res.json())
  const previousImages = (await parent).openGraph?.images || []

  return {
    title: product.title,
    openGraph: {
      images: ['/product-image.jpg', ...previousImages],
    },
  }
}

3. Good to Know


  • You can only export either metadata or generateMetadata from a route segment — not both
  • generateMetadata is only supported in Server Components
  • fetch calls inside generateMetadata are automatically memoized
  • If your metadata doesn’t rely on runtime data, prefer using the static metadata object

4. Supported Metadata Fields


  • title: Page title
  • description: Meta description for search engines
  • openGraph: Social sharing metadata
  • twitter: Twitter Card settings
  • robots: Indexing rules
  • icons: Favicon and Apple Touch icons
  • manifest: Path to manifest.json
  • verification: Site verification for Google, Yahoo, Yandex
  • appLinks: Deep linking for mobile apps
  • alternates: Canonical URLs, language variants, RSS feeds

5. Using metadataBase


To define a base URL for relative metadata fields like Open Graph images or canonical links:

export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
  openGraph: {
    images: '/og-image.png', // becomes https://example.com/og-image.png
  },
}

6. Combined Example


export const metadata: Metadata = {
  title: {
    default: 'My Shop',
    template: '%s | My Shop',
  },
  description: 'Best products at the best prices',
  openGraph: {
    title: 'My Shop',
    description: 'Shop online with high quality',
    url: 'https://example.com',
    siteName: 'My Shop',
    images: [
      {
        url: 'https://example.com/og.png',
        width: 1200,
        height: 630,
      },
    ],
    type: 'website',
  },
  twitter: {
    card: 'summary_large_image',
    title: 'My Shop',
    description: 'Shop online with high quality',
    creator: '@myshop',
    images: ['https://example.com/og.png'],
  },
}

Summary


  • Use metadata for static metadata
  • Use generateMetadata for dynamic metadata based on route or external data
  • Metadata is automatically injected into <head> — no need for next/head
  • Use metadataBase to simplify absolute URLs

Written & researched by Dr. Shahin Siami