subtitle: A few static blog rewrite experiences
author: Yann Esposito
email: yann@esposito.host
date: [2021-05-01 Sat]
keywords: blog static
description: Minimal and fast static website builder with make.
As someone on the Internet said not so far ago.
Building its own static building system is a rite of passage for many developers.
It has a lot of nice features.
It gives a goal with a feeling of accomplishment.
It is simple enough so most developers could build their own system.
It could also become complex when you go down the rabbit hole.
Along the years I used different tools and used and wrote of few static
website systems:
(in Ruby), at that time it looked like this:
(haskell static website generator)
(emacs package in conjunction with org-mode)
(haskell again)
So if you look at the progression, I first used nanoc because I used ruby
and it was a new solution, the website looked really great.
Also the main developer
was really helpful.
Ruby was really great at dealing with regular expressions for hacking my
documents.
Then I was interested in Haskell, and I switched to a Haskell-made
solution.
I used hakyll, and I wrote a bit about it in
As a side note, the author of Hakyll
is apparently a
friend of the author of nanoc.
They both wrote a static site generators with their preferred programming
language.
I added a lot of personal features to my own site builder.
It was a nice toy project.
Then, due to a major disruption in my professional and private life I
stopped to take care of my website.
And a few years ago, I wanted to start a new website from scratch.
In the meantime I switched my editor of choice from vim to Emacs.
I started to work in Clojure and emacs is generally a natural choice
because you can configure it with LISP.
I discovered
(I don't think the homepage of org mode makes justice
to how incredible it is).
So org-mode comes with an export system.
Thus I switched to org-publish.
Again
It was nice but slow.
I improved a few things like writing a short script to
Generate RSS from a tree of html files.
I still had the feeling it was too slow.
Static site building is a specific usage of a build system.
And as I knew I could use =pandoc= to build HTML out of org-mode files
and still versed in the Haskell culture I decided to try
You can learn more by reading this excellent paper about it, I
think all developer should read it:
As a bonus,
is written in Haskell.
I could then directly use the
library in my build program.
It worked like a charm and it was *very fast* as compared to other
solutions I tried.
So really let me tell you shake is a great build system.
Unfortunately it was not perfect.
While it was very fast, and I was able to use pandoc API directly.
It made me dependent on Haskell.
The best way I found to have Haskell reproducible build environment is to
use
This was great until the Big Sur update.
To keep it short, nix stopped working on my computers after I upgraded my
to Big Sur.
Gosh, it was painful to fix.
Concurrently I discovered
and wanted to duplicate my website into
gemini sphere.
So I tried to update my build system but my code was to oriented to use
pandoc and it was painful to have gemini in the middle of it.
Particularly, generating a gemini index file.
My main goal was to have gemini file that could only be linked from withing
gemini sphere.
Because gemini is a lot smaller web where you could feel a bit more
protected from what the Web has become along the years.
Whatever, in the end, I just had two problems to tackles.
1. Haskell became difficult to trust as very stable tool. Stable in the
sense that I would not have any support work to do in order to keep just
using it and not fixing/tweaking it.
2. Simplify the overall system to have a simpler build description
So a very stable tool that I am pretty sure will still work almost exactly
as today in 10 years is *=make=* (more precisely gnumake).
I expected a lot of people had already come to the same conclusion and
wrote about it.
To my great surprise, I found very few article about generating static
website with make.
I only found solutions a bit too specific for my need.
This is why I would like to give you a more generic starting point
solution.
Instead of copy/pasting my current =Makefile= entirely let me give you a
more generic one.
It should be a great start.
The first part will be used to simply copy the files from =src/= to
=_site/=.
all: website # directory containing my org files as well as my assets files SRC_DIR ?= src # directory where I will but the files for my website (HTML + assets) DST_DIR ?= _site # list all files in src # if you want to exclude .org files use the exclude from the find command SRC_RAW_FILES := $(shell find $(SRC_DIR) -type f) # generate all file that should be copied in the site # For my site, I want to publish my source files along the HTML files DST_RAW_FILES := $(patsubst $(SRC_DIR)/%,$(DST_DIR)/%,$(SRC_RAW_FILES)) ALL += $(DST_RAW_FILES) # COPY EVERYTHING (.org file included) $(DST_DIR)/% : $(SRC_DIR)/% mkdir -p "$(dir $@)" cp "{body}lt;" "$@"
This part is about running the =pandoc= command for all =org= files in =src/=
so they generate a html file in =_site/=.
# ORG -> HTML, If you prefer markdown replace .org by .md EXT := .org # all source file we'll pass to pandoc SRC_PANDOC_FILES ?= $(shell find $(SRC_DIR) -type f -name "*$(EXT)") # all destination files we expect (replace the extension by .html) DST_PANDOC_FILES ?= $(subst $(EXT),.html, \ $(subst $(SRC_DIR),$(DST_DIR), \ $(SRC_PANDOC_FILES))) ALL += $(DST_PANDOC_FILES) # use a template (you should use one) TEMPLATE ?= templates/post.html # URL of the CSS put yours CSS = /css/y.css # The pandoc command to run to generate an html out of a source file PANDOC := pandoc \ -c $(CSS) \ --template=$(TEMPLATE) \ --from org \ --to html5 \ --standalone # Generate all html if the org file change or the template change $(DST_DIR)/%.html: $(SRC_DIR)/%.org $(TEMPLATE) mkdir -p $(dir $@) $(PANDOC) {body}lt; \ --output $@
A missing part is often the part where you would like to generate
an index page to list the latest posts.
Here you are a bit alone, you need to make one yourself.
There is not generic way to do this one.
# Generating an index page is not difficult but not trivial either HTML_INDEX := $(DST_DIR)/index.html MKINDEX := engine/mk-index.sh $(HTML_INDEX): $(DST_PANDOC_FILES) $(MKINDEX) mkdir -p $(DST_DIR) $(MKINDEX) ALL += $(HTML_INDEX)
Finally, a few useful make commands. =make clean= and =make deploy=.
# make deploy will deploy the files to my website write your own script deploy: $(ALL) engine/deploy.sh website: $(ALL) .PHONY: clean clean: -rm -rf $(DST_DIR)/*
Limitation: =make= is old.
So it really does not support spaces in filenames.
Take care of that.
Let me tell you.
While this is quite a minimalist approach (<100 lines) it is nevertheless *very fast*.
It will only generate the minimal amount of work to generate your website.
I have a nice watcher script that update the website every time I save a
file.
It is almost instantaneous.
The only risky dependencies for my website now is =pandoc=.
Perhaps, they will change how they generate an HTML from the same org file
in the future.
I still use =nix= to pin my pandoc version.
The static site builder itself is very simple, very stable and still
very efficient.
As a conclusion, if you want to write your own static site builder that's great.
There are plenty of things to learn along the way.
Still if you want something stable for a long time, with a minimal amount
of dependencies, I think this Makefile is really a great start.