Add dynamic post tag pages
Apr 3, 2024I want a way for users to be able to find posts based on topic. To do this, I used a dynamic tag page.
I can add tags to the front matter at the top of each post, something like:
layout: main.njk
title: Add dynamic post tag pages
tags:
- post
- 11ty
I then took the examples from the official 11ty site and modified them slightly to use my pre-existnig templates, and to pare down the features a bit. I now have two new pages: tags.md
and tags-list.md
.
Tags.md looks like this:
---
pagination:
data: collections
size: 1
alias: tag
filter:
- all
- post
- posts
- tagList
addAllPagesToCollections: true
layout: collection.njk
eleventyComputed:
title: Tagged “{{ tag }}”
permalink: /tags/{{ tag | slugify }}/
---
{% set postslist = collections[ tag ] %}
{% for post in postslist | reverse %}
<li>
<a href="{{ post.url }}">{{ post.data.title }}</a>
- {{ post.date | postDate }}
</li>
{% endfor %}
<p>See <a href="/tags/">all tags</a>.</p>
Related, I found how to display code in blocks without having to remove curly braces by using %raw%
and %endraw%
tags. Neat! Thanks to this blog post.
Anyways, the code for the tags listing is very similar to the code for my post list page. In fact, I could easily make the overall post list into a special case of tag listing, but that's not important to me right now.
This generates pages like /tags/11ty/index.html
, but it doesn'ts do just /tags/
. Instead, that's handled by tags-list.md
, here:
---
layout: collection.njk
permalink: /tags/
title: Tags
---
<ul>
{% for tag in collections.all | getAllTags | filterTagList %}
{% set tagUrl %}/tags/{{ tag | slugify }}/{% endset %}
<li><a href="{{ tagUrl }}" class="post-tag">{{ tag }}</a></li>
{% endfor %}
</ul>
I then went back and added tags to each of my old posts, and added a navigation tag to the tags index page, as described in my navbar post.
This also involved a few new filters, shamelessly stolen from the 11ty starter blog project:
eleventyConfig.addFilter("getAllTags", collection => {
let tagSet = new Set();
for(let item of collection) {
(item.data.tags || []).forEach(tag => tagSet.add(tag));
}
return Array.from(tagSet);
});
eleventyConfig.addFilter("filterTagList", function filterTagList(tags) {
return (tags || []).filter(tag => ["all", "nav", "post", "posts"].indexOf(tag) === -1);
});