This is the story of Dr. Hakyll, who created a GitHub page with Hakyll and CircleCI in the name of science and all its wonders.
Published: Jul. 29, 2015
Last updated: Feb. 9, 2022
Hakyll is a Haskell library and program for creating static sites such as simple blogs. Hakyll sites are configured in Haskell in a similar way to xmonad. Moreover, Hakyll sites use Pandoc, which means content can be written in markup languages like Markdown and LaTeX.
Getting started with Hakyll is easy thanks to the Hakyll tutorials and examples. In addition, there are several blog posts about how to build and publish a Hakyll site:
After using services such as Blogger and WordPress.com, and taking a look at tools like Jekyll (which inspired Hakyll), I finally decided to create a blog with Hakyll, GitHub Pages, and CircleCI. Here are the steps I followed.
GitHub Pages gives you one user (and organization) site and one
project site for each of your repositories. The most important
difference between user and project sites is that GitHub uses the
master
branch to publish user sites and the gh-pages
branch to
publish project sites.
To create a user or organization site:
Create a GitHub repository named username.github.io, where username is your GitHub username or organization name.
Create an empty Git repository for your site, commit, and push:
$ mkdir username.github.io/
$ cd username.github.io/
$ git init
$ git commit --allow-empty -m "Create master branch"
$ git remote add origin git@github.com:username/username.github.io.git
$ git push -u origin master
The master
branch is used by GitHub to publish your site. This
is just an empty commit to create the branch. When your site is
ready, you can push to master
manually, but the idea is to have
a continuous integration service do that for you.
hakyll
for the source of your site:$ git checkout --orphan hakyll
The hakyll
branch will contain your site's configuration and
content.
_site
, commit, and push:$ git submodule add git@github.com:username/username.github.io.git _site
$ git commit -m "Create hakyll branch"
$ git push -u origin hakyll
GitHub Pages is not designed to work immediately with tools like
Hakyll. Since Hakyll generates your site in a directory called
_site
, you can use that directory to update the site published
by GitHub.
To create a project site for an existing GitHub repository, use
gh-pages
instead of master
:
gh-pages
, commit, and push:$ git clone git@github.com:username/repository.git
$ cd repository/
$ git checkout --orphan gh-pages
$ git rm -rf .
$ git commit --allow-empty -m "Create gh-pages branch"
$ git push origin gh-pages
_site
, commit, and
push:$ git checkout --orphan hakyll
$ git rm -rf .
$ git submodule add git@github.com:username/repository.git _site
$ git commit -m "Add hakyll branch"
$ git push -u origin hakyll
The following instructions assume that you're creating a user (or
organization) site. If you're creating a project site, the
instructions are very similar, but use the gh-pages
branch instead
of master
.
The easiest way to configure Hakyll is to use the hakyll-init
program as described in the installation
instructions. Basically:
$ cabal install hakyll
$ hakyll-init .
$ cabal configure
$ cabal build
$ cabal run build
Run the preview server:
$ cabal run watch
And go to http://localhost:8000.
$ cabal run clean
$ cabal run build
Or:
$ cabal run rebuild
As another option, use the Dr. Hakyll sample project. It's a Hakyll site that can be used as a complement to Hakyll's sample site:
It uses Bootstrap and Mark Otto's Bootstrap blog example.
It includes a basic feed configuration for RSS and Atom as described in Hakyll's feeds tutorial.
(See Bryn Keller's blog for an example of a static site created with Hakyll and the Bootstrap blog example.)
Once your site is ready, add and commit all changes (except _cache
,
_site
, and other Haskell ignored files):
$ git add --all
$ git commit -m "Configure Hakyll"
You can now push the changes or wait until CircleCI is configured:
$ git push origin hakyll
To configure CircleCI, follow your GitHub repository, add a user key to the SSH keys in your project's settings, and make sure it's selected by default.
Now, create a circle.yml
file and add your configuration:
``` machine:
ghc:
version: 7.8.4
```
Or:
``` machine:
ghc:
version: 7.10.1
```
``` dependencies:
override:
- cabal update
- cabal sandbox init
- cabal install --only-dependencies -j
- cabal configure
```
``` test:
override:
- cabal build
```
If building succeeds, CircleCI should initialize and update the
_site
submodule, and switch to the master
(or gh-pages
)
branch there. Adittionally, it should generate your site:
post:
- git submodule init
- git submodule update
- cd _site/ && git checkout master
- cabal run build
hakyll
branch. First, push all changes in _site
to master
using the current date and time as reference in the commit message.
Also, add [ci skip]
to make CircleCI skip building master
:``` deployment:
production:
branch: hakyll
commands:
- git config --global user.email circleci@circleci
- git config --global user.name CircleCI
- cd _site/ && git status
- cd _site/ && git add --all
- cd _site/ && git commit -m "Update (`date '+%F %T %Z'`) [ci skip]"
- cd _site/ && git push origin master
```
Second, update the submodule in the hakyll
branch. A Git
submodule is a static reference to a specific commit in a
repository. In this case, the hakyll
branch has a reference to a
commit in the master
branch. Since the master
branch was just
updated, the reference in hakyll
must be updated to point to the
latest commit. CircleCI should just add _site
and push. Again,
add [ci skip]
to the commit message to avoid building everything
again. For more information about Git submodules, see the
reference or Nicola Paolucci's
Git submodules.
- git status
- git add _site/
- git commit -m "Update _site (`date '+%F %T %Z'`) [ci skip]"
- git push origin hakyll
date
command, add it to
the machine configuration:``` machine:
...
timezone:
America/Guayaquil
```
Or directly to the date
command:
TZ=America/Guayaquil date '+%F %T %Z'
Finally, push your changes:
$ git add circle.yml
$ git commit -m "Configure CircleCI"
$ git push origin hakyll
Once CircleCI is done building your site, you're done. Go to http://username.github.io.
I think Hakyll is an excellent static site generator. The examples and tutorials make it even better. And it's Haskell. However, there are some things that don't work immediately which are worth mentioning:
By default, there are no comments in a Hakyll blog. There are several examples of sites proudly generated by Hakyll that use services such as Disqus, which is good enough for me.
By default, Hakyll has no way to work with drafts. But you can configure your site to do so. For detailed information about one way to do it, see Drafts in Hakyll by Jorge Israel Peña.
Since Hakyll sites can be used with Git and GitHub, my favorite
solution for drafts is simply creating a separate branch and using a
pull request for each post. You can preview your site, but it'll only
include the draft if you merge it to the hakyll
branch.
Join our community of avid readers and stay informed with the latest articles, tips, and insights delivered straight to your inbox. Don't miss out on valuable content – subscribe now and be part of the conversation!
We care about your data. Check out our Privacy Policy.