Semi-automatic breadcrumbs for GitHub Pages

GitHub Pages is an excellent way to host a simple website. It uses a versatile static website generator: Jekyll. Unfortunately, GitHub Pages doesn't support all the features of Jekyll; in particular, it doesn't allow to use plugins, except a few whitelisted plugins. When a plugin is not available, you need to implement the feature manually.

That's what we are going to do in this article: add breadcrumb to a website, without any plugin.

Wheat Bread

Photo by Richard Revel from Pexels

As an example, here are the breadcrumbs for arduinojson.org/api/jsonarray/add/:

Breadcrumbs on arduinojson.org

The existing solutions

Several automatic solutions have been proposed.

The first solution works perfectly but uses a plugin so we cannot use it on GitHub Pages.

The second solution splits the URL and extracts the name from each segment. For example: /api/jsonarray/add/ produces the breadcrumbs "home / api / jsonarray / add". But there are two problems with this solution. First, it uses the URL to find the name of the crumbs, instead of the page title. The second problem is that it adds a crumb even if there is no page associated with it; for example, for the path /a/b/c/, it produces crumbs for a, b and c, even if /a/b/ is a 404.

The third solution scans all the pages from the site (using the variable site.pages) and finds the ones that match the URL of the current page. The problem with this solution is that it cannot work because the variable site.pages only contains the pages that have been generated so far. It may work occasionaly, but the vast majority of the time it doesn't.

A new solution

The solution that I present in this article has the following features:

  1. It doesn't need a plugin.
  2. It allows to customize the name of the crumb.
  3. It doesn't add a crumb if the page doesn't exist.
  4. It is dead simple!

But, it is not fully automatic, as we'll see.

Listing the possible paths

Because pages are generated in a random order, it is not possible to rely on site.pages to get the title of the page for a crumb.

Instead, we are going to create a list of candidates for crumbs. This list will contain all the possible crumbs for all pages. We'll store this list in _data/breadcrumbs.csv:

url,title  
/,Home
/api/,API
/api/jsonarray/,JsonArray
/api/jsonbuffer/,JsonBuffer
/api/jsonobject/,JsonObject
/api/jsonvariant/,JsonVariant
/doc/,Manual
/example/,Examples
/news/,News
/faq/,FAQ

For each crumb, we define two fields: the URL and the title. The URL allows matching the candidate crumb with the current page URL. The title is the text that will be displayed in the breadcrumbs.

The order of the lines in this file is important because it determines the order of the crumbs.

Display the breadcrumb

Thanks to the data file feature of Jekyll, the content of the file is available in the variable site.data.breadcrumbs.

Here is the code to generate the breadcrumb:

<ol class="breadcrumb">  
  {% for crumb in site.data.breadcrumbs %}
    {% assign url_prefix = page.url | slice: 0, crumb.url.size %}
    {% if (url_prefix == crumb.url) and (page.url != crumb.url) %}
      <li class="breadcrumb-item">
        <a href="{{ crumb.url | prepend: site.baseurl }}">
          {{ crumb.title }}
        </a>
      </li>
    {% endif %}
  {% endfor %}
  <li class="breadcrumb-item active">
    <a  href="{{ page.url | prepend: site.baseurl }}">
      {{ page.title }}
    </a>
  </li>
</ol>  

The code loops through all the candidate crumbs. For each crumb, it tries to match the crumb's URL with the beginning of the page's URL. If the crumb's URL matches, it adds it to the list. The last step adds the title of the page.

See it in action

I'm using this technique in arduinojson.org, you can find the source code on GitHub: