Published on

Gatsby RSS feed with images compatible with mailchimp newsletter

Authors

As I've been playing around with SSR, Gatsby and starting yet another blog (about coffee this time), I thought it would be a nice experiment to start building an email-list with Mailchimp while I was at it. There is this cool feature that automatically generates newsletters based on RSS feeds and I decided to give that a go.

The first logical place to get started is of course the Gatsby "Adding an RSS feed" howto guide. This works like a charm, but for my email newsletter the image is a must have.

There were a couple of caveats I ran into:

  • You have to add a custom xml namespace in the setup options to support <media:content> tags in your feed, as defined by the rssboard
  • The query should contain a reference to the image, I (re)used a childImageSharp from one of the pages where I render the blog images.
  • Please note that images in queries in gatsby-config.js somehow don't automatically generate the images to your build folder, like the queries do in the templates or pages folders. I ended up reusing the 400 size images I used in my blog-list.
  • In the serialize portion each rss item gets rendered, there are two custom elements defined. one for the HTML content and one for the aforementioned image.

If you finished setting up this configuration you can follow the mailchimp guide for setting up RSS based newsletters 💪

I ended up with the something like the following plugin code in the gatsby-config.js:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-feed`,
      options: {
        setup: options => ({
          ...options,
          custom_namespaces: {
            media: 'https://www.rssboard.org/media-rss',
          },
        }),
        query: `
          {
            site {
              siteMetadata {
                title
                description
                siteUrl
                site_url: siteUrl
              }
            }
          }
        `,
        feeds: [
          {
            serialize: ({ query: { site, allMarkdownRemark } }) => {
              return allMarkdownRemark.edges.map(edge => {
                const featuredImage = edge.node.frontmatter.img

                return Object.assign({}, edge.node.frontmatter, {
                  description: edge.node.excerpt,
                  date: edge.node.frontmatter.date,
                  url: site.siteMetadata.siteUrl + edge.node.fields.slug,
                  guid: site.siteMetadata.siteUrl + edge.node.fields.slug,
                  custom_elements: [
                    { 'content:encoded': edge.node.html },
                    featuredImage && {
                      'media:content': {
                        _attr: {
                          url:
                            site.siteMetadata.siteUrl +
                            featuredImage.childImageSharp.fluid.src,
                          medium: 'image',
                        },
                      },
                    },
                  ],
                })
              })
            },
            query: `
              {
                allMarkdownRemark(
                  sort: { order: DESC, fields: [frontmatter___date] },
                ) {
                  edges {
                    node {
                      excerpt
                      html
                      fields { slug }
                      frontmatter {
                        title
                        date
                        img {
                            childImageSharp {
                                fluid(maxWidth: 400) {
                                    aspectRatio
                                    base64
                                    sizes
                                    src
                                    srcSet
                                }
                            }
                        }
                      }
                    }
                  }
                }
              }
            `,
            output: '/rss.xml',
            title: 'RSS Feed',
            match: '^/blog/',
          },
        ],
      },
    },
  ],
}