Enabling Tags In Jekyll on GitHub Pages
Editor’s note: the first time I published this article, Liquid, Jekyll’s templating engine, rendered the code in the example text. 😂 Be sure to escape your Liquid, all.
Perhaps the only downside to using GitHub Pages to host a Jekyll blog is that its whitelist of approved plugins is limited. It doesn’t support any Jekyll tagging plugins, so you have to roll your own. Jekyll’s flexibility makes this easy to complete.
1. Tag Your Posts
First, you have to have tagged your posts in the frontmatter.
---
title: "My Post"
date: 2025-05-18
tags:
- jekyll
- blogging
- how-to
---
Note that Obsidian (the notetaking software that I use to maintain my blog posts) uses YAML to store the tags.
If your editor of choice uses an array to store the tags, it may look slightly different.
---
title: "My Post"
date: 2025-05-18
tags: [jekyll, blogging, how-to]
---
This will be important later on as we will use RegEx to extract the tags from the posts as a part of our script.
2. Render Tags in your Post Template
This is optional, but if you want to display your tags on the posts themselves, you need to add this snippet to your _layouts/post.html
file.
``` {% if page.tags %} <ul class="post-tags"> {% for tag in page.tags %} <li><a href="/tags/{{ tag | slugify }}/">{{ tag }}</a></li> {% endfor %} </ul> {% endif %} ```
3. Add a Tags Page
This is the page where your tags will display. In the root of your site, add a tags.html
file with this content:
``` --- layout: default title: Tags --- <h1>Tags</h1> <ul> {% assign tags = site.tags %} {% for tag in tags %} <li> <a href="/tags/{{ tag[0] | slugify }}/">{{ tag[0] }} ({{ tag[1].size }})</a> </li> {% endfor %} </ul> ```
4. Create a Generate Tags Script
If your tags are stored in YAML, like mine are, here is the script:
#!/bin/bash
POSTS_DIR="_posts"
TAG_DIR="tags"
LAYOUT="tag"
PERMALINK_BASE="/tags"
mkdir -p "$TAG_DIR"
> .all_tags.tmp
# Extract tags from front matter
for FILE in "$POSTS_DIR"/*; do
in_frontmatter=false
in_tags=false
while IFS= read -r line; do
# Detect start/end of front matter
if [[ "$line" == "---" ]]; then
if $in_frontmatter; then
break
else
in_frontmatter=true
continue
fi
fi
# Parse tags
if $in_frontmatter; then
if [[ "$line" =~ ^tags: ]]; then
in_tags=true
continue
fi
if $in_tags; then
if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*(.+)$ ]]; then
tag="${BASH_REMATCH[1]}"
echo "$tag" >> .all_tags.tmp
elif [[ ! "$line" =~ ^[[:space:]]*- ]]; then
in_tags=false
fi
fi
fi
done < "$FILE"
done
# Generate unique, slugified tag pages
sort -u .all_tags.tmp | while read -r TAG; do
SLUG=$(echo "$TAG" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-+|-+$//g')
FILE="$TAG_DIR/$SLUG.md"
cat > "$FILE" <<EOF
---
layout: $LAYOUT
tag: $TAG
permalink: $PERMALINK_BASE/$SLUG/
---
EOF
echo "Generated: $FILE"
done
rm .all_tags.tmp
If your tags are in array, use this script instead.
#!/bin/bash
POSTS_DIR="_posts"
TAG_DIR="tags"
LAYOUT="tag"
PERMALINK_BASE="/tags"
mkdir -p "$TAG_DIR"
# Extract tags from all posts
TAGS=$(grep -h "^tags:" "$POSTS_DIR"/* | \
sed -e 's/^tags:[[:space:]]*//' -e 's/\[//;s/\]//' -e 's/,/ /g' | \
tr ' ' '\n' | sort -u | grep -v '^$')
# Generate one page per tag
for TAG in $TAGS; do
SLUG=$(echo "$TAG" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/^-+|-+$//g')
FILE="$TAG_DIR/$SLUG.md"
cat > "$FILE" <<EOF
---
layout: $LAYOUT
tag: $TAG
permalink: $PERMALINK_BASE/$SLUG/
---
EOF
echo "Generated: $FILE"
done
5. Make the Script Executable
Run this in your terminal.
# make the script executable
chmod +x generate_tags.sh
# run the script.
./generate_tags.sh
You should now see a folder called tags with a .md file for each of the tags in your frontmatter.
When you go to yoursite.com/tags
you will see a list of tags. Clicking on any of them will take you to yoursite.com/tags/tagname
with a list of links to tagged posts. And your posts will have a list of tags at the bottom. Very nice!
Bonus Points - Pre-Commit Hook
However, you don’t want to have to remember to run this manually before you commit, so set it to run in a pre-commit hook.
Create the hook and set it to be executable:
touch .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Add the code to the script:
#!/bin/bash
echo "Generating tag pages..."
./generate_tags.sh
# Optionally: add generated files to the commit
git add tags/
Now, every time you commit, git will run the script.
Created by Jim Smits, Researched with ChatGPT, Scripts by ChatGPT. For more information, please refer to AI Disclaimer.