Jekyll, a first run
Reading Time: 8 minutes
As you may have noticed, I’ve kept the default first entry just because. Here’s a true description of how my first run went.
Why Jekyll?
- I wanted something KISS, just place lean markup somewhere and have it converted to static html files, no more. In fact,
my main page already does this with my own PHP code, but this time I didn’t want to waste time to write something
that cares about time and date of posts etc etc.
Plus, as part of the KISS principle the resulting HTML code should not be a cluster of eye-defiling div soup. - Being able to easily git my page
- I already saw a blog using Jekyll so I figured I’d give it a go.
A short look revealed:
- No funky daemon* with yet-another-fancy-application-behind™ tearing possible additional holes into the web server host
- No super-fancy DSL requiring you to learn Vendor® Software™’s own language/dialect, tying you to the product
- The above: place files, render, go home
* yes, I am aware that jekyll can be run as a web-app daemon - but as they themselves state this is only for development purposes. I for myself will occasionally use jekyll build –watch in a systemd service while I do lots of changes, and periodical execution of build without –watch the rest of the time. How to ease that approach: see “Publish the Site” later in this post.
Let’s go, then!
Installation
Pretty straightforward. Many how-tos of course suggest manual gem pulling and stuff, but I rather keep my things updated through repositories. In case of Debian (which this first installation runs on), this is a simple
Point out a directory where jekyll should “live”. Remember that many systems like Jekyll live off a base and publish the results to a different directory, typically a sub-directory, so in my case I went to my web-app base directory, and started with:
You can then switch to the directory and a
creates the static HTML pages.
Finally, point your web server to the resulting _site
subdirectory and that’s it.
Jekyll lets you customize source and target directories among a lot of other stuff through parameters or configuration files – but for that, there’s manuals.
Plugins
As an example, let’s add a TOC (Table of Contents) plugin.
Then, we need to include this in the jekyll source directory’s Gemfile (/web/app/base/Gemfile):
Styling
Now, you certainly have noticed we installed the minima theme. Without further ado, the blog comes in a neatly styled theme that does the trick.
I wanted to integrate this into my main site, however, which comes down to:
- a custom <nav> at the site’s top
- a custom <header>
- styling the main content like the rest of the page (like I did with cgit)
After a bit of tinkering about, I eliminated minima’s CSS (i.e. removed it from the <head>) and went on to adjust the templates and my own site CSS. To give an overview into the first insights:
Templates
There’s only one base concept how template files work: there are defaults all over the place and user custom files. That is,
if you have a folder _includes
with two files header.html
and footer.html
, and the user creates only folder/header.html
in their customization structure, footer.html
should still come from the default folder and header.html
should be the user’s.
Sounds straight-forward, not all CMS or ticket systems or or or do that or at least did that to a point. Jekyll works this straight-forward way.
Since minima is a rubygem and we used a repository package to acquire that, the theme defaults are located in:
With that knowledge, we may tweak single files. I replaced the content of header.html entirely, moved parts of it to the footer replacing all email address and twitter hullaballoo there, and that’s most of the structure.
Also, head.html (not header.html) is where my new CSS went, to answer the question for “where’s the site’s own CSS?”.
Configuration and template example: dates
There’s two approaches here, and I used them both :-)
Goal: I wanted to change the dates to roughly resemble ISO8601/RFC3339.
The standardisation approach: _config.yml
Variables! Grepping around for HTML elements of the main page’s blog entry dates and the
posts’ header dates I found _layouts/post.html
and _layouts/home.html
. For the post listing in the blog’s home page,
I chose a shorter format and for the single post details a longer one. I chose the shorter format for my default.
Within home.html we find this:
date_format is then used in any post, so we may want to adjust that. This brings us to variables. Configuration is done through
said _config.yml. It is created on jekyll new
with rudimentary content, and for further options you may want to check
the documentation. One insight, however, is this:
If you want to adjust the above site.minima.date_format, it’s important to know that site is a dict that is populated with the contents of _config.yml. Took me a few minutes to figure, I’ll save you that hassle. As this is YAML, I then put this into the file:
I still wanted to have the long format, so I just defined an individual variable for that (the name is made up by me):
Why an individual variable? None of the time formats in the docs satisfy my needs,
however, we can use any formatting from strftime(3)
as I do above.
Example _config.yml
The template customization approach: post.html
We can then proceed to copy the original post.html into a _layouts subdirectory of our Jekyll source and do this:
I’ve commented out the original line, used my variable from _config.yml
as site.variablename, and that’s the whole magic. This post’s header already shows our new format.
Any template language like Liquid (which Jekyll uses) or Jinja (Python, Ansible) work like this:
- You basically just write down the content of the resulting file.
- Variables known to the surrounding code and configuration are addressed as
{{ variable_name }}
- Programming logic like if, loops, … lives inside
{% these %}
(similar to <?php code ?>) – anything else is not interpreted
And that’s it. Take a look at the default first entry and adapt using the documentation to enrich the document header and markdown for the content.
The Markdown
After this wall of text, this is a rather short remark: Jekyll’s default renderer is kramdown which already supports GFM (Github Flavoured Markdown) which suits all my needs.
Syntax highlighting
Jekyll uses Rouge by default. I’m fine with that and the default appearance (the latter at least for now). To dig a bit deeper into styling that, you may want to use this blog post as a kickoff.
Publish the Site
Now you know basics about the templates and where to customize, and maybe you’ve already done your first post inside
_posts/
. Apache looks inside _site/
, but alas, no change.
There’s no more to do than a
Been there, done that. Now all we need to do is make this git revisioned! You may have already noticed that jekyll places
any file inside the source directory into the target directory save for special locations which are converted (yes, like
_layouts
and _posts
). You can tell Jekyll to ignore certain locations in _config.yml
:
With that in mind, we now can safely make this a general process.
Option 1: Live publishing
jekyll build
itself will already have told you that it has a –watch parameter for live processing. We can use that for a
systemd service:
Disadvantage: there’s a ruby process running all the time. So why not just periodically fire that up?
Option 2: Periodic publishing
This still frequently regenerates the site without a process idling around in the meantime that offers more attack surface.
Rename the /etc/systemd/system/blog-livegen.service
from above to /etc/systemd/system/blog-gen.service
, remove the word
“live” from the Description, remove the --watch
parameter from ExecStart
and remove any line below Group=www-data
.
Now the service can’t be enabled anymore but still be triggered manually or by a timer. Here we go:
This starts the site generation every 30 minutes with a random delay of up to 5 minutes for less predictability (people shouldn’t be able to exactly predict the runtime, the logs still will show what has happened when in the past).
Now, we can
and within up to 35 minutes tops any change is live.
The next step would be to automate pulling the git source so you can push from no matter where, but that is not in scope for a jekyll how-to anymore (in fact, we already went a bit astray with the systemd explanation ;-)).
Conclusion
It took me longer to write this blog post than to set up Jekyll. (Also, CSS adjustments were more labourous as well.) So yes, KISS is fulfilled, and I’d say the resulting HTML code is clean enough. No div soup, no funky Softwarename™ code garbage, mostly just converted Markdown. GGWP!
Also, we already gained a few pointers towards theming and templating.