Category

How To Add an RSS Feed to a Nuxt Website

If you are a user of Nuxt Content and you wish to configure an RSS feed for your website, it's a surprisingly straight forward process! In this article, we will walk through the code changes required to host an RSS feed for both a statically generated, and Universal Nuxt application.

Preface

In version 2 of Nuxt, the community module, nuxt-community/feed-module was a popular choice for adding an RSS feed to your website. However, there has been an unresolved open issue since April 1st, 2022 to add support for Nuxt v3. Thankfully, implementing this feature without a module is relatively straight forward.

Instructions

First, install the feed library into your project:

npm i -D feed

Then, create a server/ folder in your project if it does not already exist, and create a file named server/routes/atom.ts.

Here, we will leverage the feed library and construct an XML representation of our Nuxt content. As you can see, we first define our feed with metadata associated with our RSS feed. This will be used by RSS readers to provide context to the end user. Then, we query our Nuxt content with serverQueryContent and append a feed.addItem for each article.

import { serverQueryContent } from '#content/server';
import { Feed } from 'feed';

const BASE_URL = "https://mywebsite.com"
const AUTHOR_NAME = "Firstname Lastname"

export default defineEventHandler(async (event) => {

    const feed = new Feed({
      title: "My Title",
      description: "My Description",
      id: BASE_URL,
      link: BASE_URL,
      language: "en",
      image: `${BASE_URL}/images/placeholder.png`,
      favicon: `${BASE_URL}/favicon.ico`,
      copyright: `All rights reserved ${new Date().getFullYear()}, ${AUTHOR_NAME}`,
      updated: new Date(),
      generator: "Nuxt static site generation + Feed for Node.js",
      feedLinks: {
        atom: `${BASE_URL}/atom`
      },
      author: {
        name: AUTHOR_NAME,
      }
    });

    const articles = await serverQueryContent(event).find();

    articles.forEach((article) => {
      feed.addItem({
        title: article.title ? article.title : "Missing Title",
        id: article._path,
        link: `${BASE_URL}${article._path}`,
        description: article.description,
        author: [
          {
            name: AUTHOR_NAME,
          },
        ],
        date: new Date(article.date),
        image: article.cover_image ? `${BASE_URL}/${article.cover_image}` : undefined
      });
    });

    return feed.atom1();
});

And that's just about it! Except, if you are statically generating your website with the nuxt generate command, you will need to configure this server-side route to be pre-rendered on site generation. This is as simple as adding a nitro prerender definition in your nuxt.config.ts file, like so:

nitro: {
  prerender: {
    routes: ['/atom']
  }
}

Bonus

You may also be interested in adding a sitemap.xml to your website. This can be done in almost an identical fashion!

Install the dependency:

npm i -D sitemap

Create a route at server/routes/sitemap.xml.ts:

import { serverQueryContent } from '#content/server';
import { SitemapStream, streamToPromise } from 'sitemap';

export default defineEventHandler(async (event) => {
    const articles = await serverQueryContent(event).find();

    const sitemap = new SitemapStream({ hostname: 'https://my-website.com/' });

    // Add non nuxt content endpoints here
    sitemap.write({ url: '/' });
    sitemap.write({ url: '/articles' });

    // Dynamically generate routes for Nuxt markdown content
    articles.forEach((article) => sitemap.write({ url: article._path, changefreq: 'monthly' }));
    sitemap.end();

    return (await streamToPromise(sitemap));
});

And add the prerender entry in your nuxt.config.ts:

nitro: {
  prerender: {
    routes: ['/sitemap.xml', '/atom']
  }
}