Building the Bolt Blog
The Bolt Blog was built over the course of a few days with the help of some interesting and, more importantly, powerful software (specifically Jekyll). In this post we'll review how this blog was built, and which tools were used to build it.
Requirements & Constraints
When we set out to create this blog we had a few requirements and constraints. At its core we wanted the blog to be simple, flexible, and easy to maintain. This meant avoiding complex databases and deployment infrastructure. But we didn't want to sacrifice complete control over the markup and css. WordPress and its ecosystem of themes and plugins would be too much for our small blog.
Then Jekyll entered the picture. Jekyll is very lightweight: it just generates static HTML files. This means that there are no complicated databases, and a simple, static file is served to readers. But Jekyll is flexible and extensible despite its simplicity. As we describe below, using Jekyll's front-matter and the Liquid templating engine we built a solid blogging platform in a very short time.
Jekyll Setup
The Jekyll setup process is quick and painless. Just enter your terminal, install the jekyll
gem, and create your project!
$ gem install jekyll
$ jekyll new my-awesome-site
For more information about Jekyll head over to the Quick Start Guide, or check out the more extensive Installation Guide.
Workflow
After creating the Jekyll project, we needed to set up some basic infrastructure. During development we constantly have stylesheets changing, so we launch the Jekyll project with a special command:
$ cd ~/my-awesome-site
$ jekyll serve -w
Your terminal should output something like:
Configuration file: /my-awesome-site/_config.yml
Source: /my-awesome-site/blog
Destination: /my-awesome-site/_site
Generating... done.
Auto-regeneration: enabled
Server address: http://0.0.0.0:4000
Server running... press ctrl-c to stop.
The blog is then available by visiting http://localhost:4000
in your browser.
The "-w" flag tells Jekyll to watch all project files and regenerate the static site whenever there is a change. This is nice, however it's not quite awesome enough, yet.
Compiling Assets
We use a paid tool called CodeKit ($28) to watch our assets and automatically refresh the blog in the browser when there is a change. CodeKit will also watch our SASS files, preventing the need for another terminal command.
If CodeKit isn't your cup of tea and you prefer to work in the terminal you can set up a SASS watcher or follow a guide to set up Grunt. Here is a very good one by Paul Stamatiou: Developing a responsive, Retina-friendly site (Part 1).
CSS Resources
If it hasn't become obvious yet, we use SASS (SCSS would work as well). We also use a few libraries/frameworks to help us out with the development process.
SASS Mix-In Library
The first library we use is Bourbon.
Bourbon is a library of SASS mixins by thoughtbot comparable to Compass. Bourbon lets us do awesome things like provide vendor-prefix support without any extra work on our part. It also provides the base for the following two SASS libraries.
Responsive Grid-System
We wanted the blog to adhere to a grid system, and responsive grids seem to be all the rage.
We went with Bourbon Neat, as it compliments the Bourbon library very well and maintains thoughtbot's minimal approach.
Styles Baseline
Bitters is a relatively new tool by thoughtbot that helps predefine some default styles in a more extensive way than just a CSS reset. Bitters is used in tandem with normalize.css.
Layouts Setup
After setting up our styling resources we used Jekyll's default Liquid templating engine and some standard CSS practices to define our main layouts.
We open our main stylesheet and @import
the required files for Bourbon, Bourbon Neat, and Bitters.
We don't import normalize.css
for reason explained below. Instead we ensure it is the first stylesheet linked in our <head>
tag.
@import
vs <link>
You'll notice that we only use @import
with the SASS libraries. This is because SASS can pass through variables, mix-ins, and other neat resources via @import
. However, @import
has its drawbacks, and shouldn't be used unless absolutely necessary.
One significant drawback of using @import
is the lack of parallel stylesheet loading. Browsers will wait until the first @import
call is fully loaded before continuing to load the rest of the stylesheets. This will slow down your site, especially if you have many @import
calls.
On the other hand, using <link>
tags in the <head>
of your HTML document will load all stylesheets in parallel but cannot pass through any variables or mix-ins.
Segmenting layouts with _includes
We have four distinct layouts:
- default (index)
- archive
- post
- error
Each of these is an HTML file in the _layouts
directory.
Here is a sample of the default layout for the Bolt Blog:
You'll notice a few things, the first one being that we have a lot of include
tags. Each include
tag references a file in the _includes
directory.
These files have bits and pieces of code that are often repeated throughout the site. Sometimes a layout will utilize many includes (index), and sometimes it will only use a few (error).
Below are some of the include
files used in the Bolt Blog:
Facebook / Twitter Meta Tags
We have both Facebook and Twitter social tag support. You'll notice that we reference some properties of a variable named site
. These are defined in a file named _config.yml
, which is automatically created for you when you first set up your Jekyll project.
Styles
This is a pretty standard way to link stylesheets. We've placed it in its own includable file so that it can be easily maintained across many layouts. We could set up logic to only include certain stylesheets based on which layout is loaded, but that isn't necessary at this point.
Authors and Attribution
A fairly new feature of Jekyll is data files. We use this to store globally-accessible data and access it within various layouts. The contents of any YAML files you put in the _data
directory are available within a layout.
An example usage is author attribution. Below is our authors.yaml
data file. The data is stored as YAML, and is pretty easy to structure.
We access the data through the site.data
reference provided by Jekyll. For example, to get the name
value for the author artur
, we just include the tag:
{{ site.data.authors[artur].name }}
This is where Jekyll's awesome front-matter is helpful. We specify an author
variable by adding it to a post's front-matter, like so:
---
layout: article
title: Improve your note-taking skills with this one weird trick!
author: artur
---
This specifies who the author is, but we don't have a way to dynamically show the author data based on who the author is yet.
To get author data we created an author
include file. A basic sample is shown below:
The author
include above is a simplified version of the file used for the Bolt Blog. I've removed some more advanced logic, which changes the author reference object based on whether the layout is default
or not. This allows multiple author references for pages that show multiple articles (such as the index/default page).
If you'd like to see the more advanced version, take a look at this gist: 7922950.
Deployment
Because Jekyll just generates static content, deployment is quick and painless. We commit everything to git, including the generated _site directory, and pull from git on the deployment target machine.
We already have nginx up and running, so we just drop in a simple server config that points to our _site directory and restart nginx. Here’s our config for reference:
server {
server_name blog.bolt.co;
listen 80;
listen 443 ssl;
if ($server_port != 443) {
rewrite ^ https://$host$request_uri? permanent;
}
root /usr/local/bolt/blog/_site;
index index.html;
try_files $uri $uri.html @404;
location @404 {
error_page 404 /404.html;
}
}
In Conclusion
Overall, Jekyll is a very flexible tool. There are some more advanced techniques that I haven't touched on, but might in a future post. Jekyll, combined with smaller tools like Bourbon and Neat is very powerful, and is more than capable of meeting the requirements of a small blog or static site.