DEV Community

Cover image for How to create a Sitemap in Nuxt Content
Michał Kuncio
Michał Kuncio

Posted on • Originally published at michalkuncio.com

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);
});


Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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'
        }
    ];
Enter fullscreen mode Exit fullscreen mode

And now, we can combine our articles with static pages:

const sitemapElements = [...staticSites, ...docs];
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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'
    });
}
Enter fullscreen mode Exit fullscreen mode

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();
Enter fullscreen mode Exit fullscreen mode

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
    });
}
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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']
        }
    },
});
Enter fullscreen mode Exit fullscreen mode

And that's all! I love how simple this solution is thanks to Nuxt server routes and nitro prerendering.

Top comments (0)