Fork me on GitHub

Tutorial: Using teasers in Hakyll

Introduction

Sometimes it is convenient to have an excerpt of a post displayed on the index page along with a “Read more…” link to encourage your readers to read the rest of the post.

You can do this in Hakyll by using “teasers” functionality.

Marking teasers in posts

First, you have to put a tag in your post which separates the teaser from the rest of the article. We use <!--more--> for this to mimic the WordPress convention:

---
title: My teasering post
---
In this post I'll try to explain how to use teasers.

<!--more-->

And here I am proceeding with the explanation.

This is an HTML comment, so it doesn’t have any visual impact on the post, it is there solely for semantic purposes.

Referring to teasers in templates

Now, we want to refer to the teaser in the template. We can do this pretty intuitively by using $teaser$ key:

<li class="post_item">
    $date$ - $title$
    <p>Teaser: $teaser$</p>
    <a href="$url$">Read more</a>
</li>

Gluing together

The only thing left is to glue those things together. An important question here is on what stage of the compilation we want to extract a teaser. Usually, we want to use pandoc output, i.e. raw HTML without any templates applied (since we do not want some surrounding JavaScript or common text from the templates to be included in the teaser). We can specify this by using snapshots: we save the snapshot during compilation and load it to resolve $teaser$ key later:

match "posts/*" $ do
  route $ setExtension ".html"
  compile $
     pandocCompiler
     -- save immediately after pandoc, but before the templates are applied
     >>= saveSnapshot "content"
     >>= loadAndApplyTemplate "templates/post.html" defaultContext
     ...

You can read more about snapshots in Snapshots tutorial.

Then we use this snapshot while generating teasers using the teaserField function:

    loadAndApplyTemplate
         "template/postitem.html"
         (teaserField "teaser" "content" <> defaultContext)
         item

Here, we’ve just added a new context which knows how to handle $teaser$ key to the default context (note that we passed the same snapshot name "content" which we used while saving).

Optional teasers

In case you don’t add a <!--more--> comment, $teaser$ will not be defined. This means you can use something like:

$if(teaser)$
    $teaser$
$else$
    $body$
$endif$

Known issues

Since we use an HTML comment <!--more--> to separate the teaser, sometimes pandoc can “eat” the comment while converting (for example this happens with literate Haskell source). In order to overcome this problem you may try to use something like this as a separator:

<div></div><!--more-->

Other tutorials

The other tutorials can be found here.

Documentation inaccurate or out-of-date? Found a typo?

Hakyll is an open source project, and one of the hardest parts is writing correct, up-to-date, and understandable documentation. Therefore, the authors would really appreciate it if you would give feedback about the tutorials, and especially report errors or difficulties you encountered. If you have a github account, you can use the issue system. Thanks! If you run into any problems, all questions are welcome in the above google group, or you could try the IRC channel, #hakyll on irc.libera.chat (we do not have a channel on Freenode anymore).