How to add an RSS-feed to your Next.js site
Tags: nextjs, typescript, tutorial, react
Published: 2019-12-02 12:15:52

I love RSS-feeds (and still curse Google for cancelling Google Reader) and use them as my main news source for things I find interesting so with this article I would like to help people to add RSS-feeds to their blogs.

If you read my article about how to add a [sitemap.xml to your next.js site](https://www.bergqvist.it/blog/2019/11/22/adding-sitemap-to-nextjs) you will recognise much of the code, it's pretty much the same base but with slightly different XML-markup.

##Creating the page##

First off we need a page that can return the XML. I suggest you name it *"rss"*, *"feed"* or something similar.

In `getInitialProps` we get our blog posts and set the "Content-Type"-header to  *"text/xml"* so the browser knows that should expect XML instead of HTML.
We then generate the XML and passes it on to the browser using `res.write`.

```
export default class Rss extends React.Component {
  static async getInitialProps({ res }: NextPageContext) {
    if (!res) {
      return;
    }
    const blogPosts = getRssBlogPosts();
    res.setHeader("Content-Type", "text/xml");
    res.write(getRssXml(blogPosts));
    res.end();
  }
}
```

##Generating the base XML for the feed##
For the base XML document you will need to add some basic information like the title of the log, a short description, link to your website and the language of the content.
Title, link and description are mandatory elements in the [RSS specification](https://validator.w3.org/feed/docs/rss2.html) but add as many optional elements as you find useful.

```
const getRssXml = (blogPosts: IBlogPost[]) => {
  const { rssItemsXml, latestPostDate } = blogPostsRssXml(blogPosts);
  return `<?xml version="1.0" ?>
  <rss version="2.0">
    <channel>
        <title>Blog by Fredrik Bergqvist</title>
        <link>https://www.bergqvist.it</link>
        <description>${shortSiteDescription}</description>
        <language>en</language>
        <lastBuildDate>${latestPostDate}</lastBuildDate>
        ${rssItemsXml}
    </channel>
  </rss>`;
};
```

##Adding XML for the blog items##

With the basic stuff out of the way all we need to go is generate some XML for the blog posts and figure out when the blog was updated.

The `item` element should at least contain a link to the blog post, the date when it was published and the text. You can either opt to put a short description and force the user to come visit your page or put the whole post in the XML.

If you have HTML-markup in your text you need to enclose it within a  `<![CDATA[${post.text}]]>`-tag or HTML encode the text.

```
const blogPostsRssXml = (blogPosts: IBlogPost[]) => {
  let latestPostDate: string = "";
  let rssItemsXml = "";
  blogPosts.forEach(post => {
    const postDate = Date.parse(post.createdAt);
    if (!latestPostDate || postDate > Date.parse(latestPostDate)) {
      latestPostDate = post.createdAt;
    }
    rssItemsXml += `
      <item>
        <title>${post.title}</title>
        <link>
          ${post.href}
        </link>
        
        <pubDate>${post.createdAt}</pubDate>
        <description>
        <![CDATA[${post.text}]]>
        </description>
    </item>`;
  });
  return {
    rssItemsXml,
    latestPostDate
  };
};
```


##Finishing up##

The last thing you need to do is to add a `link` to your feed somewhere in the head of your document.

```
<link 
  rel="alternate" 
  type="application/rss+xml" 
  title="RSS for blog posts" 
  href="https://www.bergqvist.it/rss" />
```

This will make it easier for browsers and plugins to auto discover your feed.

[The code is available as a gist on github](https://gist.github.com/fredrikbergqvist/36704828353ebf5379a5c08c7583fe2d) and please leave a comment with any feedback.