Jekyll Category and Tag Taxonomies for custom Collection

2 minute read

Update

As of August 2019, Jekyll 4.0 release will support natively category and tag for custom collection. This means the work-around is no longer necessary. However, this tutorial is left here in case anyone still need it. For instance, static-blog hosts support only older Jekyll version.

Overview

The main purpose of this category / tag iterator is to create an index page, or a taxonomy. Brief review about Collection will be mentioned, but at this point, you should be able to build, host your own site and understand basic functionality of layout, include and post folders.

Quick View of the result

  1. Tag Archive
  2. Category Archive

An alternative would be using the Ruby plugin jekyll-archives, although as mentioned earlier these additional / non-native plugin could be not supported depend on build on the server host.

Prerequisite

  • Define a custom Collection

In case you do not have a custom collection already, it can be quickly configured. In _config.xml, a custom collection of recipe is defined as below.

1
2
3
4
5
6
7
8
9
10
collections:
  category: recipe
    output: true

defaults:
  - scope:
      path: ""
      type: recipe
    values:
      layout: single
  • Usage in article YAML Front Matter

Once the configuration is defined, simply add it in your article. For example, this tutorial has the following tags defined in its Front Matter.

NOTE: YAML Front Matter is essentially everything inside the divider (3-dashes) at the beginning of your article.

1
2
3
4
---
categories: [Tutorial, Productivity]
tags: [Jekyll, Taxonomy]
---

Category Tag Iterator

It depends on your purpose to place the following code snippet in the correct place, bu typically this would be in file _layout/categories.html if you want to create an Index / Taxonomy page.

Collect all data from collection

  1. Assign variable thisCollection for your custom collection data
  2. Apply filter to keep only category
    • group_by: Re-group field data by their category
    • join, split: Order field data into an array with , delimeter
    • map: Keep only data belongs to site.categories i.e. our interested categories.

NOTE: The | is the pipe special character from Liquid syntax.

1
2
{% assign thisCollection = site.portfolio %}	
{% assign allCats =  thisCollection | map: 'categories' | join: ','  | split: ','  | group_by: category %}

Array for unique values

This stage is not necessary but recommended, if you’re doing indexer, it is best to count duplicated values and later display that Category only once.

1
2
3
4
5
{% capture category_array %}
  {% for eachCat in allCats %}
    {{ eachCat.name }}|
  {% endfor %}
{% endcapture %}

Iterate all categories

Now it is essentially a nested for-loop to match all of categories of the current article (post.categories) with the one collected earlier from all articles of a collection.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{% for eachCat in allCats %}
  {% for post in thisCollection %}
    
    {% if post.categories contains eachCat.name %}

      {% assign thisCat = eachCat.name | append: '|' %}

      {% if category_array contains thisCat %}
        <!-- Apply your code here to display the category list -->
      {% endif %}

      {% assign category_array = category_array | remove: thisCat %}
    {% endif %}

  {% endfor %}
{% endfor %}

Final implementation for this website.

Troubleshooting (Extra)

  • Custom Plugin Jekyll Hook

Another approach is writing your own plugin with the Jekyll.Hook method inspired from this StackOverflow Discussion.