Structuring a jekyll theme

How to plan for and use a structure for your theme

Index file *

This is the starting point of your site or blog. There's not much to talk about for this page. The page itself shouldn't contain much aside from some YAML front matter.

---
title: Home
layout: index
---

Everything that you see on, for example my landing page isn't generated in \index.html. Rather, it's generated in _layouts\index.html. This separation of content from layouts is very similar to what you might see in a MVC-oriented framework.

Additionally, actual content isn't output in our layout either. The layout only determines in which, and in what order, layouts should be included.

{% include header.html %}
    {% include index.html %}
{% include footer.html %}

There's 3 includes to take note of here:

  1. header.html
    Contains the header element and everything associated with this. Also starts the html and body elements.

  2. footer.html
    Pulls in any javascript and finishes the html and body elements.

  3. index.html
    Generates and output content.

The index include isn't very big and should be more or less self-explanatory

{% assign link = true %}

{% for post in site.posts %}
    <article>
        {% include preview.html %}
    </article>
{% endfor %}

All it does is enumerate the last 10 posts on the site and includes preview.html, which expects a variable named post to be set and assigned a post object. preview.html is very simple:

<h1>
    {% if link %}
        <a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a>
    {% else %}
        {{ post.title }}
    {% endif %}
</h1>

<p>
    {{ post.summary }}
</p>

And finally, this is where things are output and actually rendered. Setting a variable named link to anything but false or null will render the h1-element as a link.

The reason why I pulled out preview.html instead of writing the markup directly in the post-loop in (the include) index.html is because I want my theme to be as modular and atomic as possible.

Anytime I want a preview (wherever that might be) I can just assign a variable named post with the correct data and {% include preview.html %} and it should work OOB.

Posts *

The structure and flow for rendering of single post pages isn't much different. Probably the biggest difference is the entry point to the layout. In any post I want rendered with the post layout, I use

---
...
layout: post
---

Now, in the layout post.html there's 3 files included

{% include header.html %}
    {% include post.html %}
{% include footer.html %}

The first and last are included in every layout for obvious reasons, the middle one though is different:

<article>

    {% assign post = page %}
    {% include preview.html %}

    {{ content }}
</article>

Here you see why I pulled out preview.html as a separate module. Since preview.html requires a post variable assigned a post object, we assign post to page (which is the current post object). Finally, since we don't assign anything to link, we won't get our h1 as a link.

Conclusion *

This work, together with learning the syntax of liquid, took me about a day in effective time. As far as I'm concerned, that's very, very little time for setting up a whole site, even a static one.

This post is one in a series of posts on building a site with Jekyll. These are the articles I have written so far, in no particular order: