Adding tags for indexing webpages with Jekyll

10 Apr 2019 - tsp
Last update 14 Jan 2021
Reading time 2 mins

The following is a description on how to add tags (as an index method) to your statically generated Jekyll page.

Note that this only works if you can guarantee there are no special characters in your tag names. Because of this - this is just a hackish way to solve the tagging problem. It also doesn’t scale that way. If you have a really large project or a project where you cannot trust your input data - you should use a different method.

The basid idea is to add a list of tags to the YAML frontmatter:

- Tag 1
- Tag 2

A small shellscript iterates over all markdown files in your project structure excluding the tags directory and generates a list of all articles for each tag it encounters - and an tag index as well. These generated lists are markdown documents themselves and get translated by Jekyll during the build run.


if [ $# -eq 0 ]; then
        # First clean up
        rm -rf tags
        mkdir -p ./tags

        # Build index
        find ./ -name "*.md" -exec ./ {} \; -path ./tags -prune
	# Index a given file

        echo "Indexing ${1}"

        cat ${1} | while read -r LINE; do
                if [ ${CUTSTATE} -eq 0 ]; then
                        if echo "${LINE}" | grep -q 'title:'; then
                                CURTITLE=`echo "${LINE}" | sed 's#title:##g'`
                        if [ "${LINE}" = "tags:" ]; then
                elif [ ${CUTSTATE} -eq 1 ]; then
                        if [ "${LINE}" = "---" ]; then
                                TAGNAME=`echo ${LINE} | tr -d '-'`
                                TAGFNAME=`echo ${TAGNAME} | tr -d ' ' | tr '[:upper:]' '[:lower:]'`

                                if [ ! -e ./tags/${TAGFNAME}.md ]; then
                                        # Create tag file
                                        echo "---" > ./tags/${TAGFNAME}.md
                                        echo "layout: tagspage" >> ./tags/${TAGFNAME}.md
                                        echo "title: Tag ${TAGNAME}" >> ./tags/${TAGFNAME}.md
                                        echo "description: All articles and posts tagged with ${TAGNAME}" >> ./tags/${TAGFNAME}.md
                                        echo "tagname: ${TAGNAME}"  >> ./tags/${TAGFNAME}.md
                                        echo "---" >> ./tags/${TAGFNAME}.md
                                        #echo "${TAGNAME}" > ./tags/${TAGFNAME}.md

                                        if [ ! -e ./tags/ ]; then
                                                echo "---" > ./tags/
                                                echo "layout: tagspage" >> ./tags/
                                                echo "title: List of all known tags" >> ./tags/
                                                echo "description: A list of all known tags on the page" >> ./tags/
                                                echo "---" >> ./tags/
                                        echo "* [${TAGNAME}](/tags/${TAGFNAME}.html)" >> ./tags/

                                if echo "${1}" | grep -q '_posts'; then
                                        TAGLINK=`echo ${1} | sed 's#./_posts/#/#g' | tr '-' '/' | sed ''`
                                        TAGLINK=`echo ${1} | sed 's#./#/#g' | sed ''`

                                echo "* [${CURTITLE}](${TAGLINK})" >> ./tags/${TAGFNAME}.md
        return 1

This script uses a single layout file _layouts/tagspage.html. This layouts file may look like the following script (this is the one used on this page at the time of writing this note):

layout: default

<div class="articleheader">
	{% if page.tagname %}
	<h1>All articles and pages tagged <em>{{page.tagname}}</em></h1>
	{% else %}
	<h1> All known tags </h1>
	{% endif %}

{{content }}

This article is tagged:

Data protection policy

Dipl.-Ing. Thomas Spielauer, Wien (

This webpage is also available via TOR at http://rh6v563nt2dnxd5h2vhhqkudmyvjaevgiv77c62xflas52d5omtkxuid.onion/

Valid HTML 4.01 Strict Powered by FreeBSD IPv6 support