Update?
I have some free time right now and I’ve have some ideas for blog posts I hadn’t gone around to. So why not jot them down and update my blog a bit? Well… I didn’t set up any automated updates, nor had I touched my blog in years, then built withghost
. Even worse, it wasn’t just ghost
that needed to be updated. I was looking at multiple updates that needed to be done, with Ubuntu
, ghost
and nodejs
all sitting at incompatible outdated versions. I’d have to do the updates in some ordering I am way to unfamiliar to determine.I tried for a bit, but after some hair pulling, I thought: “Why not just recreate this trash completely?”. I wasn’t too happy with ghost
anyway, it was way too overkill for my purposes, I didn’t need subscribers or mailing lists. Just a static site with some words on it, perhaps with some styling and some files I could host.But What if I Didn’t?
In comes Github Pages, a free way to host static websites! I’ve wanted to try using it for quite a while, and I’m already quite familiar with Github, having to use it for work.To use it, I’d need a static site generator. The typical choice here is Jekyll, even being recommend on their own site. I’ve chosen a Haskell alternative called Hakyll, for the simple reason that I like to use Haskell. Getting it up and running was quick; the Hakyll tutorial ends with a nice working blog website with a few placeholder posts. My next step was to translate theghost
Here’s an archive I could find of my website. I broke everything attempting to update my VPS, so getting a production example wasn’t exactly possible.
content I’d backed up, to the markdown files Hakyll builds into html using pandoc.After that tedium came the fun part, getting everything exactly as I liked it. I’ll go over noteworthy things I changed or added to my setup, and how I did it. A lot of existing blogposts exist on integrating features into Hakyll. As always, I’m standing on the shoulders of giants.Styling
After clunking around in CSS for a bit trying to get a consistent color scheme based on gruvbox, this very short post gave me the idea to use Clay for my styling instead. I didn’t know Clay existed prior, but I definitely liked the idea of using Haskell for everything.Unfortunately, the way described in the blogpost limits it to a single module, which seemed counterproductive to the idea of using a preprocessor in the first place. So instead, I run the script as an executable via cabal. One thing to note, is to fix the dependencies of the created file usingrulesExtraDependencies
, so it is recreated on a change to any of the underlying modules. I’m using the following pattern quite often to avoid unnecessary/missed recompilation.main = hakyll $ do
...
match "css/**.hs" $ compile getResourceBody
clayDependencies <- makePatternDependency "css/**.hs"
rulesExtraDependencies [clayDependencies] $
create ["css/main.css"] $ do
route idRoute
compile createCssUsingCabal
Syntax & Latex
Can’t have a techblog without snippets of code right? Luckily, Tony Zorman wrote a nice blogpost, integrating pygments into a Hakyll blog. I didn’t deviate much from that. I’m not too big of a fan of including the.css
file manually, as I already have the above pipeline working nicely. But recreating the pygments syntax coloring files would require me understanding the way it tags tokens, and I can’t be bothered.Similarly, I was able to follow this post to use KaTeX.Sidenotes
I like to use side notes quite a bit instead of footnotes, as I find it often detracts from the point you’re making, if the reader is compelled to jump to a different section of the page. For sidenotes, there already exists a package I could reuse after flipping the html-sidenotes flag that isn’t on hackage yet.Using nix, I just overrode thepandoc-sidenotes
version in the overlay that’s used while creating my shell, and it’ll automatically be installed in the shell-provided ghc
.makeHaskellOverlay (prev: hfinal: hprev:
{
pandoc-sidenote = hprev.callCabal2nixWithOptions "pandoc-sidenote"
(builtins.fetchGit {
url = "https://github.com/jez/pandoc-sidenote";
rev = "<insert hash here>";
})
"-f html-sidenotes"
{};
}
)
Fonts
I’m using Montserrat for regular ol’ text and Fira Code for typesetting code. I could just use Google’s CDN to host these fonts, but that’s no fun and implies any visitor getting unnecessarily tracked by big boi G. But if I’m self-hosting, I may as well go all out and do some font optimization.I downloaded the variable font.ttf
files from Google, and used fontimize to load in the html documents and optimize each variable font file individuallyNote that
. This implies wrangling my nix environment a bit and writing a python script, invoking it via optimise_fonts_for_html_contents
circumvents css files. The implication being that fonts are only optimized based on rough information visible in the HTML, instead of full granularity.This means that it is incompatible with the KaTeX
font files as those are mainly styled using classes. Perhaps I can get it to work at a future point, but I’d have to toy with Hakyll quite a bit. I’d need to give fontimize
the right version of the website, and to use the optimized font files afterwards in the final output.unsafeCompiler
.# Optimizing is as simple as calling a single function.
optimise_fonts_for_html_contents(
html_contents=[html.read() for html in html_files],
fonts=font_file_paths,
subsetname="subset",
print_stats=False,
)
Deployment
I was able to riff off of this blog post to deploy my blog, which is located in a private repository, to my public pages repo. I changed it to support a minimal build environment via nix as that’s what I use to maintain dependencies. I tried to optimize the Github Action time a bit by including nix caching, but also garbage collecting the nix store to keep the caches up to date, and creating a separate build profile from the default shell I use to write this blog.jobs:
build-deploy:
steps:
- run: |
nix develop .#minimal -c cabal update
nix develop .#minimal -c cabal build --only-dependencies site
nix develop .#minimal -c cabal build site
nix develop .#minimal -c cabal exec site build
- run: |
nix develop .#minimal --profile /tmp/build-profile
nix-store --gc
Misc
There’re some more nice blogposts I used to add several niceties.- Drafts: I found this blogpost on being able to include drafts in Hakyll.
- Feeds: I added both RSS and Atom feeds following Robert Pearce’s example.
- Formatted Titles: In the base setup, titles are pulled from metadata and inserted into the templates without going to the pandoc transformation. Which means that every character is piped verbatim, no bold, italics, monospace, no anything. Just plain old characters. This post describes a nice solution, using the first header in the content as the title of the post instead, which does include any formatting conversion done by pandoc.
- Resume: I’ve been impromptu maintaining my resume in a separate location and copying the built file over, but I may as well build it on the fly as part of this blog.I didn’t follow any instruction on doing this, but improvising it was simple enough. I just had to ad the latex dependencies to my nix environment and create my resume in a similar fashion to how the syntax highlighting is set up, calling out to
latexmk
to build my resume file.
rulesExtraDependencies
to handle dependencies of files that are created via IO. But getting it all into, what I think is, a nice result was pretty easy and painless.