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:
const client = require('../../client')
const sm = require('sitemap')
const defaultUrls = [
{ url: '/', changefreq: 'daily', priority: 1 },
{ url: '/pricing', priority: 0.5 },
{ url: '/pricing/compare', priority: 0.5 },
{ url: '/docs', priority: 0.7 },
{ url: '/community', priority: 0.7 },
{ url: '/blog/', changefreq: 'weekly', priority: 0.7 },
]
async function getSitemap() {
const { routes, blogposts } = await client.fetch(`
{
"routes": *[_type == "route" && includeInSitemap],
"blogposts": *[_type == 'post' && includeInSitemap == true && publishedAt < $now] | order(publishedAt desc) {
slug
}
}
`)
const urls = routes
.filter(({ slug = {} }) => slug.current)
.reduce(
(acc, route) => [
...acc,
{
url: route.slug.current,
priority: route.sitemapPriority || 0.5,
},
],
defaultUrls
)
const blogUrls = blogposts
.filter(({ slug = {} }) => slug.current)
.map(post => {
return {
url: `/blog/${post.slug.current}`,
priority: 0.5,
}
})
return sm.createSitemap({
hostname: 'https://www.sanity.io',
cacheTime: 600000,
urls: urls.concat(blogUrls),
})
}
module.exports = function sitemapXML(req, res, next) {
res.setHeader('Content-Type', 'application/xml')
getSitemap()
.then(result => {
res.send(result.toString())
})
.catch(next)
}
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:
import groq from 'groq'
import sanityClient from '../sanity-client'
export default function SiteMap() {
return <div>loading</div>
}
export async function getServerSideProps({ res }) {
const baseUrl = `https://myawesomesite.com`
const query = groq`{
"countries": *[_type == 'country']{slug},
}`
const urls = await sanityClient.fetch(query)
const countries = urls.countries.map(page => {
const slug =
page.slug.current === '/' ? '/' : `/${page.slug.current}`
return `
<loc>${baseUrl}${slug}</loc>
<changefreq>daily</changefreq>
<priority>0.7</priority>
`
})
const locations = [...countries]
const createSitemap = () => `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${locations
.map(location => {
return `<url>
${location}
</url>
`
})
.join('')}
</urlset>
`
res.setHeader('Content-Type', 'text/xml')
res.write(createSitemap())
res.end()
return {
props: {},
}
}
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. 🙏
There's a reactions leaderboard you can check out too.
Analytics Information