How to add an RSS feed with images to a Gatsby site

Published on

Last Updated on

Estimated Reading Time: 3 min

Gatsby has a good article on how to add an RSS feed to your gatsby site. Although it will suffice in most cases and is a good starting point, it wasn't exactly working for me.

  • My posts live under "/blog/" but the pages are under "".
  • I am working with MDX, but the document deals with markdown posts.
  • It doesn't explain how to add the featured image in the list view.

Let us start modifying the options once we have the base from the gatsby article.

Getting the data

query `
    site {
        siteMetadata {

        limit: 1000
        filter: { fileAbsolutePath: { regex: "//content/posts//" } }
        sort: { order: DESC, fields: [frontmatter___date] }
    ) {
        edges {
            node {
                excerpt(pruneLength: 140)
                frontmatter {
                    featuredImage {

So what am I doing here?

  • Lines 3-7: I get the siteUrl from the site metaData. We will need this to build the URL to the posts.
  • Line 9: Since all of my content is in MDX files instead of markdown, I use allMdx.
    • Line 10: I limit it to 1000 records. I guess this could be a much smaller value, but it's ok for the time being.
    • Line 11: I want to build the feed only for my posts, so I add a regex to get only those records that are present in "content/posts".
    • Line 12: I sort the records by date in descending order.
  • Lines 14-26: I get the excerpt and html. I also get the slug, title, date and the featured image url from the frontmatter. The excerpt is also pruned to a maximum length of 140 characters.

Build the feed object

The documentation states that every feed must include option, query and title. It also recommends passing a serialize function to customize the feed structure. This is what the final feeds array looks like

feeds: [
        serialize: ({ query: { site, allMdx } }) => {
            const {
                siteMetadata: { siteUrl },
            } = site;

            return => {
                const {
                    node: {
                        frontmatter: { title, date, slug, featuredImage },
                } = edge;

                const blogUrl = `${siteUrl}/blog/${slug}`;

                return Object.assign({}, edge.node.frontmatter, {
                    description: excerpt,
                    url: blogUrl,
                    guid: blogUrl,
                    enclosure: featuredImage && {
                        url: siteUrl + featuredImage.publicURL,
                    custom_elements: [{ 'content:encoded': html }],

        output: '/blog/rss.xml',
        title: "Ankur Sheel's Ramblings",

Let's break this down.

  • Line 3: Create the serialize function which destructures site and allMdx from the query object.
  • Lines 4-6: Destructure the siteUrl from the site object.
  • Line 8: Loop through all the edges and map to a feed item.
    • Lines 9-15:Destructure title, date, slug, featuredImage, excerpt and html.
    • Line 17: Create the URL to the blog post.
    • Line 19: Create the feed item to be returned.
      • Line 20-24: Nothing fancy happening here. Just setting the feed item properties.
      • Line 25-27: enclosure is required to set the featured image. It takes in a URL that is set to the public URL of the featured image. If there is no featured image, then the enclosure will be empty.
      • Line 28: Set the content to be the HTML content.
  • Line 33: Set the path and filename for the RSS feed.
  • Line 34: Set the title for the RSS feed.


After making the changes, the RSS feed for my blog now looks like Rss Feed screenshot

Are you showing images in your RSS feed? How did you go about it? Let me know.