Generating a Self-Contained Gallery Index

2021-05-01

When I design projects for fun, I'm also the one that has to maintain them, so I tend to design them to be small and simple. For a website, deployment and versioning simplicity is easier when the site is self-contained, in some sense. That could mean a Tiddlywiki-style approach where a single HTML file contains the entire wiki program, along with all the wiki content. To avoid the need for another "control" program, Tiddlywiki is also a quine, allowing it to copy itself (including any updates) to download either to the client or a compatible server. A Fossil-style design also qualifies in my mind, but instead of having the program be a quine, Fossil uses a control program, fossil, and a data file, typically named something like myrepo.fossil, which is a simply a sqlite database of the Fossil repository's data. Together, a fossil repo can be read by the fossil executable to host the repository as a website, or perform a wide variety of the typical operations you'd expect from a distributed DVCS, like git.

What this means in practice is that Tiddlywiki and Fossil are trivially easy to host, but when it comes to hosting non-text content, like images (or, I daresay videos), they really start to fall apart. This challenge led me to start thinking about the design of an extremely minimal gallery system. The very simplest I could imagine is a simply a directory of files served by nginx via the autoindex feature feature. This will list the files, but provides no preview. So I really wanted thumbnails in my extremely-minimal gallery. So I then started to consider a script that would look at a directory of files and generate thumbnail images, along with an index file that loaded all them in a grid of some kind.

Coming back to the self-contained idea: what if the thumbnails were embedded in the index file? I'd used the data-url/base64 trick in Tiddlywiki before to embed small snapshots (300x300) in my journal wiki. What if I did the same thing with the index file? One HTTP request. OK, so in the category of "minimal scripting languages", I typically go with either bash (ubiquity) or Lua (comfort). Bash seems pretty tempting. I could cat an HTML header with style info, and then loop over images and write an img tag for each:

for img in $(ls *.jpg); do
    data=$(convert "${img}" -quality 50 -resize 300x300\> - | base64 -w 0)
    cat << EOF >> $OUTFILE
<img src="data:image/jpeg;base64,$data"/>
EOF
done