Skip to main content

Command Palette

Search for a command to run...

Next.js ~Meta data~

Updated
3 min read
Next.js ~Meta data~

Next.js(App Router) generates metadata that can be used for SEO or SNS sharing by exporting a meta object or generateMetadata functionality from layout.tsx or page.tsx.
Unlike the traditional pages directory (next/head), everything is handled securely on the server-side. We’ll explain the main configuration patterns and provide clear examples.

  1. Static Metadata: To set a fixed title or description, export the Metadata object.
// app/page.tsx or app/layout.tsx
import { Metadata } from 'next'

export const metadata: Metadata = {
  title: 'Home | My Site',
  description: "This is the site's homepage.",
  keywords: ['Next.js', 'React', 'metadata'],
  openGraph: {
    title: 'Home | My Site',
    description: "This is the site's homepage.",
    url: 'https://example.com',
    siteName: 'My Site',
    images: [
      {
        url: 'https://example.com',
        width: 1200,
        height: 630,
      },
    ],
    locale: 'ja_JP',
    type: 'website',
  },
  twitter: {
    card: 'summary_large_image',
    title: 'Home | My Site',
    description: "This is the site's homepage.",
    images: ['https://example.com'],
  },
}

export default function Page() {
  return <h1>Hello!</h1>
}

2. Dynamic Metadata: If you wish to modify metadata based on URL parameters (params) or data from external APIs—for example, on blog post pages—use the generateMetadata function.

// app/posts/[id]/page.tsx
import { Metadata } from 'next'

type Props = {
  params: Promise<{ id: string }>
}

// Data retrieval function (as Next.js automatically memoises this, calling it again on the page will not affect performance)
async function getPost(id: string) {
  const res = await fetch(`https://example.com{id}`)
  return res.json()
}

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

  return {
    title: `${post.title} | マイサイト`,
    description: post.summary,
    openGraph: {
      title: post.title,
      description: post.summary,
      images: [post.coverImage],
    },
  }
}

export default async function Page({ params }: Props) {
  const id = (await params).id
  const post = await getPost(id)
  
  return <article><h1>{post.title}</h1></article>
}

3.By defining a template in the root layout.tsx file using the title template feature (title.template), you can partially replace the title on subpages.


// app/layout.tsx (root layout)
export const metadata: Metadata = {
  title: {
    template: '%s | MySite',
    default: 'MySite - Official Home', // Default used when a child page has no title
  },
}
// app/about/page.tsx (Company overview page)
export const metadata: Metadata = {
  title: 'Company Overview', // In the browser this will appear as "Company Overview | MySite"
}

4. File based meta data

Instead of writing the code yourself, simply place the files in a specific folder within the app directory, and Next.js will automatically recognise and generate the meta tags for you.

  • Icons: favicon.ico(root directory only)、icon.pngapple-icon.png

  • Social media sharing images: opengraph-image.pngtwitter-image.png

  • For search engine crawlers: robots.txtsitemap.xml

💡 Note (Important) Exporting metadata via code (metadata / generateMetadata) is supported only in server components. Since it cannot be exported from client component files that declare “use client,” please define it in the parent layout or page (on the server side) in such cases.