Metadata helps search engines index the content of a web page and helps users to find what they are looking for. Next.js 13 introduced new APIs which help developers to improve SEO in very simple ways. In this article, we are going to learn to define metadata in Next.js applications using meta files.
What is Metadata?
Metadata provides information about web pages. It is not visible to the user but works behind the scenes, embedded in HTML usually within
Some common metadata types include
- Title: Title of the webpage displayed in a browser tab.
<title>Title</title>- Description: Brief overview of webpage content.
<meta name="description" content="This is a brief description of my webpage.">- Author: Author of the webpage generally used to give credit to the author.
<meta name="author" content="Sarthak Roy">- Date: Specified when webpage was last modified.
<meta name="date" content="2024-11-05T14:30:00+02:00">- Keywords: Comma seperated keywords related to webpage that search engines to index the content.
<meta name="keywords" content="Next.js, React, GeeksforGeeks">- Favicon: Small image displayed in browser tab.
Why Metadata Matters?
- Search Engine Optimisation: Metadata helps search engines understand the content of website which helps search engines to index the website.
- Classify data: Metadata tags such as Title, Author, Publication date etc helps to classify data which make it easier for search engines to find important data especially from large websites.
- Social media integration: Metadata is essential for social media platforms because it provides important data about the content of website. Preview images are also a form of metadata that increases engagement rate.
Different ways to add Metadata in Next.js 13
Next.js 13 introduced new metadata APIs that makes it really easy and intuitive to add metadata to webpages. There are two ways to add metadata:
- Config-based: Export a static
metadata object or a dynamicgenerateMetadata function from layout.(jsx | tsx) or page.(jsx | tsx). - File-based: Next.js has special files that is used to generate meta data.
We are only going to discuss about file based method in this article.
Next.js offers special files to define metadata for webpage:
- favicon.ico, apple-icon.jpg and icon.jpg: Utilised for favicons and icons
- opengraph-image.jpg and twitter-image.jpg: Utilised for social media images.
- robot.txt: Provides instructions for search engine crowling.
- sitemap.xml: Offers informatipn about website's structure. we can programmatically generate using javascript.
- manifest.json: Used for meta data in every website extension.
Setting up Next.js project
Now its time to get started with coding. I am going to use pnpm and TypeScript for this demo but it is completely optional. Use the following command to initialise a new Next.js project in you desired directory.
pnpm create next-app@latest

Start the dev server:
pnpm devManaging Metadata in Next.js
Now we are going to use metadata files to define metadata for our websites.
Favicon
Import your desired image inside app directory and rename it to favicon.ico. This should be enough to change the favicon of the webpage.
You can also define apple-icon.(jpg | jgeg | png) and icon.(jpg | jpeg | png | svg | ico) in the same way.

Opengraph-image and twitter-image
Add an opengraph-image.(jpg|jpeg|png|gif) and twitter-image.(jpg|jpeg|png|gif) image file to any route segment.
Add (opengraph-image | twitter-image).alt.txt to display text content when image can not be loaded.
robot.txt
It is a text file that provides instructions to web crawlers, on how to crawl and index a website.
Add robot.(js | ts) in app directory. Next.js will generate robot.txt from it.
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: '/admin/',
},
sitemap: 'https://aokura.site/sitemap.xml',
}
}
Sitemap
In Next.js sitemap.(xml | js | ts) is special file that is used to generate sitemap for the web application.
We can going to generate sitemap using sitmap.(js | ts).
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: `https://my-site.com/%60,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1,
},
{
url: `https://my-site.com/updates%60,
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.6,
},
{
url: `https://my-site.com/achievements%60,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.7,
}
]
}
We can view the generated sitemap in /sitemap.xml route.

We can use
import { BASE_URL } from '@/app/lib/constants'
export async function generateSitemaps() {
/* Fetch the total number of products
and calculate the number of sitemaps needed
*/
return [{ id: 0 }, { id: 1 }, { id: 2 }, { id: 3 }]
}
export default async function sitemap({
id,
}: {
id: number
}): Promise<MetadataRoute.Sitemap> {
// Google's limit is 50,000 URLs per sitemap
const start = id * 50000
const end = start + 50000
const products = await getProducts(
`SELECT id, date FROM products WHERE id BETWEEN ${start} AND ${end}`
)
return products.map((product) => ({
url: `${BASE_URL}/product/${product.id}`,
lastModified: product.date,
}))
}
Static metadata
We can export metadata function from layout.tsx or page.tsx to set static metadata.
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My website',
description: 'Metadata demo',
keywords: []
}
export default function Page() { }
Dynamic metadata
We can export special generateMetadata function which fetches dynamic metadata.
export async function generateMetadata(
{ params }: { params: { id: string } },
parent: ResolvingMetadata
): Promise<Metadata> {
const id = params.id;
const { data } = await axios.get < ProjectType > (`${server}/projects/${id}`);
const previousImages = (await parent).openGraph?.images || [];
return {
title: data.title,
keywords: [
data.category,
data.title,
],
openGraph: {
images: [data.image, ...previousImages],
},
};
}