How to generate your website sitemap in Nuxt3

09 May 2023

Index


What is the sitemap.xml file

A sitemap is a file that lists all the pages and content on a website, organized in a hierarchical structure. It provides a roadmap of the website for search engines and visitors to easily navigate and discover content. Sitemaps can also include additional information, such as the last time a page was modified and its priority level.

By submitting a sitemap to Google through Google Search Console, website owners can ensure that their pages are more easily discovered and crawled by Google's bots. This can help improve the visibility and ranking of a website's pages in Google search results.

In Nuxt it isn't so easy to set up the code that will automatically generate your sitemap of all the pages (both static and dynamic), so today you have to learn how to do this.

Install and setup

First of all we'll need the sitemap package from npm:

npm install --save sitemap

Yes, there's a really cool module called nuxt/sitemap made up for Nuxt or the new simple-sitemap for Nuxt3 but if you have to generate your pages from nuxt/content like me, keep reading this guide.
If you need a basic and fast configuration for your sitemap, follow this link.

Now, we need to tell Nuxt that we want to generate the sitemap.xml page when we're going to build our application. To to this, first of all we need to work under the server folder in our main path. Now let's create the sitemap.xml.ts (or .js if you prefer) in the routes folder.

folder tree

We'll need some methods from node, nuxt and sitemap modules: let's import them.

[sitemap.xml.ts]

import { serverQueryContent } from '#content/server';
import { SitemapStream, streamToPromise } from 'sitemap';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';

Now we have to create the functions that we'll use to handle our static pages under /pages directory, thanks to fs and path module that we just imported.

[sitemap.xml.ts]

const getStaticEndpoints = (): string[] => {
  const __dirname = dirname(fileURLToPath(import.meta.url));
  const files = getFiles(`${__dirname}/../../pages`);
  return files
    .filter((file) => !file.includes('slug'))
    .map((file) => file.split('pages')[1])
    .map((file) => {
      return file.endsWith('index.vue')
        ? file.split('/index.vue')[0]
        : file.split('.vue')[0];
    });
};

const getFiles = (dir: string): string[] => {
  const dirents = fs.readdirSync(dir, { withFileTypes: true });
  const files = dirents.map((dirent) => {
    const res = resolve(dir, dirent.name);
    return dirent.isDirectory() ? getFiles(res) : res;
  });
  return files.flat();
};

Last step, let's fetch our docs from the folder under /content directory and write the code that will generate our sitemap.xml using the sitemap module

You can copy and paste this code, changing the BASE_URL and if you want the changefreq value.

The "changefreq" value can be set to one of several predefined options, such as always, hourly, daily, weekly, monthly, yearly, or never. For example, if a page on your website is updated frequently, such as a news page, the "changefreq" value can be set to "hourly" or "daily" to indicate that the page's content is likely to change frequently. On the other hand, if a page is unlikely to change often, such as an "About Us" page, the "changefreq" value can be set to "yearly" or "never".

[sitemap.xml.ts]

// imports

const BASE_URL = 'https://YOURWEBSITEURL.com';

export default defineEventHandler(async (event) => {
  const sitemap = new SitemapStream({ hostname: BASE_URL });

  // fetch docs in /content/* folders
  const docs = await serverQueryContent(event).find();
  for (const doc of docs) {
    sitemap.write({
      url: doc._path,
      changefreq: 'weekly'
    });
  }

  // fetch page from /page/* folders
  const staticEndpoints = getStaticEndpoints();
  for (const staticEndpoint of staticEndpoints) {
    sitemap.write({
      url: staticEndpoint,
      changefreq: 'weekly'
    });
  }

  sitemap.end();
  return streamToPromise(sitemap);
});

// getStaticEndpoints()
// getFiles()

Congrats! 🎉
Now you can run on of the following commands to see your sitemap.xml generated in the /public directory.

npm run build 

or

npm run generate