Sitemap Generation for Dynamic Routes In NextJS with the Sanity Client
A sitemap is an important for Search Engine Optimisation (SEO) because it makes it easier for Google and other search engines to find your site’s pages.
Google ranks web pages not just websites. There is no downside of having an XML Sitemap and having one can improve your SEO.
At the beginning of January I asked a question in the Sanity.io Slack.
The Lee Robinson solution didn’t work for me so I reached out on the Sanity slack channel and Knut being the legend he is offered up how they have done it:
1const client = require('../../client')2const sm = require('sitemap')3const defaultUrls = [4 { url: '/', changefreq: 'daily', priority: 1 },5 { url: '/pricing', priority: 0.5 },6 { url: '/pricing/compare', priority: 0.5 },7 { url: '/docs', priority: 0.7 },8 { url: '/community', priority: 0.7 },9 { url: '/blog/', changefreq: 'weekly', priority: 0.7 },10]11async function getSitemap() {12 const { routes, blogposts } = await client.fetch(`13 {14 "routes": *[_type == "route" && includeInSitemap],15 "blogposts": *[_type == 'post' && includeInSitemap == true && publishedAt < $now] | order(publishedAt desc) {16 slug17 }18 }19 `)20 const urls = routes21 .filter(({ slug = {} }) => slug.current)22 .reduce(23 (acc, route) => [24 ...acc,25 {26 url: route.slug.current,27 priority: route.sitemapPriority || 0.5,28 },29 ],30 defaultUrls31 )32 const blogUrls = blogposts33 .filter(({ slug = {} }) => slug.current)34 .map(post => {35 return {36 url: `/blog/${post.slug.current}`,37 priority: 0.5,38 }39 })40 return sm.createSitemap({41 hostname: 'https://www.sanity.io',42 cacheTime: 600000,43 urls: urls.concat(blogUrls),44 })45}46module.exports = function sitemapXML(req, res, next) {47 res.setHeader('Content-Type', 'application/xml')48 getSitemap()49 .then(result => {50 res.send(result.toString())51 })52 .catch(next)53}
I was just about to start getting my head around how that was done
then James Weis came in with setting the headers to text/xml
This made a lot more sense to me so I implemented this straight away.
Create the file as pages/sitemap.xml.js
then the following:
1import groq from 'groq'2import sanityClient from '../sanity-client'34export default function SiteMap() {5 return <div>loading</div>6}78export async function getServerSideProps({ res }) {9 const baseUrl = `https://myawesomesite.com`10 const query = groq`{11 "countries": *[_type == 'country']{slug},12 }`13 const urls = await sanityClient.fetch(query)14 const countries = urls.countries.map(page => {15 const slug =16 page.slug.current === '/' ? '/' : `/${page.slug.current}`17 return `18 <loc>${baseUrl}${slug}</loc>19 <changefreq>daily</changefreq>20 <priority>0.7</priority>21 `22 })2324 const locations = [...countries]25 const createSitemap = () => `<?xml version="1.0" encoding="UTF-8"?>26 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">27 ${locations28 .map(location => {29 return `<url>30 ${location}31 </url>32 `33 })34 .join('')}35 </urlset>36 `37 res.setHeader('Content-Type', 'text/xml')38 res.write(createSitemap())39 res.end()40 return {41 props: {},42 }43}
This is genius!
So what the code block there is doing is saving the file as the
sitemap and it’s located with the rest of the pages as sitemap.xml
,
this can them be added to the Google search console as the sitemap and
located as https://myawesomesite.com/sitemap.xml
.
I asked for permission to document this from James and he was happy with being mentioned, thanks James. 🙏
Back to Top