Megan Sullivan

How to Add an RSS Feed to Your Gatsby Site

January 30th, 2021

(15-minute read)

Introduction

As a content creator, you want to make it easy for your readers to stay updated on your latest content. By adding an RSS feed to your site, readers can get automatic updates whenever you post a new article, video, or photo of your dog.

In this post, I'll show you how to add an RSS feed to a Gatsby site.

A Quick Crash Course on RSS Feeds

How does an RSS feed work?

RSS stands for "really simple syndication." In other words, it's a way to give other websites information about your content so that they can get it in front of more users.

Here's a brief overview of how it works:

  1. Your site generates an RSS feed that includes information about all your content. You add a link to it someplace (maybe your site's header or footer) where it's easy for users to find.
  2. A reader decides they love your content and want to get updates from your site. (Hooray!) They add the URL for your RSS feed to whatever feed aggregator software they use (like Feedly). The feed aggregator periodically checks your RSS feed to see if there's any new content.
  3. Time goes by. When you post a new piece of content, your RSS feed gets updated to include additional data about the new content.
  4. The next time your reader's feed aggregator checks your site's RSS feed, it sees the new content and notifies the reader. The reader checks out your new content and marvels at how handy it is that your site has an RSS feed!

The best part: once you set up your RSS feed the first time, all the updates happen automatically! 🥳

What does an RSS feed actually look like?

An RSS feed is a specific kind of XML file. The structure looks similar to HTML, but it uses different kinds of elements.

The two main RSS elements are:

  • <channel> - Contains information about your overall site, like the URL where it's hosted. Each RSS feed contains a single <channel> element, which itself contains one or more <item> child elements.
  • <item> - Contains information about a single unit of content on your site, like a specific blog post or video. You'll have multiple <item> elements - one for each piece of content on your site.

Prerequisites

In this post, you'll learn specifically how to add an RSS feed to an existing Gatsby site.

If you don't have a Gatsby site of your own, that's fine! I created some starter code that you can use to follow along. (Don't worry, I won't tell.) More on that in the next section.

If you'd rather follow along with your own Gatsby site, it will be helpful to have a basic blog set up, with separate pages for each post. The starter code uses the gatsby-transformer-remark plugin to query for Markdown nodes, but if your blog posts use something besides Markdown, you can make adjustments to the GraphQL queries specified in this post.

The Starter Code

The starter code for this post is a simplified Gatsby blog. Posts are written in Markdown and are stored in the src/blog directory.

To get the site up and running locally:

  1. Fork the starter project repo on GitHub.
  2. Clone your forked repo. (Don't forget to swap out <your-github-username> for your own GitHub username.)
    shell
    git clone https://github.com/<your-github-username>/gatsby-blog-with-rss-feed-example.git
  3. In your terminal, change directories into the repo you just cloned.
    shell
    cd gatsby-blog-with-rss-feed-example
  4. Start up the local development server.
    shell
    npm run develop
  5. In a web browser, navigate to localhost:8000. You should see something like this:

Adding an RSS Feed

The high-level process for adding an RSS feed to your Gatsby site looks like this:

  • Prerequisite: Confirm that you have siteMetadata set up in your gatsby-config.js file.
  • Step 1: Install the gatsby-plugin-feed plugin.
  • Step 2: Configure gatsby-plugin-feed in your gatsby-config.js file.
  • Step 3: Build and serve your site locally to test the RSS feed.
  • Step 4: (Optional) Add a link to your RSS feed to your site.

Prerequisite: Confirm that you have siteMetadata

If you haven't already, you'll need to add a siteMetadata object to your gatsby-config.js file. This object contains high-level information about your site.

Your siteMetadata object will need the following properties:

  • title - The name of your site.
  • siteUrl - The URL where your site will be hosted once it's deployed.
  • description - A short sentence describing the purpose of your site.

This data will be added to the <channel> element in your RSS feed.

The starter code shows what this looks like in context:

javascript
// gatsby-config.jsmodule.exports = {  siteMetadata: {    title: "My Personal Blog",    siteUrl: "https://my-personal-blog.com",    description:      "An example Gatsby blog with an automatically generated RSS feed.",  },  // ...}

Step 1: Install gatsby-plugin-feed

In your command line, install gatsby-plugin-feed.

shell
npm install gatsby-plugin-feed

This will add the plugin to your package.json file as a dependency and add it to your node_modules folder.

Step 2: Configure the plugin in your gatsby-config.js file

To make your Gatsby site actually use the plugin, you need to add it to the plugins array in your gatsby-config.js file. (You can add it before or after the existing plugins; it doesn't matter.)

javascript
// gatsby-config.jsmodule.exports = {  siteMetadata: { /* ... */ },  plugins: [    {      resolve: 'gatsby-plugin-feed',      options: {        // We'll get to this in a moment      }    },    // The rest of the existing plugins  ]}

Next, configure the additional options that gatsby-plugin-feed needs to generate your RSS feed. Your options object should have the following fields:

  • query - The GraphQL query for pulling in data that should be shared across all the RSS feeds generated.
    • By default, this will pull in the data from siteMetadata. It's still a good idea to configure the query yourself, so that it's explicit.
  • feeds - An array of feed objects (described below).
    • Unless you want to have separate RSS feeds for different kinds of content, you'll probably only need one feed object in this array.

A feed object has the following properties:

  • title - (string) The text to put in the <title> element of the generated RSS feed.
  • output - (string) The path where you want your generated RSS feed to be hosted on your site.
  • query - (string) A GraphQL query for how to get the data for the contents of the feed.
  • serialize - (function) A function specifying how to set properties on the <item> elements in the RSS feed for each piece of content.

Setting the title and output options are more straightforward, but the query and serialize options are described in more detail below.

Configuring options.query and feed.query

You may have noticed that there are two different query attributes in the plugin configuration: one under options and one in an individual feed object. Why are there two?

Imagine if you wanted to generate multiple RSS feeds for your site. For example, maybe you want one RSS feed for your blog posts and a separate RSS feed for your videos. Some of the data for your RSS feed will be the same in both cases (like the metadata for your site), but other data will be different (like the content of each <item> element in your feed).

The data from options.query will be included in all of your RSS feeds, while the data from the query field on a feed object will only be used for that specific feed.

Now let's put this into practice!

The query to pull in your shared site metadata will look like this:

javascript
`{  site {    siteMetadata {      title      description      siteUrl      site_url: siteUrl    }  }}`

And the query to pull in your blog data for your feed will look like this:

javascript
`{  allMarkdownRemark(sort: {fields: frontmatter___date, order: ASC}) {    nodes {      frontmatter {        title        date        description      }      html      slug: gatsbyPath(filePath: "/{MarkdownRemark.frontmatter__title}")    }  }}`

Configuring serialize

The serialize option takes a function that shows how to use the data from your GraphQL queries to build up the fields in each <item> element in the feed.

For this project, your serialize function will set the following properties for each item:

  • title - The name of this piece of content.
  • description - (optional) A 1-2 sentence summary of this piece of content.
  • url - The full URL where this piece of content lives.
    • This will show up as a <link> element in the <item> element generated for the RSS feed.
  • guid - Globally unique identifier. A string that is unique to this piece of content. (You can just use the URL again for this.)
  • date - The publish date for this piece of content.
    • This will show up as a <pubDate> element in the <item> element generated for the RSS feed.

serialize receives all the data from the combined options.query and feed.query response. You can destructure this data and use it in your configuration for each <item> element. For example, the function below will create an <item> element with the title, description, and date data from node.frontmatter, and it also adds a url and guid property by combining data from the site and allMarkdownRemark queries.

javascript
({ query: { site, allMarkdownRemark } }) => {  return allMarkdownRemark.nodes.map(node => {    return Object.assign({}, node.frontmatter, {      url: `${site.siteMetadata.siteUrl}${node.slug}`,      guid: `${site.siteMetadata.siteUrl}${node.slug}`,    })  })}

The Full Plugin Configuration

After adding all the plugin options to your gatsby-config.js file, the configuration for gatsby-plugin-feed should look like this:

javascript
// gatsby-config.js{  resolve: "gatsby-plugin-feed",  options: {    query: `      {        site {          siteMetadata {            title            description            siteUrl            site_url: siteUrl          }        }      }    `,    feeds: [      {        title: "My Personal Blog RSS Feed",        output: "rss.xml",        query: `        {          allMarkdownRemark(sort: {fields: frontmatter___date, order: ASC}) {            nodes {              frontmatter {                title                date                description              }              html              slug: gatsbyPath(filePath: "/{MarkdownRemark.frontmatter__title}")            }          }        }        `,        serialize: ({ query: { site, allMarkdownRemark } }) => {          return allMarkdownRemark.nodes.map(node => {            return Object.assign({}, node.frontmatter, {              url: `${site.siteMetadata.siteUrl}${node.slug}`,              guid: `${site.siteMetadata.siteUrl}${node.slug}`,            })          })        },      }    ]  }},

Step 3: Build and serve your site locally to test the RSS feed

gatsby-plugin-feed only generates an RSS feed for production-style builds. (In other words, the URL to your RSS feed won't work if you're running npm run develop. You'll get a 404 error.)

To test your RSS feed locally, you'll have to build your site and start up a server by running the following command:

shell
npm run build && npm run serve

Once your site is up and running, you should be able to see it in a web browser at localhost:9000. You can check your RSS feed by visiting localhost:9000/rss.xml (or whatever you configured the output option to be).

The generated RSS feed should look something like this:

xml
<rss version="2.0">  <channel>    <title>My Personal Blog RSS Feed</title>    <description>      An example Gatsby blog with an automatically generated RSS feed.    </description>    <link>https://my-personal-blog.com</link>    <generator>GatsbyJS</generator>    <lastBuildDate>Wed, 27 Jan 2021 08:07:58 GMT</lastBuildDate>    <item>      <title>My First Post</title>      <description>The first thing I've ever written.</description>      <link>https://my-personal-blog.com/my-first-post/</link>      <guid isPermaLink="false">https://my-personal-blog.com/my-first-post/</guid>      <pubDate>Fri, 01 Jan 2021 00:00:00 GMT</pubDate>    </item>    <item>      <title>Another Great Post</title>      <description>The second thing I've ever written.</description>      <link>https://my-personal-blog.com/another-great-post/</link>      <guid isPermaLink="false">https://my-personal-blog.com/another-great-post/</guid>      <pubDate>Sat, 02 Jan 2021 00:00:00 GMT</pubDate>    </item>    <item>      <title>Yet Another Post</title>      <description>The third thing I've ever written. I'm on a roll!</description>      <link>https://my-personal-blog.com/yet-another-post/</link>      <guid isPermaLink="false">https://my-personal-blog.com/yet-another-post/</guid>      <pubDate>Sun, 03 Jan 2021 00:00:00 GMT</pubDate>    </item>  </channel></rss>

If it worked, congratulations, your site now has an automatically generated RSS feed! If it didn't, try checking out the Troubleshooting Errors section. (If your problem isn't listed there, reach out to me on Twitter and I'll try to help debug!)

Now that you've done all this work to generate an RSS feed for your site, it's time to make it discoverable by your readers! (This step is technically optional, although it's probably a good idea if you want people to actually find your RSS feed.)

Use Gatsby's <Link> component to add a link to your RSS feed somewhere on your home page. (Not sure where to put it? The header or footer is a good start.)

javascript
// import { Link } from 'gatsby'<Link to="/rss.xml">RSS feed</Link>

If your prod build is still running from Step 3, you'll need to kill the server (with ctrl + c or by closing the terminal window) and rerun the build/serve command to see your changes. (Production builds don't have hot reloading, so you need to restart the server for your changes to be picked up.)

And you're done! The next time you deploy your site, you should be able to visit <your-domain>/rss.xml (or whatever you configured output to be) and see your own RSS feed.

Troubleshooting Errors

To help troubleshoot, here are some of the errors I ran into as I was implementing this on my own site, as well as the solution for how I fixed the problem.

Cannot query field "siteUrl" on type "SiteSiteMetadata".

The Error Message:

shell
ERROR #11321  PLUGIN
    "gatsby-plugin-feed" threw an error while running the onPostBuild    lifecycle:
    Cannot query field "siteUrl" on type "SiteSiteMetadata".
    GraphQL request:7:11    6 |           description    7 |           siteUrl      |           ^    8 |           site_url: siteUrl, Cannot query field "siteUrl" on type     "SiteSiteMetadata".
    GraphQL request:8:11    7 |           siteUrl    8 |           site_url: siteUrl      |           ^    9 |         }

The Underlying Problem: Your site doesn't have site metadata, which the default query in gatsby-plugin-feed expects there to be.

The Solution: Add site metadata to your gatsby-config.js file. See Prerequisite: Confirm that you have siteMetadata.

Cannot query field "fields" on type "MarkdownRemark".

The Error Message:

ERROR #11321  PLUGIN
"gatsby-plugin-feed" threw an error while running the onPostBuildlifecycle:
Cannot query field "fields" on type "MarkdownRemark".
GraphQL request:16:1515 |               }16 |               fields {   |               ^17 |                 slug

The Underlying Problem: Your blog posts don't have a slug field. The default GraphQL query used by gatsby-plugin-feed expects your MarkdownRemark nodes to have a fields.slug property. (You can use the GraphiQL explorer to manually inspect the available fields on the MarkdownRemark query and confirm that fields.slug is not available.)

The Solution: In your configuration for gatsby-plugin-feed (in the gatsby-config.js file), make sure the feed.query option includes a slug field in the query. See the section on Configuring options.query and feed.query in Step 2.

Takeaways

  • Adding an RSS feed to your site lets readers get automatic updates when you post new content.
  • To add an RSS feed to a Gatsby site, use the gatsby-plugin-feed plugin. It only generates RSS feeds on production-style builds.

Wrap It Up

Now that you've added an RSS feed to this sample blog site, try adding one to your own Gatsby site. If you run into problems, you can reach out to me on Twitter and I'll do my best to help troubleshoot.

Want to be notified when I write new content? You can subscribe to the RSS feed for my own blog, or you can follow me on Twitter.

Additional Resources