Integrating Gatsby with Medium
If you are using Gatsby for your main website or blog, and yet you write on Medium, you’ll probably want to make sure your website lists your Medium articles.
A bit of background
If you aren’t familiar with Gatsby, in a nutshell, it generates your website as static HTML, which is served fast and cached at the edge via Content Delivery Networks.
Please read my previous article for more details.
Bringing your Medium Articles into your Gatsby website
Your first thought maybe, “Medium must have an API. I’ll call that during the Gatsby build and add my articles to my website.”
Medium has (an old) API, but you can’t use it to read articles.
So what else is there?
Well, you can get an RSS feed of your articles. And, you can use a Gatsby plug-in to read that feed and turn them into data to generate your website.
Unfortunately, the Medium RSS feed only provides the ten most recent articles.
There are some great articles on Medium to help you achieve this.
And here’s another approach: exporting a backup of your Medium articles and generating your posts from that.
An Alternative Approach
The above approaches may have worked for those authors, but my requirements were slightly different:
- I don’t want to republish the Medium story on my blog and fall foul of Medium’s current duplicate content policy. I want to list the articles on my website and take the reader to the article on Medium.
- I want to use my tags to group articles on my website and not rely on Medium tags.
- I want to retain the ability to publish posts on my website, mixed in with Medium articles.
- When I publish an article on Medium, I don’t mind a little bit of manual curation effort on my website.
As you can see from the screenshot, I achieved this. The post summary and post image can be viewed on my website and use the website’s content tags. However, the body of the post directs the reader to view it on Medium.com.
The solution was surprisingly easy.
It’s a blog post; sort of
Using the Gatsby Starter Blog, you get a skeleton Gatsby website to publish your blog posts.
It reads markdown files from a blog folder and generates the HTML during the Gatsby build.
My solution was to create a content/medium
folder and place markdown files with the relevant frontmatter for the Medium articles.
---
title : Begin with the end in mind
description: It's time to redefine an agile manifesto statement and avoid a common pitfall when starting software development projects.
host: medium
date : "2021-12-27"
thumbnail : "Car Chassis Example.png"
url : https://medium.com/@gavgrayston/begin-with-the-end-in-mind-bc7c4f4c0566
tags : ["Agile", "Software Development", "Continuous Delivery"]
---
Step 1: Modify gatsby-config.js
Create the medium folder within the content folder, then modify the gatsby-config.js
file to read that file.
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/content/medium`,
name: `medium`,
},
},
...
Step 2: Modify gatsby-node.js
Next, edit the gatsby-node.js
file. This file configures the graphql query that reads in the posts.
Here we added a hosts field to the frontmatter.
type Frontmatter {
title: String
description: String
date: Date @dateformat
host: String
}
Step 3: Modify the blog-posts.js file
blog-posts.js
generates the HTML from the loaded posts from graphql.
Modify the graphql to load the additional fields, such as host, URL, and thumbnail. Note that gatsby will recognise that the thumbnail field is an image and process and convert the image file.
markdownRemark(id: { eq: $id }) {
id
excerpt(pruneLength: 160)
html
frontmatter {
title
date(formatString: "MMMM DD, YYYY")
description
host
url
tags
thumbnail {
childImageSharp {
gatsbyImageData
}
}
}
}
Next, we want to change the content of the blog post. If it is a blog post, we render the content as normal. However, if the post is hosted on Medium, we provide a button to view the article on the URL specified in the frontmatter. (Note the button component is via the Gatsby Material UI theme).
const isMedium = (post.frontmatter.host === 'medium');
let content;
if (isMedium) {
content =
<section>
<p>This article is published on <a href={post.frontmatter.url} target='_blank'
rel="noreferrer">Medium.com</a></p>
<p><Button variant="contained" href={post.frontmatter.url} target='_blank' rel="noreferrer">Read on
Medium.com</Button></p>
</section>
} else {
content =
<section
dangerouslySetInnerHTML={{__html: post.html}}
itemProp="articleBody"
/>
}
And here is how to load the post image thumbnail from the frontmatter.
const postImage = getImage(post.frontmatter.thumbnail)...
...
<GatsbyImage
image={postImage}
layout="fixed"
formats={["auto", "webp", "avif"]}
src={post.frontmatter.thumbnail}
quality={95}
alt={post.frontmatter.title}
/>
Further Development
You can, of course, then go on to create a post list component, loading the data and a smaller thumbnail image.
Tip: If you want to load a smaller sized image of the thumbnail, simply specify this in the graphql query.
frontmatter {
date(formatString: "MMMM DD, YYYY")
title
description
host
url
tags
thumbnail {
childImageSharp {
gatsbyImageData(width: 280)
}
}
}