Adding Related Articles with Astro Content Collections
8 min readAstro's content collection feature is a game changer for easily managing content in a type safe manner. It also can help to easily add related collections or data types through referencing. In this article I show how I implemented a related articles feature.
Introduction
In the past iterations of my blog I have implemented a “related posts” feature. To say the least it was not exactly a fun experience. Normally it would entail finding posts with similar tags, creating a list of those posts, removing duplicates, and finally boiling down the list to to most current posts. The previous solution can be found here. Astro provides a pretty handy way to reference existing collections or data types in other schemas using the reference
helper. Albeit this is great for creating the contract that represents what one expects it doesn’t go as far as I had hoped it would so there was some hacking to be done!
Updating the Schema
First up I needed to update the articleSchema
adding the relatedArticles
property. I wanted this contract to be required at all times so in the event there is not any related articles the field will be initialized with and empty array.
Updating existing articles
With the schema updated firing up Astro will lead to many a error messages about the existing articles not matching the new schema definitions. That means going through each article and manually updating them as seen below:
Adding the Related Articles to the UI
The Problem
So doing this easily adds the relatedArticles
feature to the schema and Astro will send me a nasty gram if that is not present in the frontmatter of each article. That’s great and all; but I will have to manually add related articles to that property. So what happens six months from now when I write an article that should be related to the From NextJS to Astro article? I have to remember to update all articles that should have the new article associated with it. I don’t know about you, but I barely remember what I ate for breakfast so that’s a tall order!
Thus it is time to do what all great developers do…
Spend hours automating what could manually be done in 45 minutes because future me doesn’t want to do that.
Automating the Related Articles
I don’t want to have to think past running a command in the future so scripting it is! I honestly haven’t written many scripts in a while. This made things a little challenging but fun. Actually solving a problem I have with code…isn’t that why I got into this? Oh how far I hath fallen with thee React 😢
The gist of the code below is as follows:
- Find where all the files are
- Loop over the files & read them one by one
- Loop over the files yet again to get reference to other files
- Check if the currentFile has tags that are included in the otherFile and if so push the slug of the otherFile onto an array for tracking related files.
- Stash that array of related files onto the currentFile’s frontmatter
- And write the content back to the file in the correct format.
I brought in
chalk
to make things look real purty like.
Hell yeah boys! That is one sexy script and clearly a frontend developer made that terminal output. Winning awards with UI like that!
Adding Related Articles to the Plop Generator
Not gonna lie honestly I could be done. I mean that’s a pretty solid script; however what about when I am using the PlopJS generator for creating a new article? I already load the tags
into the prompts so I can select from present tags…could I populate the related articles on generation?
You bet your sweet ass I can!
Wrap Up
This turned out to be a really fun feature write and will be a lot more convenient to manage in the future with the relatedArticles.mjs
script. I have plans to bring back my older articles in an archived state in the future and this script will make adding all those articles to the relational graph so much easier.
I am interested to see as the number of articles grow how much time the script begins to take. There are three nested loops in this script so it’s not exactly performant by any stretch. How’s that saying go?
Make it right. Make it work. Make it fast.
I am somewhere between right and work…bugs will be found…in production! I might write an article in the future about performance tuning the script or hell I might even just take a stab at rewriting the script in Go! I mean performance win by switching languages FTW!
Related Articles
Going to the Gopher Side
The chaos that is the JavaScript/TypeScript ecosystem has become too much to bear in my opinion. I have become unhappy with my direction in the tech industry and in late 2023 made the decision to begin teaching myself Go and pivoting my career out of the Frontend & away from JavaScript.
From NextJS to Astro
In 2023 I began making the move from NextJS to Astro for my personal website and blog. This is my experience with the transition.
Deploying Astro to Fly: Part 2
A quick how-to guide on deploying your server-side rendered Astro projects to Fly.io.
Deploying Astro to Fly: Part 1
A quick how-to guide on deploying your static Astro projects to Fly.io.
Building A React Project From Scratch With TypeScript
Setting up a React project with Webpack 4, Babel 7, & TypeScript.
Cody is a Christian, USN Veteran, Jayhawk, and an American expat living outside of Bogotá, Colombia. He is currently looking for new opportunities in the tech industry.