The beauty of shell scripts
Edit:
Since I wrote this, I made some changes to my build script, because
- Zola has built in minification, which includes inline JS and CSS.
(not quite as effective asminifythough)- Brotli has much better compression, with similar decompression time
fdis a fast and user-friendly alternative tofindMy build script got reduced to this:
zola build fd -t file -S +32b -e html -e css -e js -e svg -e xml -e txt . public -x brotliAlso, I will probably switch back to nginx, because it now finally supports ACME.
2026-02-28
I recently decided i needed a personal website to showcase projects and publish articles. So I looked into ways to do that and quickly found Zola.
The setup was easy and before long I had a working prototype. Then I looked into ways to deploy my site. I’ve already setup Caddy on my server for some other projects, so the only things I needed to do was to put the output of Zola on the server and create a new site block with a file_server in my Caddyfile.
chjlsch.ch {
root * /srv/www/chjlsch.ch/public
file_server
}After creating some more elaborate templates and adding some dummy articles, I looked into optimisations and settled on the following two:
- minify html and css
- precompress my files for caddy to use
After some searching I found these two amazing tools:
I use Alpine Linux on my server, so installing them is quick:
apk add minify zstdZola outputs all of the files in a directory called public, so to minify all files I just call:
minify -ri publicThis minifies all files in-place (-i) recursively (-r) in the directory public. Then I compress the files using zstd, which is simmilarly simple:
zstd -19r publicThis compresses all files in public recursively (-r) using compression level 19 (-19). This also compresses the woff2 font files, which is unnecessary, because they already are compressed. To circumvent that, I create a temporary file called .tmp.zstd in which I list all files that need to be compressed. I get that list using find and then filter out the .woff2 files using ripgrep. Then I just pass that file along to zstd:
find public -type f | rg -v "\.woff.?$" > .tmp.zstd
zstd -19 --filelist .tmp.zstdSo the complete script is just five lines long:
# build.sh
zola build
minify -ri public
find public -type f | rg -v "\.woff.?$" > .tmp.zstd
zstd -19 --filelist .tmp.zstd
rm -f .tmp.zstdI like this solution, it’s simple and reliable. Instead of having a big and complex build system with lots of configuration, I have a simple shell script which does everything i need. It’s also quite fast, building my site in under 100ms (~70ms spent on compression with zstd).
Bash pipes
By the way, I learned something about pipes in bash. If you redirect output of a command like find into a file, the file gets created before the command gets executed. So if you have directory with the files alice.txt and bob.txt and then you run find > list.txt, you get the following output:
alice.txt
bob.txt
list.txt