How to create sitemaps for a Nuxt 3 static-generated site

June 20, 2022 (2y ago)

I run a Minecraft server analytics platform which utilises Nuxt 3 for its website, which uses the Nuxt content module for creating the blogs and documentation pages powered by markdown files. This works amazingly well but no sitemap has meant a portion of my website hasn't been indexed by search engines, as you can imagine this is a problem for those searching for our documentation.

As Nuxt 3 and its content module are currently in beta, other libraries that perform sitemap generation haven't yet been updated to support these. Due to this, I've had to look into a temporary solution that would work for the time being. I have managed to create a working solution and wanted to write up a blog in case it helps anyone else.

Installation

To do this, we will first need to install our sitemap library which can be installed like so:

yarn add sitemap

Once the library has been installed, we will need to create a server folder within our sites root directory with a routes sub-folder inside it. Once this has been done we can create our sitemap file within the server/routes folder. This file will contain the following:

server/routes/sitemap.xml.ts
import {serverQueryContent} from '#content/server';
import {SitemapStream, streamToPromise} from 'sitemap';
 
// noinspection TypeScriptUnresolvedFunction
export default defineEventHandler(async (event) => {
    const articles = await serverQueryContent(event).find();
 
    const sitemap = new SitemapStream({ hostname: 'https://yourpageurl.com' });
 
    // Our root page.
    sitemap.write({ url: '/' });
    
    // Other page URLs.
    sitemap.write({ url: '/example/page-1' });
    sitemap.write({ url: '/example/page-2' });
    
    // Our Nuxt content pages.
    articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));
    sitemap.end();
 
    return (await streamToPromise(sitemap));
});

Here we are generating a sitemap based on our static pages and fetching our dynamic pages from the Nuxt content module. This means that any static pages such as pages/test/hello-world.vue would need to be entered as /test/hello-world in the sitemap. Meanwhile any dynamic pages such as /blog/post-1 would be automatically added if created via Nuxt content.

Creating for static sites

As you may of spotted, we are using static generation for our app and so these routes will never exist upon deployment. Thankfully Nuxt lets us pre-render these pages which would build our sitemap when building. We can do this by adding the following to our nuxt.config file:

nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
 
export default defineNuxtConfig({
    nitro: {
        preset: 'aws-lambda',
        prerender: {
            routes: ['/sitemap.xml']
        }
    }
})

And that's it! We've now created a sitemap for our statically generated Nuxt 3 application. You can see a live preview of this sitemap by visiting https://yourpageurl.com/sitemap.xml in your browser once deployed.

Here is a live preview of this in action from my businesses website.