How to create a Sitemap in Nuxt Content
Tags: nuxt, vue, javascript
Published: 2023-10-11 17:22:57

[Nuxt Content](https://content.nuxt.com/) 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.

```js
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***:
```js
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:

```js
const staticSites = [
        {
            _path: '/'
        },
        {
            _path: '/about'
        },
        {
            _path: '/open-source'
        }
    ];
```

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

```js
const sitemapElements = [...staticSites, ...docs];
```

Next up, let's create a sitemap stream by using the utility function from the ***'sitemap'*** package:

```js
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:

```js
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':

```js
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:

```js
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.

```js
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:

```js
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.