Another day, another tweak I’m making to my blog. Today’s task, alongside sorting out the navigation to display better, was adding some content to my Posts page. On my old blog, this page listed all the tags I have and a few examples of the posts found in them, so I set about doing exactly that.
After attempting to write my own code to pull out the latest five posts from a specific tag, I stumbled across Max Böck Github repo with an example of how to display webmentions. This filter allowed passing a collection to it and also customizing the number of posts to display. The filter is as follows:
// Get the first n elements of a collection.
eleventyConfig.addFilter('head', (array, n) => {
if (n < 0) {
return array.slice(n)
}
return array.slice(0, n)
})
This made my job much easier, and the filter could potentially be reusable in other situations. For the time being, I chose to display the three most-used tags until I can clean up my imported posts from my old blog and integrate others than using for. As an example, to show the first 5 posts in my Reviews Collection, I use {% raw %}{% for post in collections.Review | head(-5) %}{% endraw %}
.
I use head(-5)
in the filter to get the latest 5 posts, whereas head(5)
would get the first 5 from the collection, i.e., the oldest posts. Once I have cleaned up my posts, I plan to display all collections here and make the code cleaner rather than repeating it three times. But as a stopgap while I do this, I am pretty happy with how it turned out.
James Somers encouraging more people to write:
More people should do what I’m doing right now. They should sit at their computers and bat the cursor around — write full sentences about themselves and the things they care about.
This is an old post, and reminiscent of many newer versions I have linked to but it captures what I experience perfectly. When I am motivated to write, and that doesn’t come easily, the world seems different. As James says about himself — I feel curious about things, with a desire to form thoughts and ideas about myself.
It doesn’t need to be great writing, I mean look at the state of my posts, you just need to do it. Let me know the things you are doing and what you find interesting. Set free your inner weirdness and display your motivations. Just write and the world will be right.
Really early on a Sunday morning, and with sore legs from a long run the day before I took my Richo GRiiix out in Grantham to see what I could find. The answer was not a lot, but I loved the cold air but nice low sunshine. This is where my street photography excels.
One of the great things about making your own website is that you can build new things. One of the worst things about making your own website is that you keep building new things. After web mentions and a way to publish easily, the next thing on my list was a blogroll. Not just a page people can go to, but a way to surface the things I like to everyone who happens to visit my website.
Thankfully, this was easy, and I took inspiration from Chris Hannah’s blogroll on GitHub. Starting with creating two JSON files with information on the blogs I enjoy reading, and the products I like and would recommend to people.
After creating the files, I added an Eleventy filter to generate a random number in order to pick a blog and product at random for each place this would appear. It was important to me that it cycle through as many as possible, but it was not browser-intensive, and my blog continued to serve static pages.
eleventyConfig.addFilter("randomItem", (arr) => {
arr.sort(() => {
return 0.5 - Math.random();
});
return arr.slice(0, 1);
});
return {
dir: {
input: "src",
output: "public",
},
};
Then I can show them wherever I wish using {% raw %}{% for blog in blogroll | randomItem %}{% endraw %}
. The best place for this is a partial, and at the moment it lies at the end of each blog post. However, I have plans to improve the design and be able to place it in more spaces.
I have a few things in the JSON files at the moment, but I have a feeling this will grow quickly
In keeping with my ways, as soon as I published my rather long-winded method of pulling in pseudo webmentions, I knew I wasn’t satisfied. Functioning is one thing, but seeing all the code on a page and having trouble following it myself gave me a headache. I began working on updates I had planned for a few weeks later.
I am now just using the Mastodon API to pull in all the information I want to display.
async function fetchAndUpdateUserPosts(instanceURL, accessToken, username) {
try {
const fetchedPosts = await fetchUserPosts(instanceURL, accessToken, username);
const filePath = `./_cache/mastodon_posts.json`;
// Check if the file exists
if (fs.existsSync(filePath)) {
// Read existing posts from file
const existingPosts = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
// Update or add new posts
fetchedPosts.forEach(newPost => {
const index = existingPosts.findIndex(oldPost => oldPost.id === newPost.id);
if (index !== -1) {
// Update existing post
existingPosts[index] = newPost;
} else {
// Add new post
existingPosts.push(newPost);
}
});
// Write updated posts back to the file
fs.writeFileSync(filePath, JSON.stringify(existingPosts, null, 2));
console.log(`Posts for user ${username} fetched and updated successfully.`);
} else {
// Write fetched posts to a new file
fs.writeFileSync(filePath, JSON.stringify(fetchedPosts, null, 2));
console.log(`Posts for user ${username} fetched and saved successfully.`);
}
} catch (error) {
console.error('Error:', error);
}
}
Full gist here.
For this, you will need an access token for the API, which is available in your settings - more info here. You will also need a username, which isn’t your actual username but more of an ID. More information on how to get this is available here.
The full script checks for changes to the cached file and only updates changes, which is handy for adding new comments, likes, or when you edit your post.
This method makes displaying the information much easier, as the old way was a complete mess. It illustrates the learning process here!
Now I just need {% raw %}{% set mastoContent = mastodon | searchContentForUrl(page.url | url | absoluteUrl(metadata.url)) %}{% endraw %}
so in my post I can then display the toot content, likes, boosts and a comment count. For instance my toot data is:
{% raw %}
<div><i class="fa-regular fa-star"></i> {{ mastoContent.favourites_count}}</div>
<div><i class="fa-regular fa-comment"></i> {{ mastoContent.replies_count}}</div>
<div><i class="fa-solid fa-rocket"></i> {{ mastoContent.reblogs_count}}</div>
{% endraw %}
This new approach, although much cleaner, disregards webmentions from any source other than Mastodon. I am still pulling these in but displaying them on a private dashboard in my CMS. My plans are to filter out Mastodon-related ones and display these on the post page as well. This will take me a while to figure out the best way to show them, and at this point, I will pull in all old data from my old blog.