Unlock seamless workflows and faster delivery with our latest releases - Join the deep dive

How to Create a Sitemap when using Next.js

9 replies
Last updated: Jan 8, 2021
Anyone know how to create a sitemap when using NextJS with Sanity?
Not a Sanity specific question I know

I found this from Lee Rob
https://leerob.io/blog/nextjs-sitemap-robots
It doesn't generate the paths though just the file name so,
<https://mysite.com/folder/[file]>
Jan 8, 2021, 4:56 PM
We've set it to an API route inside of Next, with this code:
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)
}

Jan 8, 2021, 5:03 PM
So, do I add this to a scripts folder and call it in the
next.config.js
like in Lee's example
user Y
?
Jan 8, 2021, 5:06 PM
I got this working a different way. Not sure if it is the best way or not but I am using
getServerSideProps
on a page file that is called
sitemap.xml.tsx
and set the headers to text/xml.
Jan 8, 2021, 5:36 PM
Also what is
includeInSitemap
in the query?
Jan 8, 2021, 5:36 PM
Could you link an example
user U
?
Jan 8, 2021, 5:37 PM
import sanity from "@sanity/client";
import groq from "groq";

export default function SiteMap() {
  return <div>loading</div>;
}

export async function getServerSideProps({ res }) {
  const baseUrl = `<https://cwp-www.vercel.app>`;

  const query = groq`{
    "pages": *[_type == 'sitePage']{slug},
  	"service": *[_type == 'service']{slug},
    "people": *[_type == 'person' && title->name != 'Service Ambassador']{slug} ,
	  "article": *[_type == 'article']{slug}
    }`;

  const client = sanity({
    projectId: "YOUR PROJECTID",
    dataset: "YOUR DATASET",
    token: "", // or leave blank to be anonymous user
    useCdn: false, // `false` if you want to ensure fresh data
  });

  const urls = await client.fetch(query);

  const pages = urls.pages.map((page) => {
    const slug = page.slug.current === "/" ? "/" : `/${page.slug.current}`;
    return `${baseUrl}${slug}`;
  });

  const service = urls.service.map((page) => {
    const slug = `/service/${page.slug.current}`;
    return `${baseUrl}${slug}`;
  });

  const people = urls.people.map((page) => {
    const slug = `/people/${page.slug.current}`;
    return `${baseUrl}${slug}`;
  });

  const article = urls.article.map((page) => {
    const slug = `/article/${page.slug.current}`;
    return `${baseUrl}${slug}`;
  });

  const locations = [...pages, ...service, ...people, ...article];

  const createSitemap = () => `<?xml version="1.0" encoding="UTF-8"?>
    <urlset xmlns="<http://www.sitemaps.org/schemas/sitemap/0.9>">
        ${locations
          .map((location) => {
            return `<url>
                        <loc>${location}</loc>
                        <changefreq>weekly</changefreq>
                    </url>
                  `;
          })
          .join("")}
    </urlset>
    `;
  res.setHeader("Content-Type", "text/xml");
  res.write(createSitemap());
  res.end();

  return {
    props: {},
  };
}
Jan 8, 2021, 5:38 PM
That's great
user U
, do you mind if I document this on my blog?
I'll credit you, do you have somewhere I can point to or will just your name there be enough?
Jan 8, 2021, 6:09 PM
Cool!
Jan 8, 2021, 6:16 PM
Yea I don’t mind. Just the name would be cool. Thanks!
Jan 8, 2021, 6:17 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?