Simplifying and extending Jekyll CLI capabilities using Jtasks

When I started using Jekyll, serving a site was as simple as short jekyll serve command. After creating a few first posts I discovered drafts feature. Now serving a site command became jekyll serve --drafts. Then Jekyll 3 was released and I have figured out that GitHub Pages not necessarily switched to building hosted sites using the latest Jekyll release (now GitHub Pages supports Jekyll 3, but migration took a few months). I’m hosting this blog at GitHub, so I had to keep my development environment in align with environment used by GitHub. Otherwise, developing with Jekyll 3 locally and then pushing results to GitHub’s build server on Jekyll 2.4 may result in compatibility issues. Luckily, keeping environment in alignment with GitHub can be easily achieved by using gh-pages gem.

This adds another layer of complexity. Now we need a Bundler to manage our environment. Commands inside a given bundle are launched using bundle exec. Now to serve a site including drafts, we have to type:

$ bundle exec jekyll serve --drafts

Not so convenient as in the beginning, huh?

In my previous post I have showed set up steps and discussed advantages of using Vagrant to build development environment for Jekyll projects. In spite of advantages, Vagrant brings another layer of complexity. For me this resulted in creation of the Makefile with the shortcuts for something like:

$ bundle exec jekyll serve --host --drafts --force-polling

This includes various combinations for different jekyll subcommands and options (basic usage is: jekyll <subcommand> [options]). Obviously make is not the best way to manage this. It is very easy to get confused with different make tasks.

So, I decided to write my own tool which will wrap common Jekyll commands, providing corresponding set of tasks easily modifiable via both long and short CLI flags. And if I’m writing my own tool, of course it will contain some advanced features 😉.

Meet Jtasks

Jtasks (Jekyll tasks) is a collection of configurable Invoke tasks that provide simple, but powerful, interface to run both common and advanced routines in your Jekyll projects.

With jtasks you can:

$ inv --list
Available tasks:

  build     Build the site.
  clean     Clean the site.
  doctor    Search site and print specific deprecation warnings.
  list      List all posts.
  notify    Notify various services about sitemap update.
  post      Create a new post.
  preview   Launches default browser for previewing generated site.
  serve     Serve the site locally.

Basically it’s a collection of configurable tasks which are launched via inv or invoke command:

# using jtasks:
$ invoke serve -bd

# common way:
$ bundle exec jekyll serve -d ./dist/ --host --port 5000 --drafts

--destination, --host and --port are configured as a global variables at the settings part of the script:

# === Settings ===

# Project directories
_site_dest = "./dist/"        # Dir where Jekyll will generate site
_posts_dest = "./_posts/"     # Dir with posts
_drafts_dest = "./_drafts/"   # Dir with drafts

# Global options
_hostname = ''         # Listen given hostname
_port = '5000'                # Listen given port
_bundle_exec = False          # Run commands with Bundler
_fpolling = False             # Force watch to use polling
_incremental = False          # Enable incremental build (Jekyll 3)

# Post settings
_post_ext = '.md'             # Post files extension

# Notification settings (your sitemap location)
_sitemap_url = ''

This allows flexible setup of jtasks on per-project basis eliminating the need to explicitly specify your Jekyll project’s constant values every time.

Jtasks also contains help documentation for each task:

$ inv --help serve
  Serve the site locally.

  jekyll serve [options]

  -b, --bundle-exec         Run Jekyll development server via Bundler.
  -d, --drafts              Process and render draft posts.
  -f, --force-polling       Force watch to use polling.
  -i, --incremental-build   Rebuild only posts and pages that have changed.

For more details and usage examples check project’s page at GitHub.

Previous post: Jekyll development environment via Vagrant and PuPHPet

Next post: A better PostgreSQL CLI experience with few psqlrc tweaks