Getting started with Hakyll on Fedora

Posted on 28 March 2021

Upstream installation tutorial of Hakyll static site generator shows how to use cabal or stack to get hakyll installed and build example site with it. And while the tutorial also mentions an option to use distribution packages on Debian or Fedora, the rest of the tutorial doesn’t explore this option further. In this post I provide a quick overview of installation and usage when Hakyll is installed from rpm packages on Fedora 33.

Hakyll is a static-site generator written in haskell, inspired by other such tools like Jekyll, nanoc or yst. It uses haskell DSL for configuration in a similar way how xmonad does, and for html building, it relies on versatile pandoc document converter.

Reasons I use Hakyll to build my personal blog include:

  • I simply prefer static-site generator approach for this use case, it allows me to write posts in a simple plain text format and then store them in a git repository.
  • I already use pandoc for various tasks (converting between wiki formats, generating epub files, exporting my markdown or org mode notes …) because it can convert between lot of markup and document formats. Possibility to use pandoc features in hakyll makes all these familiar possibilities available, which is a plus.
  • I’m little familiar with haskell and as xmonad user, I find xmonad’s approach to configuration flexible and powerful.

Installing Hakyll on Fedora

Fortunately Hakyll is already packaged in Fedora, so we don’t need to build it themselves via cabal or stack just to have it installed if we don’t have other reason to do so (eg. using latest version of hakyll for testing or development of hakyll itself).

The package we need to install is ghc-hakyll-devel:

# dnf install ghc-hakyll-devel

And everything else will be installed as a dependency. Installing the devel package is necessary because Hakyll’s reconfiguration process includes haskell compilation.

Initializing Hakyll project

First of all, we are going to use hakyll-init tool to create new directory example-site with both content and configuraion files of the example project:

$ hakyll-init example-site
Creating example-site/templates/post-list.html
Creating example-site/templates/post.html
Creating example-site/templates/default.html
Creating example-site/templates/archive.html
Creating example-site/index.html
Creating example-site/images/haskell-logo.png
Creating example-site/site.hs
Creating example-site/contact.markdown
Creating example-site/css/default.css
Creating example-site/about.rst
Creating example-site/posts/2015-10-07-rosa-rosa-rosam.markdown
Creating example-site/posts/2015-08-12-spqr.markdown
Creating example-site/posts/2015-11-28-carpe-diem.markdown
Creating example-site/posts/2015-12-07-tu-quoque.markdown
Creating example-site/example-site.cabal
$ cd example-site

Now we need to compile site.hs, which is haskell source code file with hakyll configuration for the site, into site binary file:

$ ghc --make site.hs
[1 of 1] Compiling Main             ( site.hs, site.o )
Linking site ...

We could also use cabal instead as explained in upstream hakyll installation tutorial, but since we have Hakyll installed from the rpm package, we already have all the devel dependencies installed as well, and there is no need to use cabal just for building of the site executable.

The resulting site tool then provides all hakyll’s functionality:

$ ./site -h
Usage: site [-v|--verbose] COMMAND
  site - Static site compiler created with Hakyll

Available options:
  -h,--help                Show this help text
  -v,--verbose             Run in verbose mode

Available commands:
  build                    Generate the site
  check                    Validate the site output
  clean                    Clean up and remove cache
  deploy                   Upload/deploy your site
  preview                  [DEPRECATED] Please use the watch command
  rebuild                  Clean and build again
  server                   Start a preview server
  watch                    Autocompile on changes and start a preview server.
                           You can watch and recompile without running a server
                           with --no-server.

When we check the size of the executable, we see that it’s quite large. That is because like golang, haskell compiler uses static linking by default. From the system perspective, the executable is dynamically linked though. If we stripe the binary, we can save about 25% of the executable size.

$ ls -lh site
-rwxrwxr-x. 1 martin martin 148M Mar 28 19:13 site
$ strip site
$ ls -lh site
-rwxrwxr-x. 1 martin martin 110M Mar 28 19:47 site

But when the size is really bothering us, we can tell ghc to use dynamic linking instead. This will link the executable with system haskell libraries making the binary file orders of magnitude smaller.

$ ghc -dynamic --make site.hs
[1 of 1] Compiling Main             ( site.hs, site.o )
Linking site ...
$ ls -lh site
-rwxrwxr-x. 1 martin martin 78K Mar 28 19:52 site

Building the example site

So now we can generate html files of the site via:

$ ./site build
Initialising...
  Creating store...
  Creating provider...
  Running rules...
Checking for out-of-date items
Compiling
  updated templates/default.html
  updated about.rst
  updated templates/post.html
  updated posts/2015-08-12-spqr.markdown
  updated posts/2015-10-07-rosa-rosa-rosam.markdown
  updated posts/2015-11-28-carpe-diem.markdown
  updated posts/2015-12-07-tu-quoque.markdown
  updated templates/archive.html
  updated templates/post-list.html
  updated archive.html
  updated contact.markdown
  updated css/default.css
  updated images/haskell-logo.png
  updated index.html
Success

And check the result in _site/ directory. We can also start hakyll preview http server which will present the site on http://127.0.0.1:8000 and auto recompile html files when it’s source files changes:

$ ./site watch
Listening on http://127.0.0.1:8000
Initialising...
  Creating store...
  Creating provider...
  Running rules...
Checking for out-of-date items
Compiling
Success

Next steps

As noted above, the configuration of a hakyll project is done via site.hs file, which contains haskell source code. And as you have most likely already guessed, when you update configuration in site.hs file, you need to recompile site executable.

Domain specific language approach combined with good upstream tutorials and real world examples makes changing hakyll configuration possible even without fully understanding haskell language, but having some haskell knowledge will definitely help a lot. That said I have to admit that if you don’t like idea of learning a bit of haskell (or finding an excuse for that), you won’t be very happy with hakyll.

Do you have a comment or question? You can contact me.