One of the things I was doing in Mediawiki was using a lot of templates. A lot. The way a template works in Mediawiki, you have a special page called Template:NAME
and you can embed it with {{NAME}}
in any post. You can even embed a template in a template. They’re basically static ‘blurbs.’ You can make them dynamic, but I have found that even after ten years of using Mediawiki, it’s still a bit of a mystery.
With Jekyll, that gets thrown out the window.
Let’s take, for example, my list of interviews. I have 14 or so years of interviews, broken up into a separate page by year and internally sorted by date. Manually. I also have a template {{Interviews}}
which outputs a pretty formatted link to each year. Also made manually. For every new interview, I edited at least two pages (the interview itself and the year). And for every year I had to update the main interviews page and the template.
My end goal was to do the following:
- Each year index would dynamically list the posts for that year
- The interview main page would list links to all the available years
- The interview ‘template’ would be output on every page
- The interview year page would list everything from that year
- All those things would dynamically update when I added a new item
Oh and I also wanted a layout to be intelligent enough to show a special header with specific information on the individual interview pages.
Love Collections
To convert this, I first made use of collections, making one for _interviews
and within that I have a folder for each year with the interview as a flat file and an index.md
to make the main index. I don’t have to do this. I could have the index anywhere I wanted, but this was easier for me.
There is a big gotcha here, though. Subfolders and collections and sorting by date doesn’t work the way you’d think it would. I could make it easily sort by title, and I could reverse it, but sorting by date proved to be a killer. Eventually I figured this out:
- All the pages have to have a date, even if you’re not going to sort that page (see my index)
- You can’t sort in a for loop
The final code looks like this:
{% assign posts = site.interviews | sort: 'date' %} <ul> {% for post in posts %} {% if post.topic != 'index' and post.tags contains page.year %} <li><a href="{{ site.baseurl }}{{ post.url }}">{{ post.title }} ({{ post.date | date: "%d %B" }})</a></li> {% endif %} {% endfor %} </ul>
Front Matters
This is funnier if you know that the ‘header’ of a Jekyll file is called the Font matter. Here’s an example of mine:
--- title: Interviews author: Mika E. layout: interview permalink: /interviews/ date: 2001-01-01 topic: index tags: - 2001 ---
Everything except topic: index
is a default variable. I made the topic, and what that does is tell me “This page is an index page” and what year things are. There are reasons for this down the line. Now I also want to sort by year, but I can parse the date for that.
Design the Layout
I designated my layout as ‘interview’ in the first example, so I made a file called interview.html
in layouts and made it a child of my default layout. In there, I have this code:
<ul> {% for post in site.interviews %} {% if post.topic == 'index' %} <li><a href="{{ site.baseurl }}{{ post.url }}">{{ post.date | date: "%Y" }}</a></li> {% endif %} {% endfor %} </ul>
That says “if a page is an index, list it.” Now when I want a new year, I just add in a new folder with an index file.
I’ve gone even further, taking the logic from some WordPress themes I’ve see, and the layout file has all the code for both the index view and the per-item view, allowing me to format my interviews with custom headers and footers around the content.
Does it Work?
Yes it does! Mostly.
The problem with this, and yes there’s a problem, is that the interview layout page doesn’t regenerate itself. I have to go and re-save the layout for interviews in order to regenerate any lists I have on that page.
I can get away with typing this in shell: touch _content/_jekyll/layouts/interview.html && jekyll build
but it is a little annoying. Even running a manual jekyll build
won’t do it because the layout doesn’t realize it has a change yet. I do understand why, though. It may be worth moving that somewhere else, though I have a feeling even if I make it a template it would have the same problem, since that template file wouldn’t know to update until it was edited.
It took me a while to find the magic sauce is a bit of code called regenerate: true
– This is not something you should use everywhere! I use it on my interviews index pages because those pages get updated when a new item is added to their folder. It actually lets my index pages be totally blank except the yaml headers which is nice and simple.