General website setup

The most basic structure required is as follows:

$ tree $PROJECT_ROOT
website
├── Gemfile
├── _config.yml
├── _posts
│   └── 2019-01-01-post.md
└── index.md

Here’s a basic _config.yml:

$ cat _config.yml
title: "Website"
email: "user@email.com"

markdown: kramdown
theme: minima

Technically, the Gemfile is only required to compile and run locally. Github does not require the Gemfile to be part of the git repository. Here’s a basic Gemfile:

$ cat Gemfile
source "https://rubygems.org"

gem "minima"

gem "github-pages", group: :jekyll_plugins

Post file format

Jekyll can automatically detect and generate html for new files added in the _posts subdirectory. The post file name and contents need to be in a specific format for this to work.

  1. File name must be of the format: YYYY-MM-DD-some-name.[md|markdown].

  2. The post file must have a front matter at the top.

Overriding the default theme layouts

Create a directory called _layouts in the $PROJECT_ROOT and add your own templates (*.html files). Any templates here will override the theme defaults. New templates can also be added to the same directory. Here’s an example:

$ tree $PROJECT_ROOT
website
├── Gemfile
├── _config.yml
├── _layouts
│   └── post.html
│   └── projpage.html
├── _posts
│   └── 2019-01-01-post.md
└── index.md

A page can inherit from any of the globally or locally available layouts.

Setting up tags

It seems like most of the articles online are either outdated or incorrect.

The clean and idiomatic way of accessing all the tags is as follows:

{% for tag in site.tags %}
{% endfor %}

Here, each tag is a two-tuple: tag[0] refers to the tag name; and tag[1] refers to a list of posts with the given tag.

So, to iterate over all tags and all posts for each tag, one can do something like:

{% for tag in site.tags %}
  <ul>
    <li>
      {{ tag[0] }}
      <ul>
        {% for post in tag[1] %}
          <li> {{ post.title }} </li>
        {% endfor %}
      </ul>
    </li>
  <ul>
{% endfor %}

There’s no way for Jekyll to generate the tag-specific pages (a page per tag) automatically. One would need to go outside the framework and write a wrapper script (e.g., using Python) to generate the tag-specific pages.

A workaround, I figured, is to put a list of all the tags (and their corresponding posts) in a single page and create hyperlinks to the tag anchor from the post page. See the example code here and here. Here’s a cleaner example:

For the single page with all the tags:

{% for tag in site.tags %}
  <ul>
    <li id="{{ tag[0] }}">
      {{ tag[0] }}
      <ul>
        {% for post in tag[1] %}
          <li> {{ post.title }} </li>
        {% endfor %}
      </ul>
    </li>
  <ul>
{% endfor %}

For the post page:

{% for tag in page.tags %}
  <a href="/tags.html#{{ tag }}">{{ tag }}</a>
{% endfor %}

Writing Liquid code in Posts with Jekyll

See here. (This post also uses the workarounds mentioned on the above linked page.)

Jekyll with VSCode

I ended up developing a small VSCode extension, jekyll-post, to ease some of the pain of creating new posts using VSCode.

There aren’t that many extensions for VSCode that can automatically create a new Jekyll website and help manage the website (build, deploy, etc). There’s definitely room for a new extension here.