Setting up Jekyll - related posts and series

By default, the related_posts feature of Jekyll returns the newest 10 posts rather than related posts. This is to speed up generation of the site by not using it's Latent Semantic Indexing (LSI) capabilities implemented by classifier-reborn since that takes quite a while to run.

To use LSI, you need to add the --lsi flag. Out of the box, it takes an incredibly long time to run. On my tiny blog, it took over an hour to complete the build process with LSI included. We're in luck however - installing GSL and the rb-gsl gem speeds up the process significantly (down to less than a minute for my blog). Advice from the rb-gsl gem after installation is that you could install the nmatrix and narray gems as well, but this has to be done before rb-gsl installation.

I've found that adding the nmatrix and narray gems to your Gemfile causes runtime dependency issues (specifically, duplicate definitions of classes). To automate the process, I've added a separate Gemfile.preinstall with these gems included to aid in the automated deployment on my web server. You can do this by taking advantage of the --gemfile parameter to bundler:

bundle install --gemfile Gemfile.preinstall

To install rb-gsl, install gsl as well as the development libraries:

sudo apt-get install gsl-bin libgsl2 libgsl-dev

And then add the rb-gsl to your Gemfile and install it.

Note: You can also directly install from source:

tar -xvf gsl-latest.tar.gz
cd gsl*
sudo make install

In order to link to the library, you can add the following to your .bashrc (or .zshrc, whichever shell you are using):

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/

Now that we have installation completed we can use the related_posts property with confidence. Note that this property is not supported by GitHub pages, a common hosting platform, and by default contains the x most recent posts if the --lsi flag is not passed to the generator.

We'll start off with a simple list of related posts in the main post page, limiting it to three recommendations:

{% if site.related_posts.size > 0 %}
    {% for related in site.related_posts limit:3 %}
    <li><a href="{{related.url}}">{{ related.title }}</a></li>
    {% endfor %}
{% endif %}

The final result looks pretty accurate:

Related posts

Post series

Another thing that is missing is to automatically link a series of posts together. We can easily achieve this by adding a custom series variable in the front matter of a post. This variable will indicate the name of the series which we can find posts with and group them together. For lack of a better name we will call the variable series:

title:  "Setting up Jekyll - related posts and series"
tags: jekyll ruby blog
series: building-a-blog

The include for this looks something like the following:

{% if include.series %}
  <aside class="series">
    <h3>Choose your own adventure! This post is part of the series <strong>&quot;{{ include.series | replace: '-', ' '| capitalize }}&quot;</strong></h3>
    {% for post in site.posts reversed %}
      {% if post.series == include.series %}
        {% if post.url == include.url %}
          {{ post.title }} &lt;-- <strong>this post</strong>
        {% else %}
          <a href="{{ post.url }}">{{ post.title }}</a>
        {% endif %}
      {% endif %}
    {% endfor %}
{% endif %}
aside.series {
  border-color: #BABDB6;
  border-style: solid;
  border-width: 1px;
  padding: 5px 10px 5px 10px;
  margin: 5px 0px 5px 0px;

And the final result:

Series posts

Photo by on Unsplash