Next.js Metadata API: Complete SEO Guide to Titles, Descriptions and Open Graph

Next.js Metadata API SEO Guide

Why Next.js Metadata API Matters in a Website

Imagine that you have just published a useful article on your website.

The article itself looks perfect. The URL is clean, the content answers the user’s question, and the page loads correctly.

But when someone searches for it, the search result shows a poor title and an incomplete description.

Then someone shares the page on social media and the preview displays the wrong image.

This is where metadata becomes important.

Metadata provides information about a webpage to browsers, search engines, and other platforms. In a Next.js application using the App Router, the Next.js Metadata API provides a structured way to define this information without manually constructing <head> elements for every page.

Next.js can generate the appropriate HTML metadata from a static metadata object, a dynamic generateMetadata function, or special metadata files.

For an Next.js SEO beginner, the important idea is simple:

Your visible page content tells visitors what the page is about. Metadata helps software understand and present that page.

What Is the Next.js Metadata API?

The Next.js Metadata API is a collection of features for defining metadata in applications using the App Router.

Instead of manually writing HTML such as:

<title>Next.js SEO Guide</title>

<meta name=”description” content=”Learn Next.js SEO…” />

you can define metadata in your Next.js files:

import type { Metadata } from ‘next’

 

export const metadata: Metadata = {

title: ‘Next.js SEO Guide’,

description: ‘Learn how to optimize a Next.js website for search engines.’,

}

Next.js then generates the appropriate <head> elements for the page.

The API supports many metadata fields, including:

  • title
  • description
  • keywords
  • authors
  • creator
  • publisher
  • robots
  • alternates
  • openGraph
  • twitter
  • icons
  • manifest

It also works with special file conventions for items such as favicons, Open Graph images, robots.txt, and sitemaps.

Metadata API vs. next/head

If you have worked with older versions of Next.js, you may remember:

import Head from ‘next/head’

This approach is associated with the Pages Router.

The App Router introduced the Metadata API, including the metadata object and generateMetadata. Next.js documentation still provides Pages Router guidance, but for a new App Router project, the Metadata API is the relevant approach.

So, if you are building a modern App Router application, think in terms of:

export const metadata: Metadata = {}

or:

export async function generateMetadata() {}

rather than manually adding <Head> elements.

How to Add Static Metadata in Next.js

Static metadata is the easiest place to start.

Suppose you have:

app/

about/

page.tsx

You can add:

import type { Metadata } from ‘next’

 

export const metadata: Metadata = {

title: ‘About Our Company’,

description: ‘Learn more about our company, products, and services.’,

}

 

export default function AboutPage() {

return (

<main>

<h1>About Our Company</h1>

<p>Learn more about our company.</p>

</main>

)

}

Next.js uses the exported metadata to create the corresponding HTML metadata.

Why Next.js Metadata API is useful for SEO

You can give every important page a meaningful:

  • title
  • description
  • canonical URL
  • robots configuration
  • social sharing information

This is much easier to maintain than manually constructing metadata in every component.

Configure Metadata in the Root Layout

A good Next.js SEO setup normally starts at the root layout.

For example:

import type { Metadata } from ‘next’

export const metadata: Metadata = {

title: {

default: ‘Example Website’,

template: ‘%s | Example Website’,

},

description: ‘Practical guides, tutorials, and resources for web developers.’,

metadataBase: new URL(‘https://example.com’),

}

export default function RootLayout({

children,

}: {

children: React.ReactNode

}) {

return (

<html lang=”en”>

<body>{children}</body>

</html>

)

}

The title.template option is particularly useful.

If a child page contains:

export const metadata: Metadata = {

title: ‘Next.js SEO Guide’,

}

the resulting title can use the root template:

Next.js SEO Guide | Example Website

Next.js metadata is evaluated through the route hierarchy, and metadata from child segments can override corresponding parent values.

Understanding title, default, and template

Titles are one of the most important pieces of SEO metadata because they help users and search engines understand the page.

A simple title is:

export const metadata: Metadata = {

title: ‘Next.js Metadata API’,

}

You can also define a default:

export const metadata: Metadata = {

title: {

default: ‘Example Website’,

},

}

And a template:

export const metadata: Metadata = {

title: {

default: ‘Example Website’,

template: ‘%s | Example Website’,

},

}

SEO tip

Write titles for humans first.

A useful title might be:

Next.js Metadata API: Complete SEO Guide

A poor approach would be repeatedly inserting the same keyword:

Next.js Metadata API | Next.js Metadata | Next.js SEO | Next.js Metadata API Guide

Natural language is easier to read and avoids unnecessary keyword repetition.

Google also explains that search-result title links can be generated from several sources, so the <title> element is important but does not guarantee that Google will display exactly the same text.

How to Add a Meta Description

The description can be configured with:

export const metadata: Metadata = {

title: ‘Next.js Metadata API’,

description:

‘Learn how to configure SEO metadata, Open Graph data, canonical URLs, and dynamic metadata in Next.js.’,

}

The resulting HTML contains a description meta tag.

What makes a good description?

A useful description should:

  1. Explain what the page offers.
  2. Match the page’s actual content.
  3. Be easy to understand.
  4. Give the searcher a reason to continue.
  5. Avoid unnecessary keyword repetition.

Do not treat the meta description as a list of keywords.

Also remember that a meta description does not guarantee the exact snippet Google will display. Google may generate or modify search-result snippets based on the query and page content. Next.js’s SEO documentation similarly describes the description as useful for search-result presentation and click-through rather than as a direct ranking factor.

Using metadataBase for Absolute URLs

When your metadata contains URLs, an absolute base URL is often useful.

For example:

export const metadata: Metadata = {

metadataBase: new URL(‘https://example.com’),

}

You can then use relative URLs in supported metadata fields.

For example:

export const metadata: Metadata = {

metadataBase: new URL(‘https://example.com’),

alternates: {

canonical: ‘/nextjs-metadata-api’,

},

}

The resulting canonical URL can resolve against the metadata base.

Why beginners should care

Without a consistent URL strategy, it is easy to accidentally create:

  • incorrect canonical URLs
  • incorrect Open Graph URLs
  • inconsistent domain references
  • development URLs appearing in production metadata

Always check the generated HTML after deploying your site.

How to Set a Canonical URL in Next.js

Canonical URLs tell search engines which URL you consider the preferred version of a page.

A simple example is:

import type { Metadata } from ‘next’

export const metadata: Metadata = {

alternates: {

canonical: ‘/nextjs-metadata-api’,

},

}

With:

metadataBase: new URL(‘https://example.com’)

the canonical can resolve to:

https://example.com/nextjs-metadata-api

Canonicalization is particularly useful when similar URLs can exist because of parameters, alternate paths, or other URL variations.

However, a canonical is a signal, not an absolute command. Next.js documentation distinguishes canonical URLs from directives such as robots rules.

Open Graph Metadata for Social Sharing

SEO is not limited to search results.

Suppose someone shares your article on a social platform.

Instead of a plain URL, you want the shared link to contain:

  • a useful title
  • a description
  • an appropriate image
  • the correct URL

Next.js supports Open Graph metadata.

For example:

export const metadata: Metadata = {

title: ‘Next.js Metadata API’,

description: ‘A practical guide to SEO metadata in Next.js.’,

openGraph: {

title: ‘Next.js Metadata API’,

description: ‘A practical guide to SEO metadata in Next.js.’,

url: ‘https://example.com/nextjs-metadata-api’,

siteName: ‘Example Website’,

images: [

{

url: ‘/images/nextjs-metadata-api.jpg’,

width: 1200,

height: 630,

alt: ‘Next.js Metadata API SEO Guide’,

},

],

locale: ‘en_US’,

type: ‘article’,

},

}

Open Graph metadata can improve how a URL is represented when shared. It should not be confused with a direct Google ranking signal. Next.js’s SEO documentation describes Open Graph as useful for shareability and presentation rather than direct search rankings.

File-Based Metadata in Next.js

One of the useful features of the modern Metadata API is that some metadata can be represented using special files.

Next.js supports conventions for files such as:

favicon.ico

icon.png

apple-icon.png

opengraph-image.jpg

twitter-image.jpg

robots.txt

sitemap.xml

These files can automatically contribute the appropriate metadata or routes.

The current Next.js SEO documentation describes both static and dynamic variants of these metadata file conventions.

For example, you can use:

app/

opengraph-image.jpg

page.tsx

for an Open Graph image associated with that route.

This can sometimes be simpler than maintaining a large openGraph.images configuration manually.

Dynamic Metadata with generateMetadata

Static metadata is excellent when every page has predictable information.

But consider a blog.

You might have:

/blog/nextjs-metadata-api

/blog/nextjs-image-optimization

/blog/nextjs-routing-guide

Each article needs its own title and description.

Writing a separate static metadata object for thousands of pages would not be practical.

This is where generateMetadata becomes useful.

The current Next.js API allows metadata to be generated dynamically using route parameters, external data, and parent metadata.

Example:

import type { Metadata } from ‘next’

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,

description: post.description,

}

}

export default async function BlogPost({

params,

}: Props) {

const { slug } = await params

const post = await getPost(slug)

return (

<article>

<h1>{post.title}</h1>

<p>{post.content}</p>

</article>

)

}

The important part is that metadata now comes from the same underlying content as the page.

When Should You Use metadata vs generateMetadata?

A simple rule helps.

Use metadata when:

  • the metadata is static
  • the page has a fixed title
  • the description does not change
  • the route does not require database content

Example:

export const metadata: Metadata = {

title: ‘About Us’,

description: ‘Learn about our company.’,

}

Use generateMetadata when:

  • the page is dynamic
  • metadata comes from a CMS
  • the route contains a slug or ID
  • product information determines the title
  • blog content determines the description

Example:

export async function generateMetadata({ params }): Promise<Metadata> {

const product = await getProduct(params.id)

return {

title: product.name,

description: product.summary,

}

}

Next.js specifically recommends the static metadata object when the metadata does not depend on dynamic information.

Creating Dynamic Open Graph Images

Dynamic content can also have dynamic social images.

Next.js supports special Open Graph image files and programmatic image generation. The Metadata API documentation notes that the file-based approach can be convenient for Open Graph images, while dynamic image generation can be handled using the relevant Next.js image APIs.

For example, a blog could generate an image containing:

Next.js Metadata API

Complete SEO Guide

instead of using the same image for every article.

This can make shared links more recognizable.

Adding Robots Metadata

Sometimes you do not want a page indexed.

For example, you might have:

  • private pages
  • internal search results
  • temporary pages
  • certain filtered URLs
  • account-related pages

Next.js allows robots directives through metadata.

For example:

export const metadata: Metadata = {

robots: {

index: false,

follow: false,

},

}

This corresponds conceptually to:

<meta name=”robots” content=”noindex,nofollow”>

Next.js’s documentation explains that noindex is different from simply preventing crawling with robots.txt. If the goal is to keep a page out of search results, noindex is the relevant indexing directive.

Important SEO warning

Do not accidentally place noindex on important pages.

A small metadata mistake can have a much bigger SEO consequence than a missing keyword.

Robots.txt Is Different from Robots Metadata

These two concepts are easy to confuse.

Robots metadata

Controls indexing or crawling behavior for a page.

Example:

robots: {

index: false,

}

robots.txt

Provides crawler instructions at the site level.

Next.js supports a special robots.txt file convention, allowing you to create a route such as:

app/robots.ts

or use the appropriate file-based convention.

Next.js documentation describes robots.txt as a way to control which resources crawlers can request, while noindex is used when you need an indexing directive.

Next.js Metadata API and SEO Keywords

The Next.js Metadata API supports a keywords field:

export const metadata: Metadata = {

keywords: [‘Next.js’, ‘SEO’, ‘Metadata API’],

}

However, do not assume that adding dozens of keywords will improve rankings.

Modern SEO should focus primarily on:

  • useful content
  • search intent
  • clear page titles
  • descriptive content
  • crawlability
  • indexability
  • internal linking
  • good user experience
  • appropriate structured data
  • technically sound URLs

The metadata API is a tool for communicating information about your page. It is not a shortcut around content quality.

Metadata and Structured Data Are Not the Same Thing

This distinction is important.

Metadata

Metadata includes information such as:

title

description

robots

canonical

openGraph

twitter

Structured data

Structured data describes entities and content in a standardized format, commonly using Schema.org vocabulary and JSON-LD.

For example, an article could contain JSON-LD describing:

  • headline
  • author
  • publication date
  • modification date
  • image

Google explains that structured data can help it understand page content and can support eligibility for certain search features when the relevant requirements are met.

So a complete Next.js SEO implementation may use both metadata and structured data.

Adding JSON-LD in a Next.js Application

A simplified JSON-LD example could look like:

const jsonLd = {

‘@context’: ‘https://schema.org’,

‘@type’: ‘Article’,

headline: ‘Next.js Metadata API: Complete SEO Guide’,

author: {

‘@type’: ‘Person’,

name: ‘Example Author’,

},

}

export default function Page() {

return (

<>

<script

type=”application/ld+json”

dangerouslySetInnerHTML={{

__html: JSON.stringify(jsonLd),

}}

/>

<article>

<h1>Next.js Metadata API: Complete SEO Guide</h1>

</article>

</>

)

}

Only add structured data that accurately represents the visible page content and follows Google’s guidelines.

Google recommends testing structured data and checking the rendered page with its available tools before relying on the implementation.

Metadata for Blog Posts: A Practical Pattern

Suppose you operate a technology blog.

Each article might have:

title

description

slug

author

published date

updated date

featured image

category

Your CMS could store those fields.

Then generateMetadata can turn them into page metadata:

export async function generateMetadata({ params }): Promise<Metadata> {

const post = await getPost(params.slug)

 

return {

title: post.title,

description: post.description,

 

alternates: {

canonical: `/blog/${post.slug}`,

},

 

openGraph: {

title: post.title,

description: post.description,

type: ‘article’,

images: [

{

url: post.image,

alt: post.title,

},

],

},

}

}

This creates a repeatable SEO system.

Instead of remembering to edit the HTML <head> every time an article is published, your application can generate metadata from the article record.

Metadata Inheritance and Merging

One powerful feature of the Next.js Metadata API is hierarchical metadata.

Imagine this structure:

app/

layout.tsx

blog/

layout.tsx

[slug]/

page.tsx

The root layout can define site-wide metadata.

The blog layout can define blog-specific metadata.

The article page can define article-specific metadata.

Next.js evaluates metadata through the route hierarchy and merges the resulting metadata. Child segments can replace values from parent segments.

Be careful with nested metadata

Metadata merging is not simply “everything gets combined.”

For some nested objects, a child definition can overwrite the parent value.

This is particularly important with objects such as:

openGraph

robots

The current documentation specifically describes metadata merging as shallow and notes that duplicate keys are replaced according to route ordering.

Common Next.js Metadata API Mistakes

  1. Using generateMetadata unnecessarily

If your metadata is static, don’t make the application fetch data just to return a fixed title.

Use:

export const metadata: Metadata = {

title: ‘About Us’,

}

instead.

  1. Exporting metadata from a Client Component

The metadata object and generateMetadata are supported in Server Components.

Therefore, this pattern can cause problems:

‘use client’

 

export const metadata: Metadata = {

title: ‘Example’,

}

Instead, keep the route page or layout as a Server Component and move interactive functionality into a separate Client Component.

  1. Defining both metadata and generateMetadata

You cannot export both from the same route segment.

Choose the appropriate approach.

  1. Forgetting metadataBase

If you use relative URLs for metadata such as canonical URLs or social images, make sure your application’s URL configuration is appropriate.

For example:

metadataBase: new URL(‘https://example.com’)

  1. Using the same title on every page

A website where every page says:

My Website

misses an opportunity to clearly communicate page-specific topics.

Use meaningful page titles.

  1. Accidentally using noindex

Always inspect your robots configuration before publishing.

A page containing:

robots: {

index: false,

}

is deliberately asking search engines not to index it.

  1. Assuming metadata guarantees rankings

Metadata helps search engines and other systems understand and present your pages, but it cannot guarantee a ranking position.

Search visibility depends on many factors beyond metadata.

How to Test Next.js Metadata

After implementing the Next.js Metadata API, do not simply assume it worked.

Open the published page.

Then inspect the HTML using your browser’s developer tools.

Look for:

<title>…</title>

and:

<meta name=”description” …>

Also check relevant elements such as:

canonical

robots

og:title

og:description

og:image

twitter:card

Next.js automatically generates the relevant head elements, and its documentation specifically recommends inspecting the generated output in browser developer tools.

For structured data, use Google’s structured-data testing and validation resources where appropriate.

Next.js Metadata API SEO Checklist

Before publishing a page, run through this checklist.

Basic SEO

  • Does the page have a meaningful title?
  • Is the description relevant to the actual page?
  • Is the H1 consistent with the page topic?
  • Is the URL clean and understandable?

Technical SEO

  • Is the canonical URL correct?
  • Is the page accidentally marked noindex?
  • Can search engines crawl the page?
  • Is the production domain being used?

Social sharing

  • Is the Open Graph title useful?
  • Is the Open Graph description accurate?
  • Is the social image appropriate?
  • Are image URLs valid?

Dynamic pages

  • Does generateMetadata retrieve the correct record?
  • Does every important dynamic URL receive unique metadata?
  • Does the metadata handle missing content correctly?

Structured data

  • Is structured data appropriate for the page?
  • Does it accurately represent visible content?
  • Has it been validated?

Don’t Forget Sitemaps and Internal Links

The Next.js Metadata API is only one part of technical SEO.

A page also needs to be discoverable.

Next.js supports sitemap conventions, including dynamic sitemap generation for applications with changing content.

For a content website, your overall SEO system could therefore look like:

Page Content

↓

Metadata API

↓

Canonical + Robots + Open Graph

↓

Structured Data

↓

Internal Links

↓

XML Sitemap

↓

Search Engine Discovery

No individual element replaces the others.

A Simple SEO-Friendly Next.js Metadata Example

Here is a practical starting point:

import type { Metadata } from ‘next’

 

export const metadata: Metadata = {

metadataBase: new URL(‘https://example.com’),

 

title: {

default: ‘Example Website’,

template: ‘%s | Example Website’,

},

 

description:

‘Practical web development tutorials, guides, and resources.’,

 

alternates: {

canonical: ‘/’,

},

 

openGraph: {

title: ‘Example Website’,

description:

‘Practical web development tutorials, guides, and resources.’,

url: ‘https://example.com’,

siteName: ‘Example Website’,

images: [

{

url: ‘/og-image.jpg’,

width: 1200,

height: 630,

alt: ‘Example Website’,

},

],

locale: ‘en_US’,

type: ‘website’,

},

 

robots: {

index: true,

follow: true,

},

}

This is a starting point rather than a universal template.

Your actual metadata should describe your website and its content accurately.

Key Takeaways

  1. The Next.js Metadata API provides a structured way to manage SEO and sharing metadata in App Router applications.
  2. Use the static metadata object when metadata is predictable and does not require dynamic information.
  3. Use generateMetadata when titles, descriptions, images, or other metadata depend on route parameters or external data.
  4. Use canonical URLs, robots directives, Open Graph data, and other fields according to the actual needs of each page.
  5. Special metadata files can simplify favicons, social images, robots.txt, and sitemap implementation.
  6. Metadata is only one part of SEO; content quality, crawlability, internal linking, structured data, and technical performance also matter.
  7. Always inspect the generated HTML and validate important SEO elements after implementation.

FAQ

  1. What is the Next.js Metadata API?

The Next.js Metadata API is a set of App Router features for defining webpage metadata such as titles, descriptions, canonical URLs, robots directives, Open Graph information, and other <head> elements.

  1. What is the difference between metadata and generateMetadata?

The metadata object is generally used for static metadata. generateMetadata is used when metadata needs to be generated dynamically from route parameters, external data, or parent metadata.

  1. Can I use the Metadata API inside a Client Component?

The metadata export and generateMetadata are supported in Server Components. If your page needs client-side interactivity, keep the page or layout as a Server Component and move the interactive portion into a separate Client Component.

  1. Does the Next.js Metadata API improve Google rankings?

The API helps you provide useful information such as titles, descriptions, canonical URLs, and other metadata, but it does not guarantee higher rankings. Search engines evaluate many aspects of a webpage and website.

  1. Can Next.js generate Open Graph images?

Yes. Next.js provides metadata file conventions for Open Graph and Twitter images and also supports programmatic image generation for dynamic use cases.

Conclusion

The Next.js Metadata API turns SEO metadata from a collection of manually written <head> tags into a structured part of your application.

For a beginner, the best approach is to start small.

Set a useful title and description in your root layout. Give important pages their own titles. Add canonical URLs where appropriate. Configure Open Graph information for pages that are likely to be shared. When your website becomes dynamic, use generateMetadata to create metadata from the same content that powers the page.

Then go one step further.

Check your robots directives, sitemap, structured data, internal links, and generated HTML. These pieces work together to create a technically sound SEO foundation.

The goal is not to fill every metadata field.

The goal is to give search engines, browsers, and social platforms accurate, useful information about each page.

That is where the Next.js Metadata API becomes genuinely valuable: it lets your application manage that information systematically as your website grows.

Leave a Comment

Your email address will not be published. Required fields are marked *