:books: A While Ago I Learned

How to generate and enrich pages in a Jekyll blog

programming Jekyll jekyll Ruby ruby

This site is made with Jekyll, a blog-aware static site generator written in Ruby.

Jekyll takes the Markdown files in a directory and turns them into HTML pages. You can attach structured data to these pages like tags, categories and whatever you want using YAML frontmatter. For example, this could be a Markdown file representing a blog post:

---
layout: post
title: Blogging Like a Hacker
tags: blog hack jekyll
---

Hello, World!

This is pretty cool and simple to use, but I needed more for this blog. I wanted to generate pages dynamically that are not based on existing Markdown files. And I also wanted to generate data that would be bothersome to hardcode into frontmatter.

All of this can be done with generators.

Enriching existing pages

Here’s a simple generator which dynamically adds frontmatter data to every post in your blog:

module AddTagsCountPlugin
  class Generator < Jekyll::Generator
    def generate(site)
      # Iterate over each post (Markdown files
      # in the `_posts` directory).
      site.posts.docs.each do |post|
        # Add a property to each post that indicates
        # the number of tags.
        post.data['tags_count'] =
          post.data.fetch('tags', []).length
      end
    end
  end
end

This blog uses a generator plugin to enrich the frontmatter data of its posts. It does things like attach logos to post tags and automatically deduce additional tags based on other frontmatter data.

Generating new pages

Here’s a simple generator which adds an entirely custom page to your blog, without needing a corresponding Markdown file:

module AddCustomPagePlugin
  class CustomGenerator < Jekyll::Generator
    def generate(site)
      site.pages << CustomPage.new(site: site)
    end
  end

  class CustomPage < Jekyll::Page
    def initialize(site:)
      @site = site

      # Path to the source directory.
      @base = site.source

      # Directory the page will reside in.
      @dir = 'posts'

      # All pages have the same filename.
      @basename = 'index'
      @ext = '.html'
      @name = 'index.html'

      # Define any custom data you want.
      @data = {
        'layout' => 'page',
        'custom' => 'data',
        # Get data from wherever you need.
        'whatever' => File.read('~/whatever.txt')
      }
    end
  end
end

You could of course generate as many pages as you want with this, based on whatever data source.

This blog uses a generator plugin to create its /posts page. It groups posts into custom categories to display the featured columns in the page, then the rest of the posts underneath.

Another example

I first learned to use generators a while ago in 2016. While working for the Media Engineering Institute, I used Jekyll to make a website that hosts psychiatry-related videos.

It was interesting to make because unlike your usual Jekyll site, it does not contain a single Markdown file. All pages are generated by this plugin using this YAML data file, making this a good example of a truly custom Jekyll site.