Creating an api endpoint
First of all, we will create a new file on `pages/api/sitemap.js`. In this file we will write a handler that creates or sitemap dynamically.
export default async function handler(request, response) {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/xml');
// Instructing the Vercel edge to cache the file
response.setHeader('Cache-control', 'stale-while-revalidate, s-maxage=3600');
// generate sitemap here
let xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://wardpoel.be</loc>
<lastmod>2023-03-29</lastmod>
</url>
</urlset>
`;
response.end(xml);
}
The sitemap we just made, will only include our homepage. We can easily add urls in the `<urlset>`. Let's say we have a blog on our site and want to include all our blogs in the sitemap.
export default async function handler(request, response) {
response.statusCode = 200;
response.setHeader('Content-Type', 'text/xml');
// Instructing the Vercel edge to cache the file
response.setHeader('Cache-control', 'stale-while-revalidate, s-maxage=3600');
let blogs = await client.fetch(`*[_type == "blog"]{slug, _updatedAt} | order(date desc)`);
// generate sitemap here
let xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://wardpoel.be</loc>
<lastmod>2023-03-29</lastmod>
</url>
<url>
<loc>https://wardpoel.be/blog</loc>
<lastmod>2023-03-29</lastmod>
</url>
${blogs.map(blog => `
<url>
<loc>https://wardpoel.be/blog/${blog.slug.current}</loc>
<lastmod>${blog._updatedAt}</lastmod>
</url>
`)}
</urlset>
`;
response.end(xml);
}
See how we add each blog to the sitemap `urlset` section. And we also included the blogs overview page.
Rewrite rule
The last step is to use a rewrite rule. This configuration will rewrite requests from `/sitemap.xml` to our custom `/api/sitemap` endpoint.
module.exports = {
async rewrites() {
return [
{
source: '/sitemap.xml',
destination: '/api/sitemap',
},
]
},
}