Published on

Understanding Jekyll and GitHub Pages

Authors

In the midst of setting up this blog, I had spent some effort going through the documentation of Jekyll and GitHub Pages to understand how GitHub Pages worked together with Jekyll. I thought it would be a good idea to share my understanding so that someone may find it useful later.

Below are a few references that I found useful.

I assume that the reader is familiar with Git, GitHub and will not be covering instructions to add, commit and push code onto GitHub.

Jekyll, the static site generator

Jekyll is a static site generator implemented in Ruby. A static site refers to a website which consists of complete HTML files that are served directly on request. This means the contents on the website are completely contained in the HTML files. This is as opposed to a dynamic site where website contents are generated by a web application server on request.

Jekyll pre-builds HTML files with content from Markdown files. To do so, Jekyll has features such as HTML components, HTML layouts, CSS preprocessing, etc. The generated static site is completely contained in the _site folder in the Jekyll project and served from there.

GitHub Pages, the static site hosting service

GitHub Pages is the static site hosting service offered by GitHub. It serves any static page as long as the file is contained in the source directory. This directory can be the root directory in the master or gh-page branch or the docs directory in the master branch, depending on your configuration. You can specify this in the repository settings. The static pages do not necessary have to be generated by Jekyll.

GitHub Pages is also able to use Jekyll to generate static site from the source directory as long as it is properly configured as a Jekyll project and serve the generated static pages in the _site folder.

This is a source of confusion for me as it did not seem to make sense that the same directory used to serve static pages directly can also be used to generate static pages with Jekyll. It turns out, this is a feature of Jekyll. Any static file in the source directory is copied into the _site folder mentioned earlier without any processing and can be served directly from there. This also has the effect of preserving any relative links between static pages in the source directory, allowing linking between pages without modification.

From my understanding, when GitHub Pages is activated, a continuous deployment pipeline is set up in the source directory. This runs the jekyll build command to generate the static pages. The contents in the _site folder are then served on GitHub Pages. This pipeline is run on every push to the branch.

To serve up static files in the source directory directly without any processing by jekyll build, you may include an empty .nojekyll file.

Setting up Jekyll

There are instructions for installing Jekyll on the official documentation, hence I will not repeat them here. The components for setting up a Jekyll project is also succintly explained in the documentation. I will cover them briefly.

  • Ruby
    • Jekyll is implemented in Ruby programming language.
  • Gem
    • Ruby libraries are called gems and distributed on RubyGems. Gem is used to download and install these libraries. Jekyll is itself a gem. This is analagous to pip in Python.
  • Gemfile
    • This file contains the list of gems required for a Ruby project. For Jekyll, it is also used to manage Jekyll plugins. This is analagous to the requirements.txt file in Python.
  • Bundle
    • I understand this as the environment manager for Ruby, to ensure the right versions of gems are used. This is analagous to virtual environment in Python.

Setting up Jekyll for GitHub Pages

This is where information can get confusing. Jekyll is used to generate static site in general, not specifically for GitHub Pages. GitHub Pages uses a specific version of Jekyll and has limited whitelisted plugins.

You may see suggestions to fill up the Gemfile as follows.

# Gemfile
source "https://rubygems.org"

gem "jekyll"

group :jekyll_plugins do
  gem "jekyll-feed"
end

This allows specifying arbitrary versions of Jekyll and Jekyll plugins, which may not work with GitHub Pages. To ensure that your local environment works with GitHub Pages, you will have to install Jekyll with the github-page gem. The gem specifies the correct version of Jekyll and also includes a list of plugins installed in the GitHub Pages environment.

Please specify the Gemfile as follows.

# Gemfile
source "https://rubygems.org"

gem "github-pages", group: :jekyll_plugins

group :jekyll_plugins do
end

You may then run bundle update and bundle install to set up your environment. Run bundle exec jekyll new . --force to initialise the Jekyll project. You will have to modify the Gemfile again to revert it. Run bundle exec jekyll serve to build and serve the website locally for a preview. It should look similar to the Jekyll Minima theme website.

You may start working on your website from here.

GitHub Pages plugins

The github-pages gem specifies a list of plugins and their versions. Do take note that, according to the documentation and the source code of the gem, there are selected Jekyll plugins that are enabled, installed and whitelisted. Any plugins not included cannot be used for Jekyll on GitHub Pages, even if they work in your local environment, unless you set up your own continuous deployment process.

At the time of this writing, they are listed as follows.

  • Enabled by GitHub Pages and cannot be disabled
    • jekyll-coffeescript
    • jekyll-commonmark-ghpages
    • jekyll-default-layout
    • jekyll-gist
    • jekyll-github-metadata
    • jekyll-optional-front-matter
    • jekyll-paginate
    • jekyll-readme-index
    • jekyll-relative-links
    • jekyll-titles-from-headings
  • Installed by github-pages gem
    • jekyll-avatar
    • jekyll-feed
    • jekyll-mentions
    • jekyll-redirect-from
    • jekyll-remote-theme
    • jekyll-seo-tag
    • jekyll-sitemap
    • jemoji
  • Whitelisted in the source code of github-pages gem
    • jekyll-include-cache
    • jekyll-octicons

To ensure all whitelisted plugins are available for use in your Jekyll project, you may want to specify the Gemfile as follows.

# Gemfile
source "https://rubygems.org"

gem "github-pages", group: :jekyll_plugins

group :jekyll_plugins do
  gem "jekyll-include-cache"
  gem "jekyll-octicons"
end

Conclusion

I have covered my understanding of Jekyll, how Jekyll works on GitHub Pages and how to setup the Gemfile to facilitate local development and site preview. With this knowledge, I find that it will be easier for me to set up GitHub Pages for project documentation in the future.

Hope this benefits you too!

Update: below is my other post on Jekyll and GitHub Pages.

References