Website built with nix and hakyll
Go to file
Oystein Kristoffer Tveit 44697feb49
Split default.html into several templates:
default.html now consists of `navbar.html` `head.html` and
2023-03-12 22:26:50 +01:00
.github chore(deps): bump crazy-max/ghaction-github-pages from 2.5.0 to 2.6.0 2022-01-14 00:04:04 +00:00
static-site-generator Split default.html into several templates: 2023-03-12 22:26:50 +01:00
www Split default.html into several templates: 2023-03-12 22:26:50 +01:00
.ghci code cleanup 2021-08-02 20:01:55 -04:00
.gitignore The great Flakes refactor 2021-06-16 18:41:56 -04:00
LICENSE Initial commit 2020-09-21 13:10:54 +00:00 update ghci in readme 2021-09-25 23:57:40 +00:00
flake.lock Revamp: 2023-03-11 16:56:32 +01:00
flake.nix Split default.html into several templates: 2023-03-12 22:26:50 +01:00
static-site-generator.cabal Revamp: 2023-03-11 16:56:32 +01:00


Hakyll + Nix template

built with nix


nix flakes

  • Build your site into the ./result/dist folder:

    λ nix build
  • Start hakyll's dev server that reloads when changes are made:

    λ nix run . watch
    Listening on
    ...more logs
  • Run any hakyll command through nix run .!

    λ nix run . clean
    Removing dist...
    Removing ssg/_cache...
    Removing ssg/_tmp...
  • Start a development environment that

    • has your shell environment
    • has hakyll-site (for building/watching/cleaning hakyll projects)
    • has hakyll-init (for generating new projects)
    • can have anything else you put in the buildInputs of the devShell in flake.nix; for example: haskell-language-server, hlint, and ormolu
    • is set up to run ghci with some defaults and the modules loaded so you can make your own changes and test them out in the ghci REPL
    λ nix develop
    [hakyll]λ hakyll-site build
    [hakyll]λ ghci
    [1 of 1] Compiling Main    ( ssg/src/Main.hs, interpreted )
    λ >
  • Easily unbreak hakyll's nixpkgs distribution or change hakyll's compile flags via the ./haskell-overlay.nix and hakyll.patch files


All of this is custmomizable, and here are some things that are already done for you:

  • pandoc markdown customization to make it as close to GitHub's markdown style as possible
  • slugger module is included that makes nice link URIs based on post titles
  • RSS & Atom XML feed generation
  • Sitemap generation
  • Code syntax highlighting customization
  • ...other reasonable defaults

Configure the dev server, cache & tmp directories, and more in ./ssg/src/Main.hs.


Deployment is set up through a GitHub Action with cachix, and it deploys to a GitHub Pages branch, gh-pages, when you merge code into your main branch.

Setup information can be found below in the "Cachix" section.

Note: If your main branch's name isn't main, ensure 'refs/heads/main' gets updated to 'refs/heads/my-main-branch' in ./github/workflows/main.yml.


Nix Flakes

If you don't have nix and are not running macOS, follow the nix installation instructions.

At the time of writing, the macOS installation is in a weird place. You should use this:

λ sh <(curl --tarball-url-prefix

Once you have nix installed, follow the instructions here to get access to flakes:


The ./.github/workflows/main.yml file builds with help from cachix, so you'll to generate a signing key to be able to do this.

  1. Create a cache on cachix for your project
  2. Follow cachix's instructions to generate a signing keypair
  3. Copy the signing keypair value to a new CACHIX_SIGNING_KEY secret on

Enable Content-Addressible Derivation (experimental)

Given you have your nix conf experimental-features set to something like

experimental-features = "nix-command flakes ca-derivations ca-references"

Uncomment the __contentAddressed = true; line in haskell-ovelray.nix, and then run

λ nix build --experimental-features "ca-derivations flakes nix-command"

Alternatives to the haskell overlay

Overriding legacyPackages' haskell compiler packages

pkgs = nixpkgs.legacyPackages.${system};
myHaskellPackages = pkgs.haskell.packages.${haskellCompiler}.override {
  overrides = hpFinal: hpPrev:
      hakyll-src = hpPrev.callHackage "hakyll" "" {};
      pandoc-src = hpPrev.callHackage "pandoc" "2.11.4" {};
    in {
      hakyll = pipe hakyll-src [
        (withPatch ./hakyll.patch)
        (withFlags [ "-f" "watchServer" "-f" "previewServer" ])

      pandoc = pipe pandoc-src [

Pulling hakyll-src from GitHub

hakyll-src, used in the haskell-overlay.nix and in the prior example, doesn't have to come from hackage; it could come from what your pinned nixpkgs version has via hakyll-src = hpPrev.hakyll, or it could come from the hakyll repo pinned as a nix flake input:

hakyll-src = {
  url = "github:jaspervdj/hakyll/v4.14.0.0";
  flake = false;

...and then:

hakyll-src = hpPrev.callCabal2nix "hakyll" hakyll-src {};