Today I'm following up (heh, get it) on the series I started yesterday on interesting use cases for your Jamstack site's front matter. In yesterday's post, I described how to use front matter to define a list of "related posts" to a blog post. Today's post is a natural follow-up to that one and deals with... well follow-ups!
When I was describing the behavior of related posts in my demo yesterday, I mentioned that the "relationship" would be one way. So post A may be related to B and C, and we would render that, but it would not automatically create a relationship from B to A. As I said in the post, I can definitely see people disagreeing with that, but I had in mind a more natural way for an older post to be related to newer content, a follow-up.
Defining the Follow-Up
So unlike the previous post where I had to define an array in front matter, this time I'm going to use a simple key/value pair. Here's an example:
followup: /posts/beta/
As discussed in the last post, I need some way to link to another post and the URL seems like a natural fit. That was easy!
Displaying the Follow-Up
Now that I've got a way to define a follow-up, let's look at how to display it. As with the previous post, my example code uses a post
layout where I define how blog posts are rendered. Previous, the content above where the blog post would go was rather simple:
<h2>{{ title }}</h2>
<p><i>Published {{ date | dtFormat }}</i></p>
In my opinion, if I've written a follow-up to a post it should be noted on top, so I'm going to add it there:
<h2>{{ title }}</h2>
<p><i>Published {{ date | dtFormat }}</i></p>
{% if followup %}
{% assign followupPost = followup | getByURL: collections.posts %}
<p><strong>Followup:</strong> <a href="{{ followupPost.url }}">{{ followupPost.data.title }}</a></p>
{% endif %}
The change here is to simply check for the existence of the followup
data, and if so, display it. To get the post we'll call a new filter named getByURL
. Remember that we need to pass the actual data (the URL) as well as the collection of data to check.
Let's look at that code now.
eleventyConfig.addFilter("getByURL", function(url, posts) {
return posts.reduce((prev, p) => {
if(p.data.page.url === url) return p;
else return prev;
});
});
I got fancy and made use of reduce
to transform the array of posts to one object based on the URL. Nice and simple. Here's an example of it being rendered:
And that's it! Yes, this is a pretty trivial use of front matter, but as I said, I think it pairs well with the previous post. You can find the source code for this tip here: https://github.com/cfjedimaster/eleventy-demos/tree/master/funwithfrontmatter2
Extra Credit
Ok, if you want, you can stop reading now. In my original post, I mentioned how I wanted this series of posts to be Jamstack engine agnostic, but that I'd be using Eleventy as it's my favorite. I want to share a quick tip that's specific to Eleventy and this post.
If you remember from yesterday's post, I had an array of URLs pointing to related content. The filter to transform those URLs into an array of pages looked like so:
eleventyConfig.addFilter("getRelated", function(relatedPosts, posts) {
let related = [];
posts.forEach(p => {
if(relatedPosts.includes(p.data.page.url)) related.push(p);
});
return related;
});
In today's post, I'm doing similar logic, but for just one URL. One nice thing that Eleventy supports is the ability for one filter to call another, and that means I can rewrite the above logic (assuming I've got a site using both) to be a bit simpler:
eleventyConfig.addFilter("getRelated", function(relatedPosts, posts) {
return relatedPosts.map(p => eleventyConfig.getFilter('getByURL')(p, posts));
});
Now I simply map the passed-in array to an array of pages using the getByURL
filter. This example can be found in the same repository linked above.