Skip to content

Instantly share code, notes, and snippets.

Last active December 17, 2020 16:35
Show Gist options
  • Star 49 You must be signed in to star a gist
  • Fork 11 You must be signed in to fork a gist
  • Save evantahler/ba75e277c756fce337b7370035b298e7 to your computer and use it in GitHub Desktop.
Save evantahler/ba75e277c756fce337b7370035b298e7 to your computer and use it in GitHub Desktop.
35 lines to build a sitemap for next.js projects
#! /usr/bin/env node
// I am ./bin/buildSitemap.js
const path = require('path')
const glob = require('glob')
const fs = require('fs')
const SITE_ROOT = process.env.SITE_ROOT || ''
const SOURCE = process.env.SOURCE || path.join(__dirname, '..', 'pages', '/**/*.js')
const DESTINATION = process.env.DESTINATION || path.join(__dirname, '..', 'static', 'sitemap.xml')
let diskPages = glob.sync(SOURCE)
let xml = ''
xml += '<?xml version="1.0" encoding="UTF-8"?>'
xml += '<urlset xmlns="">'
diskPages.forEach((page) => {
let stats = fs.statSync(page)
let modDate = new Date(stats.mtime)
let lastMod = `${modDate.getFullYear()}-${('0' + (modDate.getMonth() + 1)).slice(-2)}-${('0' + modDate.getDate()).slice(-2)}`
page = page.replace(path.join(__dirname, '..', 'pages'), '')
page = page.replace(/.js$/, '')
page = `${SITE_ROOT}${page}`
if (page.match(/.*\/index$/)) {
page = page.replace(/(.*)index$/, '$1')
xml += '<url>'
xml += `<loc>${page}</loc>`
xml += `<lastmod>${lastMod}</lastmod>`
xml += `<changefreq>always</changefreq>`
xml += `<priority>0.5</priority>`
xml += '</url>'
xml += '</urlset>'
fs.writeFileSync(DESTINATION, xml)
console.log(`Wrote sitemap for ${diskPages.length} pages to ${DESTINATION}`)
Copy link

Hey @evantahler, this is great. How would I add this to the configuration and is it possible to use this with pages that get generated dynamically via an API call - so for example, at request for /, I run a fetch to build out all the pages for /job/001, /job/002, etc. These get updated on a regular basis so I would want the sitemap to update whenever the request comes through I guess, without impacting the performance of the application

Copy link

@416serg, I managed to implement a sitemap using something similar to this. Rather than implementing all pages with the same content as above I preg_matched pages and ran a function to give me the output for a specific page type. My content was coming from an API, so I set all those functions up as async, collected them in an array and ran a Promise.all to get the final output.

Copy link

@designspin can you, please, provide an example? Thanks!

Copy link

danakt commented Apr 3, 2018

You don't have to handle _document.js in the pages folder. I think that you need to add a condition to the code.

Copy link

baires commented May 22, 2018

You can just exclude _documents.js by fine tuning the glob pattern:

const SOURCE = process.env.SOURCE || path.join(__dirname, '..', 'pages', '/**/!(_*).js');

Copy link

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment