An introduction to Jekyll – a static HTML generator

Learn how to use Jekyll, a Ruby gem, to compile and create static HTML site content from simple markdown files that offer reuasability


Content management systems are powerful tools in their own right, and have become a popular way for bloggers and organisations to share and manage online content.

While using a pre-built CMS or blogging platform can be beneficial, we start to tie ourselves into dependencies. We need a hosting solution that provides the server-side language required by the CMS and a database for data storage, as well as references to media libraries and a host of other data relationships.
Databases can seriously impact site performance, especially if not regularly maintained, while server-side languages take time to process files for display. What you may need is a pure HTML site that is fast to load, intuitive to manage and easy to update and deploy on any server. In this tutorial we dive into the world of static site generation using Jekyll, a Ruby gem which compiles and creates static HTML site content from simple markdown files. We’ll create multiple layout templates and see how to use include files to increase modularity and reusability, as well as taking a look at Rake files.


Install Jekyll

Jekyll is best installed as a Ruby gem, direct from the source. Open up your Terminal window and enter the following command (line 1) to install the Ruby gem. We’re also going to install some other gems which we’ll use in our automated tasks. Once complete, verify that you have Jekyll installed by running the version request command (line 2):

001 > gem install jekyll rake term-ansicolor
 002 > jekyll --version

Create a project

The structure of a typical core Jekyll project relies on a number of directories, into which all of our written content will be placed and the resulting code generated automatically to make our lives a little easier. Enter the following commands into the Terminal window to generate the required structure as well as the default layout files. Alternatively, the start project is also available on this issue’s cover disc.

001 > mkdir jekyll_site
 002 > cd ./jekyll_site
 003 > mkdir _layouts _plugins _includes _posts css javascript images
 004 > touch index.html _config.yml _layouts/default.html _layouts/post.html _includes/post.html

Configuration file

Open up _config.yml in your preferred text editor. This file lets you define some configuration variables used to generate and compile your Jekyll static files. The full code content for this file is included in the project files on the CD, so copy and paste the content into the config file.

001 safe:        false
 002 auto:        false
 003 server:      false
 004 server_port: 4000
 005 base-url:    /
 006 source:      .
 007 destination: ./_site
 008 plugins:     ./_plugins

Start the server

Now let’s activate the Jekyll server to make sure that we can access the site on our local machine. You need to open the Terminal window again and then navigate to the directory where your Jekyll site is located. Run the following command to turn on the server. You should see a response flag up indicating the localhost URL development port.

001 jekyll server --auto

Initial compile

With the server running, we can view to the local site in our browser by going to http://localhost:4000 (assuming the default values are unchanged in _config.yml). You will see an empty page as we have not yet added any content, but viewing the source code you will also see a copy of the root index.html file has been moved to the _site directory.

Work up the layout

The next thing we need to do is open the _layouts/default.html file. This will contain the main HTML template for our website. The title tag is populated with a variable to display the current page title, which will be drawn from the YAML Front Matter values which we’ll be placing in each file that we generate. The {{ content }} tag, meanwhile, will display the content from the requested page.


Open the index.html from the root of the project. Define the YAML Front Matter at the very beginning of the file and make sure that it’s surrounded in a block of three dashed lines. Here we specify that this file must use the default layout, as we also set the title for page, which will be used in the template after it is rendered.

001 layout: default
 002 title: My Jekyll Site

Post template

For this step, you will need to open up _layouts/post.html. Any posts which we create will use this template, but this in turn must implement the default template so that the content will be rendered the way that we want. Once again, set the YAML information, as per step 7. We also assign the post variable to a new variable – page – and we’ll use an include file for reusability, which we’ll be focusing on in the next step.

001 layout: default
 002 {% assign post = page %}
 003 {% include post.html %}

Include file

Open _includes/post.html. This HTML will handle the display formatting for our individual post content only. Here we are able to use the post-specific Liquid template variables to create the URLs to each post and output the title as a header. We can also control the output of the page content and truncate the length when we’re displaying it in a list (< li>) page.

001 < h2>< a href=”{{ post.url }}” title=”[Permalink] {{ post.title 002 }}”>{{ post.title }}< /h2>
 003 {% if page.title != post.title %}
 004 {{ post.content | strip_html | truncate: 200 }}
 005 {% else %}
 006 {{ content }}
 007 {% endif %}

Stringing it

Let’s add more to the include template. Below the content variable, we can output the date of the post and, using a built-in function, we can convert it to a readable string format. We’ll also display another link to open the full article, but again only if it is currently being shown on a < li> page.

001 < ul class=”meta_data”>
 002 < li>
 003 < img src=”/images/date_posted.png” alt=”” width=”26” 004 height=”26” /> Posted {{ | date_to_string }}
 005 < /li>
 006 {% if page.title != post.title %}
 007 < li>
 008 < a href=”{{ post.url }}” title=”[Permalink]
 009 {{ post.title }}”>< img src=”/images/read_more.png” alt=”” width=”26” height=”26” /> Read full article< /a>
 010 < /li>
 011 {% endif %}
 012 < /ul>

Looping posts

Open up the root index.html file once more. Inside here we’ll add some code to loop over the generated posts and display them within the template. The loop itself is a simple ‘for in’ loop, and for each post we discover, we’ll implement the post template file from the _includes folder.

001 {% for post in site.posts %}
 002 {% include post.html %}
 003 {% endfor %}

Generate a post

We can produce a post by creating the file manually within the _posts directory. The file must follow a strict naming convention of the post date and the title of the post with spaces separated by hyphens (see below). Jekyll will use this format to generate the necessary directory structure when compiling. Here we are using markdown, so the file extension will be .md.



Each post must also contain the required YAML Front Matter at the top. Here we are telling it to use the post layout, as well as giving the post title for display purposes. We can also assign the post to any categories, and any number of tags to the post by setting them as a YAML list, like so:

001 layout: post
 002 title: “My New Post”
 003 categories:
 004 - development
 005 - design
 006 tags:
 007 - web
 008 - jekyll

Post content

The content of your post can then be written directly into the file. You can use HTML tags if you prefer, but a big benefit of using Jekyll to compile the site is that we can also use markdown language or plain text. Jekyll will convert the content into relevant HTML tags for you. Check out this resource for more information on markdown syntax:


Copy the stylesheet from the cover disc project Start folder and add it into the CSS directory within the working project location. Any files or directories not prefixed with an underscore character will automatically be included in the generated site directory by Jekyll. This can be overridden by adding them to the excluded property list in the _config.yml file.

001 exclude: [‘Rakefile’,’.gitignore’]

Rake automation

Although not required for Jekyll sites, this project includes a Rake file to help automate tasks and manage some code generation. Open up your Terminal window and type the following command to return a list of available tasks we can perform to help when working with our static site.

001 > rake

Rake it over

Run the rake post command in the Terminal window. This will automatically create a new post page for you, ready to edit and fine-tune. This task accepts two optional parameters, which allow you to specify the title of the post and also add a particular post date. If not supplied, the current date will be entered by default along with a generic title.

001 > rake post title=”My Second Post” date=”2012-11-03”

Preview the site

Run the rake preview command in your Terminal window. This will fire a number of dependent tasks to clean and rebuild your static site content. It will also create a directory structure for category and tag archive pages, as well as a tag and category cloud files in the _includes directory. You can give the site a quick once-over at http://localhost:4000.

001 > rake preview
 002 ==> Cleaning build directory...
 003 ==> _site directory is now empty. Housecleaning rocks!
 004 ==> Generating tag cloud...
 005 ==> Done.
 006 ==> Generating tags...
 007 ==> Done.
 008 ==> Generating category cloud...
 009 ==> Done.
 010 ==> Generating categories...
 011 ==> Done.
 012 Auto-regenerating enabled: . -> ./_site
 013 [2012-11-22 23:15:10] regeneration: 21 files changed
 014 [2012-11-22 23:15:10] INFO WEBrick 1.3.1
 015 [2012-11-22 23:15:10] INFO ruby 1.9.3 (2012-04-20) [x86_64-darwin10.8.0]
 016 [2012-11-22 23:15:10] INFO WEBrick::HTTPServer#start: pid=43174 port=4000

Adding meta

Open _includes/post.html. Now that we have the tag and category listing files generated for us, we can incorporate them into our template. We only want to display them when viewing a specific post and not in a list page, which we can control by amending the existing conditional statement.

Includes in sidebar

We can also include the tag and cloud link lists within the sidebar of our site design. Open _layouts/default.html and add the two references to the include files within the aside

element. This will show on every page request as it is now part of the main template.

Add pagination

At this point we’re going to add pagination to our Jekyll site. The
_config.yml file accepts a paginate property for the number of posts to show on each page. We also need to amend the loop within index.html to change the collection value from site.posts to paginator.posts, which will govern the number of posts returned during generation.

001 {% for post in paginator.posts %}
 002 {% include post.html %}
 003 {% endfor %}

Pagination links

Finally we need to include the code into _layouts/default.html to add the pagination links. We will only display the next and previous links if we have content to display on those pages, and if the first page number is ‘1’, we will take the user back to the homepage.

 002 {% if paginator.previous_page %}
 003 {% if paginator.previous_page == 1 %}
 005 {% else %}
 007 {% endif %}
 008 {% endif %}
 009 {% if paginator.next_page %} 
 011 {% endif %}