Tags in Jekyll: the setup
Jekyll is a popular blog engine that allows you to create static websites with markdown files. One of the features that Jekyll offers is the ability to tag your posts with keywords that describe their content. Tags are useful for a blog because they help you organize your posts, make them easier to find, and improve your SEO. In this post, I will show you how to use tags in Jekyll and how to create a tags page and a tags feed for your blog.
Jekyll has support for tags and categories, however using the Tag functionality comes with certain gotcha’s if you want to maintain Github Pages compatibility.
The goals are
- smoother discovery of related content
- a visual overview of top tags
- The ability to add some extra content to my tags pages.
This is the first post in a series on Tags in Jekyll, check Tags in Jekyll: Word Cloud and Tags in Jekyll: related posts.
Defining Tags
At the top of your posts
page, you can definte them. The tags for this post are defined in the front matter:
1
2
3
4
5
6
7
8
---
layout: post
title: "Tags in Jekyll: the setup"
tags:
- Web Development
- Jekyll
---
Creating Tag pages
There are 2 main approaches, one using the pattex/jekyll-tagging plugin. The other one using a collections. I recommend on reading Jekyll Collections. The second approach has the advantage of being Jekyll native.
In _config.yml
create a new collection post_tags
and some defaults, and a corresponding _post_tags
folder.
1
2
3
4
5
6
7
8
9
10
11
12
collections:
post_tags:
permalink: /tags/:name/
output: true
defaults:
- scope:
path: ''
type: post_tags
values:
permalink: "/tags/:name/"
layout: tag
The disadvantage of this model, is having to create a file for each tag in the _post_tags
folder. To know which ones are missing I have this small _site_tags_missing.txt
file I generate. It will loop over all the found site.tags
and see if there is a post_tag
with the corresponding title
(which also means my tag name can be different then the url).
Content for a tag page
1
2
3
4
5
6
7
8
9
10
11
12
---
permalink: /_site_tags_missing.txt
---
{% if jekyll.environment != 'production' %}
{%- assign post_tags = site.post_tags | map: "title" -%}
{%- for tag in site.tags -%}
{%- if post_tags contains tag[0] -%}
{% else %}
{{ tag[0] }}
{%- endif -%}
{%- endfor -%}
{% endif %}
Inside the _post_tags
folder I have a series of files, one for each tag
. The filename will become the /tags/FILENAME
url, and the title
attribute the name. This allows the #Web Development
tag to become /tags/webdev/
. Any content is rendered on the tag page.
1
2
3
4
---
title: Home Assistant
---
[Home Assistant](https://www.home-assistant.io/) is a versatile and open source platform that lets you control your home devices and services. It works great with [#Zigbee]({% include tag_url tag="Zigbee" %}) on [#NixOS]({% include tag_url tag="NixOS" %}).
A layout for the tag pages
Let’s start styling the layout of the individual tag page. I want to give an overview of all the posts tagged. I created a custom tag.html
layout in the _layouts
folder.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
---
layout: base
---
<article class="post">
<header class="post-header">
<h1 class="post-title">{{ page.title | escape }}</h1>
</header>
<div class="post-content">
{{ content }}
{% assign tag = page.title | sluggify %}
{% assign tag_posts = site.tags[tag] %}
<ul class="post-list">
{% for post in tag_posts %}
<li>
{% assign date_format = site.minima.date_format | default: "%b %-d, %Y" %}
<span class="post-meta">
{{ post.date | date: date_format }}
{%- if post.tags -%}
<span class="tags">
{% for tag in post.tags %}
{% if tag == page.title %}
{% else %}
<a href="{% include tag_url tag=tag %}">#{{ tag }}</a>
{% endif %}
{% endfor %}
</span>
{%- endif -%}
</span>
<h4>
<a href="{{ post.url | relative_url }}">{{ post.title | escape }}</a>
</h4>
</li>
{% endfor %}
</ul>
Browse more <a href="/tags">tags</a>.
</div>
</article>
An example of this can be viewed at /tags/ai. In the posts overview I also want to highlight the other tags for the particular post, this is accomplished line 22-26
. I’m using a little helper include, _includes/tag_url
to make sure I link to an existing post_tag
(and fallback to /tags
if not).
1
2
3
4
5
6
7
8
{%- capture url -%}
{% for pt in site.post_tags %}
{% if pt.title == include.tag %}
{{ pt.url | relative_url }}
{% endif %}
{% endfor %}
{%- endcapture -%}
{{ url | strip | default: "/tags/" | relative_url}}
Linking to the tags
Before (or after) the title, as part of the post-meta
I added following code.
1
2
3
4
5
6
7
8
9
10
11
{% assign date_format = site.minima.date_format | default: "%b %-d, %Y" %}
<span class="post-meta">
<span class="date">{{ post.date | date: date_format }}</span>
{%- if post.tags -%}
<span class="tags">
{% for tag in post.tags %}
<a href="{% include tag_url tag=tag %}">#{{ tag }}</a>
{% endfor %}
</span>
{%- endif -%}
</span>
Conclusion
Having a pure Jekyll & liquid version is possible, but takes some efforts and head scratching. Especially how liquid filters work. I recommend you to read the Liquid Docs before starting. This blog is fully on GitHub, so take a peak.