sitemap.xml
Source URL: https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap
sitemap.xml
Section titled “sitemap.xml”sitemap.(xml|js|ts) is a special file that matches the Sitemaps XML format to help search engine crawlers index your site more efficiently.
Sitemap files (.xml)
Section titled “Sitemap files (.xml)”For smaller applications, you can create a sitemap.xml file and place it in the root of your app directory.
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://acme.com</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>yearly</changefreq> <priority>1</priority> </url> <url> <loc>https://acme.com/about</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> <url> <loc>https://acme.com/blog</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>weekly</changefreq> <priority>0.5</priority> </url></urlset>Generating a sitemap using code (.js, .ts)
Section titled “Generating a sitemap using code (.js, .ts)”You can use the sitemap.(js|ts) file convention to programmatically generate a sitemap by exporting a default function that returns an array of URLs. If using TypeScript, a Sitemap type is available.
Good to know:
sitemap.jsis a special Route Handler that is cached by default unless it uses a Dynamic API or dynamic config option.
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap { return [ { url: 'https://acme.com', lastModified: new Date(), changeFrequency: 'yearly', priority: 1, }, { url: 'https://acme.com/about', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8, }, { url: 'https://acme.com/blog', lastModified: new Date(), changeFrequency: 'weekly', priority: 0.5, }, ]}export default function sitemap() { return [ { url: 'https://acme.com', lastModified: new Date(), changeFrequency: 'yearly', priority: 1, }, { url: 'https://acme.com/about', lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8, }, { url: 'https://acme.com/blog', lastModified: new Date(), changeFrequency: 'weekly', priority: 0.5, }, ]}Output:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://acme.com</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>yearly</changefreq> <priority>1</priority> </url> <url> <loc>https://acme.com/about</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>monthly</changefreq> <priority>0.8</priority> </url> <url> <loc>https://acme.com/blog</loc> <lastmod>2023-04-06T15:02:24.021Z</lastmod> <changefreq>weekly</changefreq> <priority>0.5</priority> </url></urlset>Image Sitemaps
Section titled “Image Sitemaps”You can use images property to create image sitemaps. Learn more details in the Google Developer Docs.
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap { return [ { url: 'https://example.com', lastModified: '2021-01-01', changeFrequency: 'weekly', priority: 0.5, images: ['https://example.com/image.jpg'], }, ]}Output:
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1"> <url> <loc>https://example.com</loc> <image:image> <image:loc>https://example.com/image.jpg</image:loc> </image:image> <lastmod>2021-01-01</lastmod> <changefreq>weekly</changefreq> <priority>0.5</priority> </url></urlset>Video Sitemaps
Section titled “Video Sitemaps”You can use videos property to create video sitemaps. Learn more details in the Google Developer Docs.
import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap { return [ { url: 'https://example.com', lastModified: '2021-01-01', changeFrequency: 'weekly', priority: 0.5, videos: [ { title: 'example', thumbnail_loc: 'https://example.com/image.jpg', description: 'this is the description', }, ], }, ]}Output:
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:video="http://www.google.com/schemas/sitemap-video/1.1"> <url> <loc>https://example.com</loc> <video:video> <video:title>example</video:title> <video:thumbnail_loc>https://example.com/image.jpg</video:thumbnail_loc> <video:description>this is the description</video:description> </video:video> <lastmod>2021-01-01</lastmod> <changefreq>weekly</changefreq> <priority>0.5</priority> </url></urlset>Generate a localized Sitemap
Section titled “Generate a localized Sitemap”import type { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap { return [ { url: 'https://acme.com', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es', de: 'https://acme.com/de', }, }, }, { url: 'https://acme.com/about', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es/about', de: 'https://acme.com/de/about', }, }, }, { url: 'https://acme.com/blog', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es/blog', de: 'https://acme.com/de/blog', }, }, }, ]}export default function sitemap() { return [ { url: 'https://acme.com', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es', de: 'https://acme.com/de', }, }, }, { url: 'https://acme.com/about', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es/about', de: 'https://acme.com/de/about', }, }, }, { url: 'https://acme.com/blog', lastModified: new Date(), alternates: { languages: { es: 'https://acme.com/es/blog', de: 'https://acme.com/de/blog', }, }, }, ]}Output:
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> <loc>https://acme.com</loc> <xhtml:link rel="alternate" hreflang="es" href="https://acme.com/es"/> <xhtml:link rel="alternate" hreflang="de" href="https://acme.com/de"/> <lastmod>2023-04-06T15:02:24.021Z</lastmod> </url> <url> <loc>https://acme.com/about</loc> <xhtml:link rel="alternate" hreflang="es" href="https://acme.com/es/about"/> <xhtml:link rel="alternate" hreflang="de" href="https://acme.com/de/about"/> <lastmod>2023-04-06T15:02:24.021Z</lastmod> </url> <url> <loc>https://acme.com/blog</loc> <xhtml:link rel="alternate" hreflang="es" href="https://acme.com/es/blog"/> <xhtml:link rel="alternate" hreflang="de" href="https://acme.com/de/blog"/> <lastmod>2023-04-06T15:02:24.021Z</lastmod> </url></urlset>Generating multiple sitemaps
Section titled “Generating multiple sitemaps”While a single sitemap will work for most applications. For large web applications, you may need to split a sitemap into multiple files.
There are two ways you can create multiple sitemaps:
- By nesting
sitemap.(xml|js|ts)inside multiple route segments e.g.app/sitemap.xmlandapp/products/sitemap.xml. - By using the
generateSitemapsfunction.
For example, to split a sitemap using generateSitemaps, return an array of objects with the sitemap id. Then, use the id to generate the unique sitemaps.
import type { MetadataRoute } from 'next'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(props: { id: Promise<string>}): Promise<MetadataRoute.Sitemap> { const id = await props.id // 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, }))}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(props) { const id = await props.id // 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, }))}Your generated sitemaps will be available at /.../sitemap/[id]. For example, /product/sitemap/1.xml.
See the generateSitemaps API reference for more information.
Returns
Section titled “Returns”The default function exported from sitemap.(xml|ts|js) should return an array of objects with the following properties:
type Sitemap = Array<{ url: string lastModified?: string | Date changeFrequency?: | 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never' priority?: number alternates?: { languages?: Languages<string> }}>Version History
Section titled “Version History”| Version | Changes |
|---|---|
v16.0.0 | id is now a promise that resolves to a string. |
v14.2.0 | Add localizations support. |
v13.4.14 | Add changeFrequency and priority attributes to sitemaps. |
v13.3.0 | sitemap introduced. |
Next Steps
Section titled “Next Steps”Learn how to use the generateSitemaps function.
- generateSitemaps
- Learn how to use the generateSiteMaps function to create multiple sitemaps for your application.