Table of contents
Getting started
Installation
yarn add next-sitemap
Create config file
next-sitemap
requires a basic config file (next-sitemap.config.js
) under your project root
ā
next-sitemap
will load environment variables from .env
files by default.
module.exports = {
siteUrl: process.env.SITE_URL || 'https://example.com',
generateRobotsTxt: true,
}
Building sitemaps
Add next-sitemap as your postbuild script
{
"build": "next build",
"postbuild": "next-sitemap"
}
Custom config file
You can also use a custom config file instead of next-sitemap.config.js
. Just pass --config <your-config-file>.js
to build command (Example: custom-config-file)
{
"build": "next build",
"postbuild": "next-sitemap --config awesome.config.js"
}
Building sitemaps with pnpm
When using pnpm you need to create a .npmrc
file in the root of your project if you want to use a postbuild step:
//.npmrc
enable-pre-post-scripts=true
Index sitemaps (Optional)
š£ From next-sitemap
v2.x onwards, sitemap.xml
will be Index Sitemap. It will contain urls of all other generated sitemap endpoints.
Index sitemap generation can be turned off by setting generateIndexSitemap: false
in next-sitemap config file. (This is useful for small/hobby sites which does not require an index sitemap) (Example: no-index-sitemaps)
Splitting large sitemap into multiple files
Define the sitemapSize
property in next-sitemap.config.js
to split large sitemap into multiple files.
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
sitemapSize: 7000,
}
Above is the minimal configuration to split a large sitemap. When the number of URLs in a sitemap is more than 7000, next-sitemap
will create sitemap (e.g. sitemap-0.xml, sitemap-1.xml) and index (e.g. sitemap.xml) files.
Configuration Options
property | description | type |
---|
siteUrl | Base url of your website | string |
changefreq (optional) | Change frequency. Default daily | string |
priority (optional) | Priority. Default 0.7 | number |
sitemapBaseFileName (optional) | The name of the generated sitemap file before the file extension. Default "sitemap" | string |
alternateRefs (optional) | Denote multi-language support by unique URL. Default [] | AlternateRef[] |
sitemapSize(optional) | Split large sitemap into multiple files by specifying sitemap size. Default 5000 | number |
autoLastmod (optional) | Add <lastmod/> property. Default true | true |
exclude (optional) | Array of relative paths (wildcard pattern supported) to exclude from listing on sitemap.xml or sitemap-*.xml . e.g.: ['/page-0', '/page-*', '/private/*'] .
Apart from this option next-sitemap also offers a custom transform option which could be used to exclude urls that match specific patterns | string[] |
sourceDir (optional) | next.js build directory. Default .next | string |
outDir (optional) | All the generated files will be exported to this directory. Default public | string |
transform (optional) | A transformation function, which runs for each relative-path in the sitemap. Returning null value from the transformation function will result in the exclusion of that specific path from the generated sitemap list. | async function |
additionalPaths (optional) | Async function that returns a list of additional paths to be added to the generated sitemap list. | async function |
generateIndexSitemap | Generate index sitemaps. Default true | boolean |
generateRobotsTxt (optional) | Generate a robots.txt file and list the generated sitemaps. Default false | boolean |
robotsTxtOptions.transformRobotsTxt (optional) | Custom robots.txt transformer function. (Example: custom-robots-txt-transformer)
Default: async(config, robotsTxt)=> robotsTxt | async function |
robotsTxtOptions.policies (optional) | Policies for generating robots.txt .
Default:
[{ userAgent: '*', allow: '/' }] | IRobotPolicy[] |
robotsTxtOptions.additionalSitemaps (optional) | Options to add additional sitemaps to robots.txt host entry | string[] |
robotsTxtOptions.includeNonIndexSitemaps (optional) | From v2.4x onwards, generated robots.txt will only contain url of index sitemap and custom provided endpoints from robotsTxtOptions.additionalSitemaps . This is to prevent duplicate url submission (once through index-sitemap -> sitemap-url and once through robots.txt -> HOST)
Set this option true to add all generated sitemap endpoints to robots.txt
Default false (Recommended) | boolean |
Custom transformation function
Custom transformation provides an extension method to add, remove or exclude path
or properties
from a url-set. Transform function runs for each relative path
in the sitemap. And use the key
: value
object to add properties in the XML.
Returning null
value from the transformation function will result in the exclusion of that specific relative-path
from the generated sitemap list.
module.exports = {
transform: async (config, path) => {
if (customIgnoreFunction(path)) {
return null
}
if (customLimitedField(path)) {
return {
loc: path,
changefreq: 'weekly',
}
}
return {
loc: path,
changefreq: config.changefreq,
priority: config.priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? [],
}
},
}
Additional paths function
additionalPaths
this function can be useful if you have a large list of pages, but you don't want to render them all and use fallback: true. Result of executing this function will be added to the general list of paths and processed with sitemapSize
. You are free to add dynamic paths, but unlike additionalSitemap
, you do not need to split the list of paths into different files in case there are a lot of paths for one file.
If your function returns a path that already exists, then it will simply be updated, duplication will not happen.
module.exports = {
additionalPaths: async (config) => {
const result = []
result.push({ loc: '/additional-page-1' })
result.push({
loc: '/additional-page-2',
changefreq: 'yearly',
priority: 0.7,
lastmod: new Date().toISOString(),
alternateRefs: [
{
href: 'https://es.example.com',
hreflang: 'es',
},
{
href: 'https://fr.example.com',
hreflang: 'fr',
},
],
})
result.push(await config.transform(config, '/additional-page-3'))
return result
},
}
Full configuration example
Here's an example next-sitemap.config.js
configuration with all options
module.exports = {
siteUrl: 'https://example.com',
changefreq: 'daily',
priority: 0.7,
sitemapSize: 5000,
generateRobotsTxt: true,
exclude: ['/protected-page', '/awesome/secret-page'],
alternateRefs: [
{
href: 'https://es.example.com',
hreflang: 'es',
},
{
href: 'https://fr.example.com',
hreflang: 'fr',
},
],
transform: async (config, path) => {
return {
loc: path,
changefreq: config.changefreq,
priority: config.priority,
lastmod: config.autoLastmod ? new Date().toISOString() : undefined,
alternateRefs: config.alternateRefs ?? [],
}
},
additionalPaths: async (config) => [
await config.transform(config, '/additional-page'),
],
robotsTxtOptions: {
policies: [
{
userAgent: '*',
allow: '/',
},
{
userAgent: 'test-bot',
allow: ['/path', '/path-2'],
},
{
userAgent: 'black-listed-bot',
disallow: ['/sub-path-1', '/path-2'],
},
],
additionalSitemaps: [
'https://example.com/my-custom-sitemap-1.xml',
'https://example.com/my-custom-sitemap-2.xml',
'https://example.com/my-custom-sitemap-3.xml',
],
},
}
Above configuration will generate sitemaps based on your project and a robots.txt
like this.
# *
User-agent: *
Allow: /
# test-bot
User-agent: test-bot
Allow: /path
Allow: /path-2
# black-listed-bot
User-agent: black-listed-bot
Disallow: /sub-path-1
Disallow: /path-2
# Host
Host: https://example.com
# Sitemaps
Sitemap: https://example.com/sitemap.xml # Index sitemap
Sitemap: https://example.com/my-custom-sitemap-1.xml
Sitemap: https://example.com/my-custom-sitemap-2.xml
Sitemap: https://example.com/my-custom-sitemap-3.xml
Generating dynamic/server-side sitemaps
next-sitemap
now provides two APIs to generate server side sitemaps. This will help to dynamically generate index-sitemap
(s) and sitemap
(s) by sourcing data from CMS or custom source.
-
getServerSideSitemapIndex
: Generates index sitemaps based on urls provided and returns application/xml
response. Supports next13+ route.{ts,js} file.
- To continue using inside pages directory, import
getServerSideSitemapIndexLegacy
instead.
-
getServerSideSitemap
: Generates sitemap based on field entires and returns application/xml
response. Supports next13+ route.{ts,js} file.
- To continue using inside pages directory, import
getServerSideSitemapLegacy
instead.
Server side index-sitemaps (getServerSideSitemapIndex)
Here's a sample script to generate index-sitemap on server side.
1. Index sitemap (app directory)
Create app/server-sitemap-index.xml/route.ts
file.
import { getServerSideSitemapIndex } from 'next-sitemap'
export async function GET(request: Request) {
return getServerSideSitemapIndex([
'https://example.com/path-1.xml',
'https://example.com/path-2.xml',
])
}
2. Index sitemap (pages directory) (legacy)
Create pages/server-sitemap-index.xml/index.tsx
file.
import { getServerSideSitemapIndexLegacy } from 'next-sitemap'
import { GetServerSideProps } from 'next'
export const getServerSideProps: GetServerSideProps = async (ctx) => {
return getServerSideSitemapIndexLegacy(ctx, [
'https://example.com/path-1.xml',
'https://example.com/path-2.xml',
])
}
export default function SitemapIndex() {}
Exclude server index sitemap from robots.txt
Now, next.js
is serving the dynamic index-sitemap from http://localhost:3000/server-sitemap-index.xml
.
List the dynamic sitemap page in robotsTxtOptions.additionalSitemaps
and exclude this path from static sitemap list.
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
exclude: ['/server-sitemap-index.xml'],
robotsTxtOptions: {
additionalSitemaps: [
'https://example.com/server-sitemap-index.xml',
],
},
}
In this way, next-sitemap
will manage the sitemaps for all your static pages and your dynamic index-sitemap
will be listed on robots.txt.
server side sitemap (getServerSideSitemap)
Here's a sample script to generate sitemaps on server side.
1. Sitemaps (app directory)
Create app/server-sitemap.xml/route.ts
file.
import { getServerSideSitemap } from 'next-sitemap'
export async function GET(request: Request) {
return getServerSideSitemap([
{
loc: 'https://example.com',
lastmod: new Date().toISOString(),
},
{
loc: 'https://example.com/dynamic-path-2',
lastmod: new Date().toISOString(),
},
])
}
2. Sitemaps (pages directory) (legacy)
Create pages/server-sitemap.xml/index.tsx
file.
import { getServerSideSitemapLegacy } from 'next-sitemap'
import { GetServerSideProps } from 'next'
export const getServerSideProps: GetServerSideProps = async (ctx) => {
const fields = [
{
loc: 'https://example.com',
lastmod: new Date().toISOString(),
},
{
loc: 'https://example.com/dynamic-path-2',
lastmod: new Date().toISOString(),
},
]
return getServerSideSitemapLegacy(ctx, fields)
}
export default function Sitemap() {}
Now, next.js
is serving the dynamic sitemap from http://localhost:3000/server-sitemap.xml
.
List the dynamic sitemap page in robotsTxtOptions.additionalSitemaps
and exclude this path from static sitemap list.
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
exclude: ['/server-sitemap.xml'],
robotsTxtOptions: {
additionalSitemaps: [
'https://example.com/server-sitemap.xml',
],
},
}
In this way, next-sitemap
will manage the sitemaps for all your static pages and your dynamic sitemap will be listed on robots.txt.
Typescript JSDoc
Add the following line of code in your next-sitemap.config.js
for nice typescript autocomplete! š
module.exports = {
}
Contribution
All PRs are welcome :)