App Router (recommended)
Next.js App Router has built-in sitemap support. Create app/sitemap.ts and export a default function.
Static sitemap
// app/sitemap.ts
import type { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
return [
{ url: "https://website.com", lastModified: new Date() },
{ url: "https://website.com/about", lastModified: new Date() },
{ url: "https://website.com/blog", lastModified: new Date() },
];
}
This generates /sitemap.xml automatically. No packages needed.
Dynamic sitemap
Fetch data from an API or database to generate URLs dynamically.
// app/sitemap.ts
import type { MetadataRoute } from "next";
export default async function sitemap(): MetadataRoute.Sitemap {
const res = await fetch("https://jsonplaceholder.typicode.com/posts");
const posts: { id: number }[] = await res.json();
const postUrls = posts.map((post) => ({
url: `https://website.com/post/${post.id}`,
lastModified: new Date(),
}));
return [
{ url: "https://website.com", lastModified: new Date() },
...postUrls,
];
}
Multiple sitemaps
For large sites, use generateSitemaps to split into multiple files.
// app/sitemap.ts
import type { MetadataRoute } from "next";
export async function generateSitemaps() {
return [{ id: 0 }, { id: 1 }, { id: 2 }];
}
export default async function sitemap({
id,
}: {
id: number;
}): Promise<MetadataRoute.Sitemap> {
const start = id * 5000;
const end = start + 5000;
const posts = await getPostRange(start, end);
return posts.map((post) => ({
url: `https://website.com/post/${post.id}`,
lastModified: post.updatedAt,
}));
}
This generates /sitemap/0.xml, /sitemap/1.xml, etc.
Pages Router (legacy)
If you’re still on Pages Router, the script-based approach works. Use next-sitemap for a simpler setup.
npm install next-sitemap
// next-sitemap.config.js
module.exports = {
siteUrl: "https://website.com",
generateRobotsTxt: true,
};
// package.json
{
"scripts": {
"postbuild": "next-sitemap"
}
}
Submit to Google Search Console
After deployment, submit your sitemap URL in Google Search Console under Sitemaps. The old google.com/ping?sitemap= endpoint was deprecated in 2023.