Adding tags

Adding tags to a Hakyll site brought some surprises. In retrospect it all makes sense, but it took some thinking on my part to work out the why of it all. The resulting code was heavily influenced by Erik Kronberg’s site.

First I thought I’d just add tags to each rendered post, by building the tags

tags <- buildTags "posts/*" (fromCapture "tags/*.html")

then adding them to the post context

let postCtx =
        field "previousPostUrl" (previousPostUrl "posts/*") <>
        field "previousPostTitle" (previousPostTitle "posts/*") <>
        field "nextPostUrl" (nextPostUrl "posts/*") <>
        field "nextPostTitle" (nextPostTitle "posts/*") <>
        field "postId" getPostId <>
        tagsField "tags" tags <>
        listFieldFunc "comments" defaultContext (getComments "comments/*") <>

and last modify the template

<p>Tags: $tags$</p>

Easy! Except it doesn’t work that way. The $tags$ is always empty. To actually get the tagsField to work as intended it’s necessary to build the tag pages, which can be accomplished using tagsRules

tagsRules tags $ \ tagStr pattern -> do
    route idRoute
    compile $ do
        posts <- loadAll pattern >>= recentFirst
        let tagsCtx =
                constField "thetag" tagStr <>
                listField "posts" baseCtx (return posts) <>
        makeItem ""
            >>= loadAndApplyTemplate "templates/tag-post-list.html" tagsCtx
            >>= loadAndApplyTemplate "templates/default.html" tagsCtx
            >>= relativizeUrls

The template for the tags pages is very simple at the moment

<h1>Posts tagged $thetag$</h1>
    <a href="$url$">$title$</a> - $date$

That’s it. With that in place the $tags$ field renders properly in the post pages as well.

Leave a comment