3 min read

Easy Sitemaps for Next.js

Next.js does not create a sitemap.xml file automatically. Here is a fast way to add support.
Easy Sitemaps for Next.js
Photo by Aaron Burden / Unsplash

After I changed my blog over to Next.js, I was looking for a quick and easy way to add a sitemap.xml file to my site. And I stumbled across this nifty module that has maybe the lowest effort possible. Here is how I used next-sitemap to quickly add sitemap support.

1. Install

yarn add next-sitemap -D

or

npm install next-sitemap --save-dev

2. Add Configuration

module.exports = {
  siteUrl: '<https://khrome.dev>',
  generateRobotsTxt: true, // (optional)
  // ...other options
}

3. Add to Scripts

I setup the package.json to handle running the sitemap module automatically. This uses a nice feature of NPM, where post will run after the task it prefixes. In this case it will run after npm run build automatically without any extra work.

"scripts": {
    "dev": "next",
    "build": "next build",
    "postbuild": "next-sitemap",
    "start": "next start"
  },

Output

This writes a sitemap.xml and  robots.txt file to the public folder. The robots file is automatically referencing the sitemap so search engine crawlers can find it.

robots.txt

User-agent: *
Allow: /
Host: <https://khrome.dev>
Sitemap: <https://khrome.dev/sitemap.xml>

sitemap.xml

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="<http://www.sitemaps.org/schemas/sitemap/0.9>"
  xmlns:news="<http://www.google.com/schemas/sitemap-news/0.9>"
  xmlns:xhtml="<http://www.w3.org/1999/xhtml>"
  xmlns:mobile="<http://www.google.com/schemas/sitemap-mobile/1.0>"
  xmlns:image="<http://www.google.com/schemas/sitemap-image/1.1>"
  xmlns:video="<http://www.google.com/schemas/sitemap-video/1.1>">
  <url>
    <loc><https://khrome.dev/></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/about></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/web-development-is-hard></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/the-rise-of-privacy-focused-analytics></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/an-unexpected-benefit-of-tailwind-css></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/creating-compelling-and-useful-404-pages></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/custom-decorators-with-storybook-and-vue></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/html-elements-with-flex-box-quirks></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
  <url>
    <loc><https://khrome.dev/custom-404-pages-on-zeit-now-v2-platform></loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2020-12-25T23:29:22.304Z</lastmod>
  </url>
</urlset>

How it Works

This works by crawling the output of the .next folder after building the site. The output in the folder determines the pages reference in the sitemap. It then creates all assets in the public folder needed by Google and other search engines. It is a simple approach that relies on the .next not changing its underlying behavior of it’s output. In other words, simple, but not robust.

Alternative Approaches

  1. One alternative would be to create a sitemap.xml.js route that outputs a xml formatted file. This file would have to import all the pages that were used to build the site, and generate the output. This is very similar to what my Svelte/Sapper project did.
  2. Another approach would be to modify the webpack configuration to gather information about all exported files, and then create a sitemap with that information.
  3. Finally, another approach would be to create a /pages/api/sitemap.js route that outputs xml similar to the first alternative.