HomeFontsAbout

Makefile Site Generator

Updated on 2021-12-08

The pages on this site are written in Markdown and converted to HTML using a custom Makefile to orchestrate the conversion. I don't see why the actual Makefile would be of use to other people, but maybe it can serve as an example for others in building their own site generators using a Makefile. In what follows, I will explain my requirements, solution and the actual code used.

Requirements

I have very modest requirements for my site generator.

Non-requirements

To prevent feature creep I have also create a list of non-requirements.

Solution

I decided to go with a Makefile using one recipe per file type. Another option would have been to use a bash script, but make is trivial to parallelize the build with the -j flag and I think easier to write.

For converting Markdown files into HTML I will use cmark-gfm, but I may switch to md4c in the future. To strip the meta data from binary files I will use mat2. Both cmark-gfm and mat2 are available in Debian 11, so easy for me to install. I will add the header and footer to pages using cat. So far I do not have support for LaTeX equations, but I will worry about that later.

The entire Makefile file is less than 50 lines of code. Time will tell if builds are fast, but so far it seems fast to me.

The next three sections include contents of Makefile, header and footer.

Makefile contents

SRC_DIR := src
DST_DIR := site
MD2HTML := cmark-gfm -e table -e strikethrough -e autolink
HTML_HEADER := header
HTML_FOOTER := footer
REMOVE_META := mat2 --inplace
SRV_SYNC := rsync -rcize ssh --delay-updates --delete-after --force
SRV_USERNAME := username
SRV_HOST := example.com
SRV_DIR := /var/www/example.com

.DEFAULT_GOAL := all

SRC_MD_FILES := $(shell find $(SRC_DIR) -type f -name '*.md')
DST_HTML_FILES := $(patsubst $(SRC_DIR)/%.md,$(DST_DIR)/%.html,$(SRC_MD_FILES))
DST_FILES += $(DST_HTML_FILES)
$(DST_DIR)/%.html: $(SRC_DIR)/%.md $(HTML_HEADER) $(HTML_FOOTER)
	@mkdir -p "$(dir $@)"
	$(MD2HTML) "$<" | cat $(HTML_HEADER) - $(HTML_FOOTER) > "$@"

SRC_JPG_FILES := $(shell find $(SRC_DIR) -type f -name '*.jpg')
DST_JPG_FILES := $(patsubst $(SRC_DIR)/%,$(DST_DIR)/%,$(SRC_JPG_FILES))
DST_FILES += $(DST_JPG_FILES)
$(DST_DIR)/%.jpg: $(SRC_DIR)/%.jpg
	@mkdir -p "$(dir $@)"
	cp "$<" "$@"
	$(REMOVE_META) "$@"

SRC_PNG_FILES := $(shell find $(SRC_DIR) -type f -name '*.png')
DST_PNG_FILES := $(patsubst $(SRC_DIR)/%,$(DST_DIR)/%,$(SRC_PNG_FILES))
DST_FILES += $(DST_PNG_FILES)
$(DST_DIR)/%.png: $(SRC_DIR)/%.png
	@mkdir -p "$(dir $@)"
	cp "$<" "$@"
	$(REMOVE_META) "$@"

DST_FILES += $(DST_DIR)/favicon.ico
$(DST_DIR)/favicon.ico: $(DST_DIR)/favicon.png
	cp "$<" "$@"

.PHONY: all
all: $(DST_FILES)

.PHONY: clean
clean:
	rm -r $(DST_DIR)

.PHONY: serve
serve: all
	python -m http.server --directory $(DST_DIR)

.PHONY: deploy
deploy: all
	$(SRV_SYNC) $(DST_DIR)/ $(SRV_USERNAME)@$(SRV_HOST):$(SRV_DIR)

Header contents

<!DOCTYPE html>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
html {
    font-size: 20px;
    background: mintcream;
    font-family: "Comic Sans MS", "Comic Neue",  sans-serif;
}
body {
    margin: 1rem;
}
p {
    line-height: 1.4;
}
code, pre {
    font-family: "Fantasque Sans Mono", monospace;
}
pre {
    overflow: auto;
}
img {
    max-width: 100%;
}
</style>
<title>The Stuff I Do...</title>
<a href="/">The Stuff I Do...</a>
<hr>

Footer contents

<hr>
<p>Copyright © 2020-2021 thestuffido.xyz All Rights Reserved</p>

How I got here...

I have been making personal webpages for myself since the 1990s. Over the years I have tried WYSIWYG editors, Jekyll, Hugo, 11ty, ssg, a convoluted JavaScript program using Markdown-it and of course just writing HTML in HTML. I am hoping this Makefile will workout, but odds are I will switch to something else at some point.


Copyright © 2020-2021 thestuffido.xyz All Rights Reserved