Jekyll Bootstrap API

How it Works

The Bootstrap API takes advantage of Jekyll's ability to "include" files within other files. This allows us to package chunks of complex Liquid code into reusable modules that can be called throughout your templates, pages, and posts.

If you are familiar with ruby-on-rails this pattern is essentially the same as defining methods in a view helper module and invoking them in your views.

Define a new "method"

Jekyll-Bootstrap uses includes to emulate a ruby method. First encapsulate your liquid code logic in a Jekyll include file:

  • _includes
    • JB
      • tags_list
{% if site.JB.tags_list.provider == "custom" %}
  {% include custom/tags_list %}
{% else %}
  {% if tags_list.first[0] == null %}
    {% for tag in tags_list %} 
      <li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag }}-ref">{{ tag }} <span>{{ site.tags[tag].size }}</span></a></li>
    {% endfor %}
  {% else %}
    {% for tag in tags_list %}
      <li><a href="{{ BASE_PATH }}{{ site.JB.tags_path }}#{{ tag[0] }}-ref">{{ tag[0] }} <span>{{ tag[1].size }}</span></a></li>
    {% endfor %}
  {% endif %}
{% endif %}
{% assign tags_list = null %}

The example above is JB/tags_list which is a helper to list tags and their total counts.

In order to emulate passing arguments to the method, your include should reference localized variables whenever possible. Now we can pass in arguments by defining the local variables immediately before calling the include file.

Invoking the Method.

<ul>
  {% assign tags_list = site.tags %}
  {% include JB/tags_list %}
</ul>

You can define as many "arguments" as you want, just remember to nullify them all at the end of your include to preserve modularity.

Gotchas

In Liquid, it is impossible to inline assign a variable to anything other than a string. This means you can't pass in arrays, hashes, etc. However, as shown above, you can pass-by-reference, and assign local variables to variables that already exist.

So to pass in data-structures, you need to define them in your YAML Front Matter, or _config.yml file first, then pass them in by reference.

Contibuting

If you have a good idea for another helper, please follow the outlines above, then submit a pull request to Jekyll-Bootstrap and I'll include it.

Methods

JB/analytics

Includes analytics tracking code into your website.

{% include JB/analytics %}

By default, analytics are not loaded when in localhost (development). Analytics are loaded when site.safe is set to true. GitHub sets this flag so we treat a true setting as "production" mode.

This method should be used within a theme's default.html layout file. Configuration for this method is outlined at: Jekyll Configuration System

JB/categories_list

Provides a convenient way to list categories.

List Sitewide Categories

List site-wide categories by passing in the site.categories variable:

<ul>
  {% assign categories_list = site.categories %}
  {% include JB/categories_list %}
</ul>

List Categories for a Specific Post

You can also list categories specific to a post:

<ul>
  {% assign categories_list = page.categories %}
  {% include JB/categories_list %}
</ul>

List Categories Per Post Iteratively

Finally let's iterate through all posts:

{% for post in site.posts %}
  <h3>Categories for: {{ post.title }}</h3>
  <ul>
    {% assign categories_list = post.categories %}  
    {% include JB/categories_list %}
  </ul>
{% endfor %}

Source

./_includes/JB/categories_list

JB/comments

Includes a commenting system on blog post pages.

{% include JB/comments %}{% endcapture %}

Depending on your provider, comments may not always work when on localhost (development).

This method should be used within a theme's post.html layout file. Configuration for this method is outlined at: Jekyll Configuration System

JB/pages_list

Provides a convenient way to list pages.

List All Pages

<ul>
  {% assign pages_list = site.pages %}
  {% include JB/pages_list %}
</ul>

List Pages From a Sub-Group

Pages cannot have categories. However we can setup a similar functionality by manually associating a page to a "group". Do this in the page's yaml front matter:

---
layout: default
title: A Nice Title
group: project
---

You then pass the group name to the pages_list helper:

<ul>
  {% assign pages_list = site.pages %}
  {% assign group = 'project' %}
  {% include JB/pages_list %}
</ul>

Source

./_includes/JB/pages_list

JB/posts_collate

Organize and list posts in month/year clusters.

Collate All Posts in Reverse Chronological Order

By default all posts are organized in reverse-chronological order - newest to oldest.

{% assign posts_collate = site.posts %}
{% include JB/posts_collate %}

Collate a Sub-Set of Posts

To collate a sub-set of posts, just pass in the sub-set. Bellow, only posts tagged "jekyll" will be collated:

{% assign posts_collate = site.tags.jekyll %}
{% include JB/posts_collate %}

Source

./_includes/JB/posts_collate

JB/setup

Provides global Liquid variables to all layouts, posts, and pages.

{% include JB/setup %}

This is automatically included for you when you use rake post and rake page to create posts and pages.

The most relevant variables this sets is BASE_PATH which should be prepended to all post and page links, and ASSET_PATH which should be prepended to all theme-specific assets.

These paths dynamically change based on localhost vs production mode as a convenience to you.

JB/sharing

This is not finished yet =(

Includes sharing widgets on your blog post pages.

Examples include tweet, plusone, like, reddit, etc.

{% include JB/sharing %}

This should be specified within a theme's post.html layout file. Configuration for this method is outlined at: Jekyll Configuration System

JB/tags_list

Provides a list of tags and their total counts.

List Sitewide Tags

You can list sitewide tags by passing in the site.tags variable:

<ul>
  {% assign tags_list = site.tags %}
  {% include JB/tags_list %}
</ul>

List Tags for a Specific Post

You can also list tags specific to a post:

<ul>
  {% assign tags_list = page.tags %}
  {% include JB/tags_list %}
</ul>

List Tags Per Post Iteratively

Finally let's iterate through all posts:

{% for post in site.posts %}
  <h3>Tags for: {{post.title}}</h3>  
  <ul>
    {% assign tags_list = post.tags %}  
    {% include JB/tags_list %}
  </ul>
{% endfor %}

Source

./_includes/JB/tags_list

Method Overrides

All Jekyll-Bootstrap methods documented above can be overridden with a custom implementation. Editing Jekyll-Bootstrap files directly is not encouraged because it will make upgrading to the latest release more problematic.

Instead you can define another file with your own customizations. This is useful if you want to define an alternative HTML output syntax for things like tag and page lists. You also might want to override a comment provider with your own custom comment provider.

Usage

1. Set Configuration

Let Jekyll-Bootstrap know you want to override a method by updating your _config.yml file.

Within the JB hash you must define (if not already defined) a hash with the key as the name of the method you intend to override:

JB :
  tags_list :
    provider : "custom"

The above code tells Jekyll-Bootstrap that you want the tags_list provider to be custom.

2. Add custom file

Next you'll need to define a file at the path:

./_includes/custom/tags_list

This file, exactly as named, will be used in place of the source Jekyll-Bootstrap file. You'll probably want to copy the "meat" of the code logic from the original source file into your custom file and then edit it as needed.

You can follow this procedure for as many methods as you wish.