gatsby logo


While doing code updates last month I noticed Gatsby RSS generation looked a bit of a mess with graphql queries directly in gatsby-config (gatsby-plugin-feed).
The generated RSS feed also did not validate.

I decided to implement my own generation script similar to the script I made for astro / nextjs but using graphql as a source.

📝 Atom Feed Generation Script

I also decided to use atom for feeds as there are a few advantages over rss.

Why Not Use a Plugin? #

The problem with blindly using plugins is you have no idea how something is implemented.

Also this site has a different graphql layout for data but all of the plugins I found (apart from gatsby-plugin-feed) had the graphql query hard coded.

Script Idea #

Here is a basic checklist of requirements for the script.

Gatsby provides excerpt with graphql so returning an excerpt should be no problem, also most fields are directly available from graphql.

Implementation #

Looking in Gatsby docs it seems the best way to implement a script is to use onPostBuild node API.

Gatsby Node APIs - onPostBuild

I decided to use jpmonette/feed as it worked well with my atom feed generation script.

Github - jpmonette/feed: A RSS, Atom and JSON Feed generator for Node.js

As most of the work is done by graphql & gatsby there are very few imports required & the only extra dependency is feed.

Gatsby GraphQL #

I already had a query setup for the old plugin which returned blog posts using filter.

allMarkdownRemark(
  limit: 20
  sort: { frontmatter: { date: DESC } }
  filter: { frontmatter: { template: { ne: "page" }, draft: { ne: true } } }
)

This returns tha last 20 entries that do not have page template & are not marked as a draft & sorts the output in descending order based on date.

excerpt(format: PLAIN, pruneLength: 450, truncate: false)

I also used excerpt to return a snippet for the summary field in the atom output.

Gatsby - GraphQL Query Options

Feed Generation #

Flow of feed generation.

Code Snippets #

Map over array of blog posts & Add each post using addItemToFeed.
Add author using addContributor.

  blogPosts.map((posts) => posts.node).forEach(addItemToFeed(feed, siteMetadata))
  feed.addContributor({
    name: options.author,
    link: siteMetadata.site_url,
  })

Write output files async.

  await fs.writeFile(`./public/${options.output.atom}`, feed.atom1())
  await fs.writeFile(`./public/${options.output.rss2}`, feed.rss2())
  await fs.writeFile(`./public/${options.output.json}`, feed.json1())

Source Code #

You can find the full pull request for these changes on github.

Valid Syndication Feed Generation pull request on github

The source for the site is available on github.

equk-gatsby