This post is a reflection on Flat File CMS, permacomputing, abstraction in software in general, and a brief technical log of some interesting things that came up while migrating a website from using ProcessWire to using Lichen-Markdown (and hacking Lichen-Markdown to do some possibly unholy things in the processs), and might be interesting to folks who take care of websites and are interested in these topics.

In May of 2025, I was working on updating the Solidarity Infrastructures website (https://infrastructures.us) to add the class projects from the third round of the class, initially thinking this would be a small task.

During this update, I ran into technical issues with our previous CMS (ProcessWire) which led me to rewriting the website to use Lichen-Markdown, which led me to hacking Lichen-Markdown to do more complicated things than I had previously used it for, which led to this blog post.

a purple iris in bloom

Is A File A Database?

On May 28, 2025 at 4:20PM, before migrating the website to Lichen-Markdown, I wrote:

spending many confused hours today trying to revive an app which has a mysql database and a docker container, that someone else made, and ive been left taking care of … this never happens with a folder of markdown files

ProcessWire – the tool the website was originally built with – is an open source CMS that seems to have a lot to love about it — but still has a database, which, from my perspective, adds a layer of complexity to system maintenance that ideally would be avoided when a folder of markdown files is a possible alternative.

Of course, this does not mean that I think databases should always be avoided — large scale applications, and certain types of complex queries, require such a tool, and in such situations it is necessary. A CMS of a mildly-complicated website with some interactive features is sort of an in-between case: for very simple websites I had generally preferred to use Lichen-Markdown, but this was my first time trying to use Lichen-Markdown as the basis for a website with many pages, many collaborators, and a number of interactive features (tags, filtering by tags, search).

There is also a perspective from which a file is also a database — and from which the difference between mysql and a folder of markdown files is just an implementation detail. However, in the current world, most of our software systems are ultimately built on top of a linux file system, so any abstraction on top of that usually comes with additional complexity and overhead:

  • can no longer use standard filesystem tools for working directly with your data (sed, find, grep, file navigation, etc.)
  • additional context switching into and out of a sql shell (same gripe here with docker)
  • one more dependency that can break or be leaky

A lot of people like Flat File CMSes, so maybe I don’t really need to say this – but it was interesting for me to reflect on what it is I actually like about it, given that in some sort of Ideal Platonic Realm, the filesystem is itself just one particular abstraction and API. But in the world we live in, this particular layer is a particular ecoysystem with a particular history, that has qualities I enjoy.

Git, CRDTs, Archive Resilience & Multi-Writer Collaboration: How I Learned To Stop Complaining And Love Conflict Resolution

After switching to Lichen-Markdown, I especially appreciated being able to back the site up with git. A repository is now on Codeberg which contains the full code and data for the site (as well as documentation for running it), such that anyone with this link could spin up their own version of the site if they wanted to. As someone tasked with taking care of this site, which now contains pages from multiple years of contributors, this was deeply relaxing.

It was also relaxing to use git as the “gate” through which I shared changes between the server and my local laptop. With many students adding and editing pages on the server, I didn’t want to delete anything or lose any changes, but I also like being able to experimentally run scripts locally on my laptop that modify things. It felt like a sort of basic realization, as this type of multi-writer collaboration is exactly what git is meant for, but switching from a non-git-based-system (ProcessWire + MariaDB) to a git-based system made this readily apparent. Using only git for synchronizing changes between the two devices, git would literally not allow me to accidentally overwrite something without giving me a chance to think about it.

After having this “aha” moment with git, I wrote a reformulation of my perennial skepticism of CRDTs:

still have a suspicion that a lot of crdt copywriting is instant-washing the fundamentally messy nature of diverse groups collaborating (which are by their nature, not “conflict-free”)… and that for many types of collaboration, git, with its difficulties, might be the better mental model

I will get to the negative parts about the migration shortly, but first one more positive thing.

an orange rose in bloom

Small Programs, Malleable Software & Beautiful Tools

Going into the migration, I wasn’t entirely sure if I would be able to replicate all of the features of the original website into the new version. I thought I might ditch some interactive features in favor of ease of maintenance. However, in the end, I was able to replicate all of the features of the original site, and keep the exact same CSS. This was cool, and also kind of strange — I did all this work to re-write the website which in the end had zero visual effect.

Lichen-Markdown has no plugin ecosystem, and is very minimal, but there was enough flexibility that I could write raw php to add the things I needed, mostly via a file called shortcodes.php, which allows for defining a custom regex pattern to look for in the markdown, along with custom PHP that will be executed at that pattern. Using this, I added frontmatter to pages (for implementing a minimal tagging system), a way to include snippets in multiple pages, and a fully-frontend-statically-compiled search. This last item was the most surprising and interesting to me — on site build, it compiles the text of all markdown pages into a search_index.json that maps URLs to page contents — then in Javascript as you search it looks through this json for matches and live-updates the results. You can try it out here. For the current number of pages on the site, its suprisingly spiffy, very simple, and an interesing way to interact with the archive contents. I’m curious how large a site would have to be before this simple search method became impractical.

The negative to all this was that this was a lot of bespoke code for this website. So far the code seems robust, but its untested, and there could be edge cases. A part of me is curious about this as a development paradigm — a framework which is so minimal, that you can basically do whatever you want on top of it using raw language features.

While looking through awesome-small-web-publishing I found a few tools which share a similar philosophy. For example makesite is a python static site generator whose core code is 130 lines of python. With such a tool, and with Lichen-Markdown, it doesn’t take long to fully understand the code of the tool you are using. Python and PHP are themselves very flexible tools, so perhaps the minimalism of the framework, is highlighting the expressiveness of the underlying language itself. werc, “a sane webi anti-framework”, espoused a similar philosophy, but built in the interesting & esoteric RC script. All three of these tools share a sense in which the code itself is the intended documentation of how to use it, and a nod towards radical transparency. For further reading on similar topics, here is a blog post on “Small Programs and Languages” as well as a long post on “Malleable Software”.

Of course there really is no panacea — but while migrating this website I was somewhat surprised that I could more easily do more complicated things with Lichen-Markdown than I originally expected. I also began to find myself nerd-sniped by all the different ways you could potentially structure the rendering pipeline of an SSG.

Perhaps working with a tool that you find beautiful, or interesting, at a particular moment, for one reason or another, is what will end up being the most nourishing cybernetics. Tools are actually all cybernetic, and in relation to the people and communities that use them. Imagining programming as a craft, and languages as tools, I feel curious about a vast landscape of beautiful tools.