Adding a Tagcloud to Nikola

There are quite a few tags on my site.

Whenever I write a new post, I tend to scan over the list of existing tags in order to check if there's an existing tag that I should be adding to the new post.

It can feel like quite hard work though: there are a lot of tags, and the lozenges are quite small and closely packed:.

Blurg, that's a dense chunk of tags

It also means that that page is probably fairly useless to visitors: short of doing a Ctrl + F on the page, you're unlikely to find what you're looking for (and that only works if you know exactly what you're looking for).

I decided the answer was to act like it's 2005 and rock a tag cloud.

This post describes the process I followed to add a tag cloud to my Nikola based site.


Existing plugins

There are already a couple of tagcloud plugins in Nikola's plugin repository

I looked at both, but decided I couldn't use tx3_tag_cloud because it requires jQuery.

The tagcloud plugin was almost perfect for my needs, but has one fairly significant drawback.

It writes it's output with the following structure

{"<tag>" : [
            <article count>, 
            <link to tag page>, 
            {posts: [ <list of posts using the tag> ],            
 "<tag 2>" : [
            <article count>, 
            <link to tag page>, 
            {posts: [ <list of posts using the tag> ],            
}

The inclusion of the post listing meant that the file ended up being quite large

$ ls -sh output/assets/js/tag_cloud_data.json 
376K output/assets/js/tag_cloud_data.json

When I quickly hacked at it to remove the listing, it shrunk considerably

$ ls -sh output/assets/js/tag_cloud_data.json 
28K output/assets/js/tag_cloud_data.json

I try to keep my site relatively light, so it seemed crazy to serve a file 12x bigger than necessary.

To address is, I created a quick fork of the plugin


Deployment

First, I installed a copy of the plugin

cd plugins
git clone https://github.com/bentasker/nikola_ssg_tagcloud_enhanced.git tagcloud_enhanced
cp -r tagcloud_enhanced/files/assets/ ../files/

Then, I had Nikola drop a copy of tags.tmpl into my theme

docker run --rm \
-ti -v $PWD:/nikola \
dragas/nikola:alpine nikola theme -c tags.tmpl

Within that file, there's a section which looks like this

    % if items:
        <h2>${messages("Tags")}</h2>
    % endif

I updated that to add a couple of div's and a javascript call

    % if items:
        <div id="tag-cloud-wrap"></div><div style="clear: both"></div>
        <script type="text/javascript">buildTagCloud(5);</script>
        <h2>${messages("Tags")}</h2>
    % endif

Then, at the bottom of the file I defined a block of items to be pushed into <head>

<%block name="extra_head">
  <script type="text/javascript" src="/assets/js/tagcloud.js"></script>
  <link rel="stylesheet" href="/assets/css/tagcloud.css" />
</%block>

Next, I added some configuration to conf.py

TAGCLOUD_ENHANCED_EXCLUDES = [
    'republished',
    'documentation',
    'blog',
    'freedom4all',
    'howto',
    'portfolio',
    'release notes',
    'releasenotes',
    'video',
    'videos.bentasker.co.uk'
]

TAGCLOUD_ENHANCED_MIN_ARTICLES = 4

This excludes a bunch of common (but not very informative) tags from the cloud and specified that a tag must have at least 4 posts linked to it to be considered.

Finally, I built the site

docker run --rm \
-ti -v $PWD:/nikola \
dragas/nikola:alpine nikola build

As a result, the Categories page now includes a tag cloud

First run at a tag cloud

There're still some room for improvemen, but it's immediately obvious which tags are used most often. Hopefully, it'll make navigation/exploration of my site easier for those looking for specific items.

The addition of the tag information JSON file also means that there's scope, in future, to perhaps add a "most common tags" module into pages too.