Otto Schnurr

iOS Software Engineer

Jekyll Notes

Most of this information comes directly from documentation at

  1. To learn Jekyll, first understand Liquid.
  2. To learn Liquid, first understand YAML.


When data is easy to view and understand, programming becomes a simpler task.

Where JSON is designed for portability, YAML is designed for readabilty.

“YAML Ain’t Markup Language” (abbreviated YAML) is a data serialization language designed to be human-friendly and work well with modern programming languages for common everyday tasks.

To achieve readability, YAML is more complex to parse than JSON. Consequently, YAML is able to cover JSON as a superset. Valid JSON is also valid YAML.


  • maps
  • sequences
  • scalars (strings and numbers)

YAML excels in working with those languages that are fundamentally built around the three basic primitives. These include the new wave of agile languages such as Perl, Python, PHP, Ruby, and JavaScript.


Colons map keys to values.

time: 20:03:20
name: John Doe

Dashes designate a sequence

# Comments start with a hash.
# Three dashes start a YAML document.
- John
- Jane

Sequences and maps may commingle.

   name: apple
   color: red
   name: banana
   color: yellow

   - apple
   - banana
   - carrot
   - onion

More YAML syntax here.


Liquid is a ruby implementation that parses markup embedded with template expressions.

<ul id="products">
  {% for product in products %}
      <h2>{{ }}</h2>
      Only {{ product.price | price }}
      {{ product.description | prettyprint | paragraph }}
  {% endfor %}

Once the templates are compiled, Liquid evaluates them with supplied parameters to “render” new markup as output.


Liquid offers two kinds of markup.

Output markup pipes content through filters:

    Hello {{ 'dave' | capitalize }}.

Tag markup applies control logic

{% if user %}
  Hello {{ }}.
{% endif %}

Building with Jekyll


Jekyll is a simple, blog aware, static site generator. It’s the engine behind GitHub Pages.

Unlike blog engines that use a database, Jekyll parses files from a directory structure to statically generate a website.

Jekyll at its core is a text transformation engine.

Consequently, source text for a Jekyll website can live in version control.

Jekyll parses meta data from source files using YAML. Liquid injects this data into template code for output.

Blog posts may be written as Markdown source files and then injected as {{ content }} into template code.


verified with: MacBook Pro (Mid 2014), OS X 10.11.6

Using these OS X instructions:

sudo gem update --system
xcode-select --install
sudo xcodebuild -license
brew install ruby
sudo gem install -n /usr/local/bin jekyll bundler
bundle update
bundle install

Local Blog

jekyll new myblog
cd myblog
bundle exec jekyll serve

Alternate Instructions

The steps outlined here seem to be specifically catered to the Mac.

Basic Commands

Compile current folder into _site/ directory:

jekyll build

Compile current folder into <destination> folder:

jekyll build --destination <destination>

Compile <source> folder into <destination>:

jekyll build --source <source> --destination <destination>

Watch the current folder. Automatically compile changes into _site/:

jekyll build --watch

_config.yml is considered “global” configuration. Changes there are not watched. Instead the executable must be restarted.

The destination folder is always cleaned on rebuilds. Don’t put anything there unless you add it to keep_files.

Source Structure

Taken directly from

├── _config.yml
├── _data
|   └── members.yml
├── _drafts
|   ├──
|   └──
├─(gem)─ _includes
|        ├── footer.html
|        └── header.html
├─(gem)─ _layouts
|        ├── default.html
|        └── post.html
├── _posts
|   ├──
|   └──
├─(gem)─ _sass
|        ├── _base.scss
|        └── _layout.scss
├── _site
├── .jekyll-metadata
  • _config.yml: Build configuration.
    • An alternative to loading up jekyll build with a bunch of command-line arguments.
  • _drafts/: Articles that are not published.

  • _includes/: Reusable code/content to share across pages and posts.
    • Invoked using liquid tag, e.g. {% include header.html %}
  • _layouts/: Contains templates for posts.
    • Chosen using the YAML front matter of each post.
    • A post is injected into a template using {{ content }}
  • _posts/: Where the articles live.
    • The filename convention for each article is specific: YEAR-MONTH-DAY-title.MARKUP
    • The resulting link for each article is configured using permalink
  • _data/: Data files that jekyll loads and makes available at build time.
    • Supported formats: .yml, .yaml, .json, .csv
    • Example: members.yml would be available as
  • _sass/: Contains Sass partials that compile into a main.css

  • _site/: The default destination targeted by jekyll build.
    • Any previous content in this directory is clobbered
      • Unless added to keep_files.
  • .jekyll-metadata: Private file for tracking incremental builds.

Any remaining files in the source directory are converted by jekyll if:

  • Then contain YAML front matter and …
  • They have an .html, .markdown, .md or .textile file extension.


Otherwise, files and folders in the source directory are copied into the target destination as is.


There are a variety of global options that can be specified either in _config.yml or as command-line arguments (or both).

  • source directory, destination directory
  • files to include or exclude
  • timezone, character encoding
  • drafts, future and unpublished posts
  • build environment
  • incremental and profile builds

You can also specify default values across specific areas of the site (for known and custom variables).

Here’s the complete list of default options that Jekyll runs with.

Content in Jekyll

YAML Front Matter

# The first line segment starts a YAML "document".
# In Jekyll, this document is known as "YAML front
# matter". It is the indicator to Jekyll that a file
# should get sent through the text engine.

# YAML front matter doesn't have to contain anything.
# However if it does, the information there becomes
# available to the the Jekyll build including this `page`
# containing the front matter.

title: Describing YAML Front Matter
custom_variable: custom values

# The second line segment ends the front matter.

All the stuff here is processed as `{{ content }}` in layout files.

Predefined front matter variables for all files: layout, permalink, published

Additional front matter variables for posts: date, category, tags. date helps give a post more precision if necessary for sorting different posts that occur on the same day.

Blog Posts

Add posts into the _posts/ directory with the format YEAR-MONTH-DAY-title.MARKDOWN.

Use post_url to refer to other posts in the site. This inoculates the link against changes in markup and permalink format.

Linking to Assets

You can use {{ site.url }} to innoculate against changes to the location of the blog (e.g. going from to

You can [get the PDF here]({{ site.url }}/assets/doc.pdf).

You don’t need to do this if you know the blog will always be at the root.

You can [get the PDF here](/assets/doc.pdf).

Access to Posts

All posts are available in site.posts.

A variety of post components are available including url, title and exerpts.

Static Pages

A static page (as opposed to a post) is content that is not date-based.

Place marked up files with front matter in the source directory or in subdirectories and those files will appear as HTML pages (in the same subdirectories) in the destination directory.

Static Files

Files that aren’t converted and just copied by Jekyll are collected in site.static_files. These files still have some Liquid properties: path, modified_time, name, basename, extname.

You can assign additional front matter to these files using defaults in _config.yml.



A collection (like posts and pages) is a namespace for a sequence of items. You can create custom collections (e.g. members, apidocs).

Declare the collection type in _config.yml:

    output: true
    permalink: /api/:path/:title:output_ext


  • May 21, 2017: Removed cruft.