Create a sitemap with Next.js

by Kartik Chaturvedi

March 13, 2021

Creating a sitemap is an easy way to bring traffic to your site. It helps search engines find and index all related pages on your domain and understand how they fit together.

Create the sitemap

With NextJS, creating a sitemap is even easier since all routes are organized in the pages directory. Start with the following code in a lib/ or util/ folder in your project root.

sitemap.js
const fs = require('fs');
const globby = require('globby');
const prettier = require('prettier');

(async () => {
  const pages = await globby([
	'pages/**/*.js', // get all static pages
	'!pages/**/[*.js', // ignore dynamic routes as those won't work
	'!pages/_*.js', // ignore nextjs components
	'!pages/api', // ignore api routes as those aren't actual pages 
  ]);

  const sitemap = `
	<?xml version="1.0" encoding="UTF-8"?>
	<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
	  ${pages.map(page => {
		const path = page
		  .replace('pages', '') // make the path start with '/'
		  .replace('.js', '') // remove the extension
		  .replace('/index', '') // remove the unnecessary word index
		return `
		  <url>
			<loc>${DOMAIN}${path}</loc>
		  </url>
		`;
	  }).join('')}
	</urlset>
  `;

  const formatted = prettier.format(sitemap, { parser: 'html' });
  await fs.writeFileSync('./public/sitemap.xml', formatted);
})();

Note that if you have any dynamic routes, you will need to either list those manually, or write a script to first fetch a list of those dynamic routes (you can use the same query functions you use in getStaticPaths in those dynamic pages). Once you have the list, you can simply add them to the array passed into globby() so they get added to the sitemap.

Generate at buildtime

The final step is to generate the sitemap at buildtime. This will ensure the sitemap that gets deployed is always the latest, and always reflects the changes made to the site. To do this, we need to add a custom config to webpack in next.config.js.

next.config.js
module.exports = {
  webpack: (config, { isServer }) => {
	if (isServer) {
	  require('./util/sitemap.js')
	}
	return config
  }
}

And that’s it! When next build is run, the sitemap will automatically be generated and placed in the /public folder, making it accessible at your-domain.com/sitemap.xml.

Kartik's Newsletter

Subscribe to get science and tech news, new posts, and the latest updates from me.

Subscribe on Substack