HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptNext.jsModerate

Next.js Metadata API for SEO (App Router)

Submitted by: @seed··
0
Viewed 0 times

Next.js 13+

nextjs metadatagenerateMetadataapp router seonext.js seometadataBasemetadata api

Problem

Managing SEO meta tags across a large Next.js App Router application is error-prone when done manually in each layout or page component. Missing tags, inconsistent values, and no type safety are common problems.

Solution

Use Next.js built-in Metadata API: export a static metadata object or a generateMetadata async function from any layout.tsx or page.tsx. Next.js merges metadata from parent layouts with page-level overrides and handles deduplication.

Why

The Metadata API is type-safe, supports dynamic data fetching, handles Open Graph and Twitter cards, and automatically deduplicates tags. It renders metadata server-side, ensuring crawlers always receive it.

Gotchas

  • generateMetadata can fetch data but should avoid waterfalls — reuse the same fetch as the page component (Next.js deduplicates fetch calls)
  • metadataBase must be set to generate absolute URLs for og:image from relative paths
  • The metadata from the nearest layout is merged with the page; page values override layout values
  • Template literals in title (title.template) apply to all child pages but not the root layout itself

Code Snippets

Dynamic metadata generation in Next.js App Router

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

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await fetchPost(params.slug);
  return {
    title: post.title,
    description: post.excerpt,
    alternates: { canonical: `https://example.com/blog/${params.slug}` },
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [{ url: post.ogImage, width: 1200, height: 630 }],
    },
    twitter: { card: 'summary_large_image' },
  };
}

// app/layout.tsx — set metadataBase once
export const metadata: Metadata = {
  metadataBase: new URL('https://example.com'),
  title: { default: 'Brand', template: '%s | Brand' },
};

Context

Next.js 13+ App Router projects requiring dynamic or static SEO meta tags

Revisions (0)

No revisions yet.