Hierarchies In a Hakyll Blog
Contents
Creating hierarchy in a blog is a useful technique. It allows you to have different sections by type of content. It lets users navigate by their interests quickly. It makes your blog organized.
My need for a hierarchy came when working on another blog - Daily Reading Notes. That blog involves notes on books I read daily. Since each book has multiple reading notes, I wanted to allow two forms of navigation: by a grouping of all notes for a particular book and by posted date. The groupings also needed to be dynamic. I didn't want to write code or updated configurations every time I added a new book.
Hakyll didn't support this out of the box, and I didn't find examples of anyone using similar layouts. So, I created my own approach which I am now sharing.
Structuring the posts directory
In order to build a dynamic hierarchy, the directory structures needs to support association of the books with their related posts.
We start our implementation by creating a page and a folder with the name
of the book inside the posts
directory. This naming convention allows us to
link the book's page to the folder containing the posts.
Our directory structure should have the following layout:
|
|
Matching the Routes
With the directory structure in place, we can proceed to creating matchers for the books and posts pages.
For the books pages, we match all the files in the posts
directory while
ignoring directories and their contents. We also set the extension of these file
to html
. The extension need to be specified because the original files are
written in markdown.
For the posts pages, we use posts/*/*
as the matcher string. The first *
tells match
to look inside any directory within posts
. The second *
tells
match
to gets all the files inside the subdirectory. These file are also
written in markdown and need their extension set to html
.
The matchers with extensions look like this:
|
|
Getting the Posts for a Book
Now that we are matching the books and posts pages, we need to group
the posts by their respective book. For this purpose, we write a small
helper function that takes the output of Hakyll's getResourceFilePath
function.
Our function takes the file path for the book page, strips out everything but the file name, and add a glob pattern to the end.
|
|
We use this function in the books pages matcher to get a list of the book's posts
as an input for the newly created bookCtx
.
Creating the bookCtx
goes in the compile
block:
|
|
This compile
block is similar to the auto generated example that lists all the
posts. Except, we generate the path for the posts relatively to the current file.
Applying Templates
In the final step, we apply templates to both outputs. The book pages need a new
template that uses the posts
list context field we generated in the previous
step. The posts can continue using the default post
template. In addition to
the individual templates, both the matchers will need the default template and the
relativizeUrls
helper.
The final output of the two matchers looks like this:
|
|
Wrapping up
With these matchers in place, we have a hierarchy of books containing the posts related to them. We can add books by creating a new page and folder with the name of the book. This setup made it easy for me to maintain a hierarchical site. I hope it does the same for you.
The final result of a book page looks like this: The Lean Startup book page. The full code for Daily Reading Notes is available on github.