UPDATE:

I was wrong. After read through Jekyll documentation(which I didn't), I found there is such a thing called Generator. I referenced to this doc and integrated with my current layout, now things are fully automated, ya!

Still you will need tags page to represent all the tags and generate a page for each tag referencing the steps I described below.


Original post

Manual

Eventually we need a bunch of pages that for each of such tag pages, contains a list of posts that have the tag. For example, this one.

Here is what we need:

1. A tag directory

Usually such page is <site.base_url>/tag/<tag_name>, let's create a directory named tag to hold tag pages.

2. Collect tags

As long as we add tags to our front matter, such tags can be found in site.tags

3. Specify a layout for such page

Adding a file as _layout/tag_page.html:

---
layout: default
---
<ul>
  {% for post in site.tags[page.tag] %}
  <li>
    <a href="{{ post.url }}">{{ post.title }}</a>
  </li>
  {% endfor %}
</ul>

4. A page to hold posts

Jekyll generates html from a given markdown file. For each of the tag, we create a <tag_name>.md, which will be used to generate a <tag_name>.html. For example, for tag python, we create a python.md using above layout

---
layout: tag_pages
title: "python"
tag: python
---

Now if we go to tag/python.html, we will see the list of posts that contains python tag.

5. Provide access to tag pages from post

Now we have pages for each tag, how to access such pages? We can have a page containing all the tags, or in each post, we display the tags associated with the post and link each tag to the tag page, as used on this site.

The way I implemented is to add a partial to override existing layout: _layout/post.html:

{% if page.tags %}
<span>
  {% assign sorted_tags = page.tags | sort %}
  {% for tag in sorted_tags %}
    <a href="/tag/{{ tag }}">{{ tag }}</a>
  {% endfor %}
</span>
{% endif %}

Problem

Jekyll doesn't have a way to maintain tags(at least I don't know).

Anytime we created a new tag, we need specify a tag.md/markdown file somewhere in our site directory. As Jekyll runs, it picks up the markdown file and created a page holding all the posts associated with that tag.

Semi-automated

I could see in future there will be some trouble for me to maintain all the tags, so I created a script to automate it.

The idea is super simple, I can use a python script to:

  1. Collect all the tags into a set
  2. Check current tag files, remove outdated tags, which are those tags not included in any of the posts
  3. Skip existing tags
  4. Create new tags

As I wrote this post, I used the script to generate the new tags. Now I'm happier.

The script is at this Gist.

Automate It More

There is still one step annoying: we need run this script to update our tags before pushing it to production.

The best way is to have a Gem handle it for we in Jekyll and have configs to tweak it. I will create one when have time but probably there is such a one already. Leave a comment if we know it!