A lightweight tagging system for blogs

The system I describe in this post is for small blogs with an index page that lists all posts. It’s essentially a filter on this list of posts, but to the user it seems like he navigates separate pages with a list of posts for each tag, that is, these “virtual” tag pages have their own heading, you can link to them, and use the back and forward buttons in the browser as expected. The advantage is that you don’t need to generate a separate static page for each tag, and the user doesn’t need to load a new page for each tag, so jumping from one tag to another is fast.1

How does it work?

If you follow a link to a virtual tag page, you are directed to the home page with a query parameter indicating the tag. In this case, for example, the “today I learned” tag: /?tag=TIL. The home page has a JavaScript snippet that parses the query parameter and filters the list of blog posts according to the tag parameter.2 It also sets a heading that contains the tag.

Let’s assume you see another interesting tag on the filtered page. A click on this tag filters the whole list of posts again and you instantly get another virtual page without reload. If the URL with the query string is not identical to the current URL, a new history state is pushed. To go back to the starting point, you can use the browser’s back button. The JavaScript snippet on the home page listens to the popstate event and re-applies the filter as long as you keep jumping from tag to tag.

Some more details

Each list item on the home page links a post and has one or multiple tag elements. They serve two purposes:

  1. You can click them to navigate to the corresponding virtual tag page (filter the home page).
  2. They indicate to the filter that the list item is relevant for the given tag.

In my case, the home page is generated from a Markdown file and I set the tags in this file. To make my life easier, I defined a custom HTML element, so all I need to write is <zb-tag>TIL</zb-tag>. I don’t need to pre-define any tags, everything happens automatically. Of course, you could also generate your home page from your Markdown files and read the tags from their front matter. Then you don’t need a custom HTML element, just generate the necessary HTML.

If you’re interested in more details, feel free to read the source file of my home page.

Other tagging systems

Usually static site generators (SSGs) will add a separate page per tag that lists relevant posts, for example Hugo taxonomies. Since my SSG is a Makefile that calls Pandoc on modified files, generating such pages is inconvenient. The more tags you have, the more unnecessary overhead.

One limitation of my system is that it requires JavaScript. If you have a lot of visitors that block or disable JavaScript, this is not for you.


  1. There is a bit of overhead, however, if the user only jumps to a single tag from a page other than the home page, because the full list of posts is loaded even if only a few are displayed.↩︎

  2. Filtering means: iterate over all list items and set display: list-item if they contain the tag we filter for or display: none otherwise.↩︎