monogram with initials UKR

RSS Feed for next.js blog

Updated: Under: technology Tags: #nextjs #web-dev

This blog finally has an RSS feed, I welcome you to 1999. When building my own blog instead of using a blogging platform I knew I was getting into a world of pain.

Most of the site is complete and usable, but what lacked was an RSS feed for potential followers to subscribe with! Let’s leave the talk and get-into it!

Colombo, Sri Lanka 2017, Newspaper Stand
Image 1: Colombo, Sri Lanka 2017, Newspaper Stand

NPM Dependencies

We’ll have to install a new package aptly named rss for making it easy to generate the RSS feed. Why reinvent the wheel, eh?

yarn add rss @types/rss

note: I added @types/rss as my next.js project is in typescript

Making A Fake Route

This is probably the point some might have scratched their heads. How can we create a custom dynamic file during build time?

There is no easy way, but this hack works perfectly. Create a new file in pages named something like static_file_build.tsx (Easter Egg!)

What we will make this route do is,

  • Render Dummy Page.
  • Load Latest Post Details.
  • Write a XML string to a file.

This file serves no display purpose but to ber an entry point to build our rss feed.

import fs from 'fs'

const DummyPage = () => {
  return "Dummy Page";
}

const buildRss = (posts: PostEntity[]): string => {
    // TODO;
}

export const getStaticProps = async () => {
  // Depends On Your Implementation
  const posts = PostAPI.getLatest()
  // Generate Feed XML
  const feedXml = buildRss(posts)
  // Write Generated RSS Feed To Public Folder
  fs.writeFileSync("public/rss.xml", feedXml);

  return {
    props: {
        posts
    },
  }
}

export default DummyPage

As shown above, it’s clear how this works. Depending on your backend get your latests posts loaded and let’s get cracking on building the feed!

Building The Feed

Now this is where the installed rss package comes to the rescue. It has an easy interface/api to build the feed and export the xml. Let’s complete the buildRss function!

Create Feed Object

The first task is to create the feed object. It should be instantiated with your basic site details.

let feed = new RSS({
  title: "Kaveen R",
  description: "blog posts",
  feed_url:  `${process.env.BASE_URL}/rss.xml`,
  site_url: `${process.env.BASE_URL}`,
  pubDate: new Date()
});

Add Posts To Feed Object

Next task is to iterate through all your blog posts and add them to the aforementioned feed object.

// Add Each Post to feed
posts.forEach((post)=>{

  // Take Markdown Content & Convert To basic HTML
  const body = ReactDOMServer.renderToStaticMarkup(
    <ReactMarkdown
        escapeHtml={false}
        source={post.content}
    />
  );

  feed.item({
    title: post.matter.title,
    description: body,
    url: `${process.env.BASE_URL}/posts/${post.matter.slug}`,
    date: post.matter.date,
    category: post.matter.categories,
    author: "Kaveen R",
  })
})

Important Notes

description should contain an HTML representation of your blog post content. Buy invoking ReactDOMServer.renderToStaticMarkup() we’re generating HTML for a given React component. This will change with the libraries you use

categories is a list of unique strings, when using customizable RSS readers users can filter your latests post using the mentioned catagories.

Serializing The Feed

Last step is to convert the feed object into an XML string which will be written to file by our dummy page!

return feed.xml({indent: true});

Now when building your page you’ll see that feed is generated an place on /public/rss.xml!

Housekeeping

There are a couple of more things to do! We ant to make sure that our RSS feed is complaint and also can be found by feed readers. This is how to quickly do that

Checking For Feed Errors

To Make Sure we deliver the best RSS feed to all users, we can validate it using a tool such as W3 Validator which will validate and give suggestions on how to make the feed better.

Making Sure The Feed Is Discoverable

On one of your main next.js template(such as _app.ts) include the following in the header, this meta tag will guide compatible software to the feed.

<Head>
    <link
        rel="alternate"
        type="application/rss+xml"
        title="RSS"
        href="/rss.xml"
    />
</Head>

Adding rss.xml to gitignore

This is to anyone who is using GIT VSC. To avoid commiting the RSS file to VCS accidentally add the feed reference to the .gitignore file.

public/rss.xml

That’s it folks! Now you got a RSS Feed for your blog. It maybe 22 years too late, but at-least we got it!


Complete Code Sample

Here is the complete code sample which we ran through today!

import fs from 'fs'
import RSS from 'rss'
import ReactDOMServer from "react-dom/server";
import ReactMarkdown from "react-markdown";

const DummyPage = () => {
  return "Dummy Page";
}

const buildRss = (posts: PostEntity[]): string => {
  
    // Create Feed With Site Details
    let feed = new RSS({
      title: "Kaveen R",
      description: "blog posts",
      feed_url:  `${process.env.BASE_URL}/rss.xml`,
      site_url: `${process.env.BASE_URL}`,
      pubDate: new Date()
    });
  
    // Add Each Post to feed
    posts.forEach((post)=>{
  
      // Take Markdown Content & Convert To basic HTML
      const body = ReactDOMServer.renderToStaticMarkup(
        <ReactMarkdown
            escapeHtml={false}
            source={post.content}
        />
      );

      feed.item({
        title: post.matter.title,
        description: body,
        url: `${process.env.BASE_URL}/posts/${post.matter.slug}`,
        date: post.matter.date,
        category: post.matter.categories,
        author: "Kaveen R",
      })
    })
  
    // Serialize Feed & Return as string
    return feed.xml({indent: true});
}

export const getStaticProps = async () => {
  // Depends On Your Implementation
  const posts = PostAPI.getLatest()
  // Generate Feed XML
  const feedXml = buildRss(posts)
  // Write Generated RSS Feed To Public Folder
  fs.writeFileSync("public/rss.xml", feedXml);

  return {
    props: {
        posts
    },
  }
}