Script Valley
Next.js: Full-Stack React Applications
Performance, Optimization, and DeploymentLesson 6.3

How to add metadata and Open Graph tags in Next.js

Metadata API, static metadata export, generateMetadata function, Open Graph, Twitter cards, canonical URLs, dynamic metadata, template strings

Static Metadata Export

Export a metadata object from any page.tsx or layout.tsx to set that route's meta tags. No more manually writing <head> tags.

// app/layout.tsx
import type { Metadata } from 'next'

export const metadata: Metadata = {
  title: {
    template: '%s | My App',  // %s is replaced by child page titles
    default: 'My App',
  },
  description: 'A Next.js application',
  openGraph: {
    siteName: 'My App',
    locale: 'en_US',
    type: 'website',
  },
}

Dynamic Metadata with generateMetadata

// app/blog/[slug]/page.tsx
import type { Metadata } from 'next'

export async function generateMetadata(
  { params }: { params: { slug: string } }
): Promise<Metadata> {
  const post = await getPost(params.slug)

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [{ url: post.coverImage, width: 1200, height: 630 }],
    },
  }
}

Next.js deduplicates the fetch in generateMetadata and the page component if they request the same URL — the data is fetched once. The title template in the root layout applies to all child pages: a page with title: 'About' renders as About | My App.

Up next

How Next.js caching works and how to control it

Sign in to track progress