Chao Sun

Creating a Blog Using Hakyll

Posted on August 15, 2013 by Chao Sun

Introduction

Hakyll is a great library for generating static sites, like Jekyll, but uses Haskell. Being a newbie on Haskell (just finished the famous Real World Haskell book, and had planned to create a blog for a long time, I decided to give it a go.

Installation

There are detailed instructions on the website. First, assuming you have cabal installed on your computer, then open a terminal and do the following:

This will also install Pandoc, if it is not already on your computer. Pandoc is another great library for converting files of different makeup formats. Hakyll uses pandoc to convert different markup format, like Markdown, Org mode for Emacs, Latex, etc., to HTML format.

Then, you can follow instructions on the website to create a sample website and see what it looks like. Later on, after you get more familier with the tool, you can change the look-and-feel of the website by change css and template files.

I made only small changes based on the example template. First, I uses the Solarized CSS theme. For this it is pretty simple, you just download the file and put it in css directory. Also, you need to add a line to templates/default.html.

Tags

Another change I made is adding tags support. For this, you need to modify site.hs (or whatever you name it).

First, you need add a tags field:

postCtx :: Tags -> Context String
postCtx tags =
  dateField "date" "%B %e, %Y" <>
  tagsField "tags" tags <>
  defaultContext

This enables you to specify tags for each post.

Then, we can create a page listing all posts under a particular tag:

tagsRules tags $ \tag pattern -> do
    let title = "Posts tagged " ++ tag

    route idRoute
    compile $ do
        posts <- recentFirst =<< loadAll pattern
        let ctx = constField "title" title <>
                    listField "posts" (postCtx tags) (return posts) <>
                    defaultContext
        makeItem ""
            >>= loadAndApplyTemplate "templates/archive.html" ctx
            >>= loadAndApplyTemplate "templates/default.html" ctx
            >>= relativizeUrls

The above code uses the layout specified in templates/archive.html and templates/default.html. It is similar to how archive.html is generated.

Finally, we need to parse tags in all posts and generate corresponding pages for each of them. This can be done in one line:

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

Now, you can put $tags$ in your page (for example, index.html), and check out the effect.

Github

One final goal is to put the website on github. This is pretty simple, you only need to create a git repository under _site directory, and add your github page URL as a remote origin. Notice that, if you also uses git for the outer directory of _site, you need to put _site in .gitignore.