How to create a Sitemap in Nuxt Content
Nuxt Content is an amazing tool that makes working with markdown content on Nuxt projects a breeze. Thanks to the power of Nuxt server routes, it's really easy to create a sitemap of our pages.
Let's take a look at the code.
import { SitemapStream, streamToPromise } from 'sitemap';
import { serverQueryContent } from '#content/server';
export default defineEventHandler(async (event) => {
const docs = await serverQueryContent(event).find();
const staticSites = [
{
_path: '/'
},
{
_path: '/about'
},
{
_path: '/open-source'
}
];
const sitemapElements = [...staticSites, ...docs];
const sitemap = new SitemapStream({
hostname: import.meta.env.VITE_BASE_URL as string
});
for (const doc of sitemapElements) {
sitemap.write({
url: doc._path,
changefreq: 'monthly'
});
}
sitemap.end();
return streamToPromise(sitemap);
});
First of all, let's create a new API route inside api/routes directory by creating a new file called 'sitemap.ts'. Thanks to that, the RRS feed will be available on your-domain.com/sitemap.xml.
Next, inside our defineEventHandler, we have to fetch all articles by using serverQyeryContent:
const docs = await serverQueryContent(event).find();
If you have any other static pages like for example contact or about, you can create an array with those pages:
const staticSites = [
{
_path: '/'
},
{
_path: '/about'
},
{
_path: '/open-source'
}
];
And now, we can combine our articles with static pages:
const sitemapElements = [...staticSites, ...docs];
Next up, let's create a sitemap stream by using the utility function from the 'sitemap' package:
const sitemap = new SitemapStream({
hostname: import.meta.env.VITE_BASE_URL as string
});
Now when we have a sitemap stream, we can iterate over our sitemap elements and write them to the sitemap stream:
for (const doc of sitemapElements) {
sitemap.write({
url: doc._path,
changefreq: 'monthly'
});
}
Next, we have to fetch all the documents we want to include inside our RRS feed. We can make use of the serverQueryContent function from '#content/server':
const docs = await serverQueryContent(event)
.sort({ date: -1 })
.where({ _partial: false })
.find();
Next up, we have to iterate over our docs and put every one of them to our previously created feed object:
for (const doc of docs) {
feed.item({
title: doc.title ?? '-',
url: `${BASE_URL}${doc._path}`,
date: doc.date,
description: doc.description
});
}
Finally, we have to end the stream and return our sitemap stream as a Promise by using the streamToPromise function from the 'sitemap' package.
sitemap.end();
return streamToPromise(sitemap);
Alternatively, if you would like to prerender the sitemap all you have to do is to specify prerender routes in nuxt config:
export default defineNuxtConfig({
// ...
nitro: {
prerender: {
routes: ['/sitemap.xml']
}
},
});
And that's all! I love how simple this solution is thanks to Nuxt server routes and nitro prerendering.