DEV Community

Kartik Chaturvedi
Kartik Chaturvedi

Posted on • Originally published at ikartik.com

Create a sitemap with Next.js

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.

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);
})();
Enter fullscreen mode Exit fullscreen mode

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.

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

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.

Top comments (2)

Collapse
 
adrien profile image
Adrien Rahier

For future readers, also note that Next.js has a great example on how to properly handle sitemaps: github.com/vercel/next.js/tree/can...

Collapse
 
adrien profile image
Adrien Rahier

Great tip! Thanks a lot
Good to know, in the above code DOMAIN is undefined and you should add it to the top like this:
const DOMAIN = 'example.com';