These cobbler’s children have excellent shoes
By Richard CrowleyI’ve worked on an enormous variety of software in my life – web, desktop, firmware, client, server – but I’ve written and rewritten my personal web content management system more times than anything else, and it’s not even close. I can think of seven complete rewrites, plus a dark age involving Wordpress. It’s been a comfortable framework in which to learn new technologies and try new ideas where the stakes are low and the enjoyment is high.
I’ve recently been back on my bullshit and decided to write about it. This is not like the old joke about the programmer with so much to write about but first they just need to whip up a quick CMS, though. I assure you I don’t have much to write about.
This is also not me winding up to start an open-source project. This is a lot closer to Cartmanland, to be honest. I wrote this software for me. I’m sharing the code because I think the potential there are eyes besides mine on it might motivate me to keep it tidy and tested. My plan is to keep endlessly tweaking the software because it’s fun. I’m the cobbler who doesn’t bother trying to sell the shoes I make.
Mergician
Here’s the pitch: HTML templating without the templating language. HTML is the language of the web and most of the time that’s what I want to be writing. But not all of the time, so I’ve included support for rendering Markdown, too.
Start with your site layout. Call it layout.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="layout.css" rel="stylesheet"/>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1" name="viewport"/>
<title>Website</title>
</head>
<body>
<header><h1>Website</h1></header>
<br/>
<div class="body"></div>
<br/>
<footer><p>© 2025</p></footer>
</body>
</html>
Then write the simplest HTML document you can imagine. Or crank out a quick novel. Call it webpage.html
:
<!DOCTYPE html>
<html>
<head>
<title>My cool webpage</title>
</head>
<body>
<h1>Things</h1>
<p>Stuff</p>
</body>
</html>
Use Mergician to merge them together:
mergician layout.html webpage.html
You get your webpage wrapped in your layout:
<!DOCTYPE html>
<html lang="en">
<head>
<link href="layout.css" rel="stylesheet"/>
<meta charset="utf-8"/>
<meta content="width=device-width,initial-scale=1" name="viewport"/>
<title>My cool webpage — Website</title>
</head>
<body>
<header><h1>Website</h1></header>
<br/>
<div class="body">
<h1>Things</h1>
<p>Stuff</p>
</div>
<br/>
<footer><p>© 2025</p></footer>
</body>
</html>
When I’m really locked into my digital gardening, this is the killer workflow. I can write HTML and open it locally to see what I’ve got cookin’. There are no artifacts of a templating language in my way. These are complete HTML documents, not fragments.
When I’m doing something that’s a little more like writing, well, I admit that I put on my oven mitts and start writing Markdown. Mergician works the same way, though:
mergician layout.html article.md
Electrostatic
At first, these very compiler-like Mergician commands, which were actually more like mergician -o article.html layout.html article.md
, were situated in a Makefile
very much like you might see gcc -o $@ $<
in days gone by. But as my ambitions grew, so did the find
command that was finding all the files that needed to be merged into the layout.
Enter Electrostatic, the Mergician-powered CMS. It works on whole directory trees of input files, merges each one into a layout, and writes the whole tree into a document root directory for your favorite web server to serve up.
My impressive Makefile
became:
all:
electrostatic -l design-system/index.html raw
OK, fine, you got me. The real thing is slightly more complex. Still beats a find | xargs
that wrapped around my screen four times.
The rest of the gang
I’ve tried to keep things small and Unix-y and I’m letting the Git repositories proliferate.
Adhering as best as I can to the principle that only good link is a permanent link, I used Mergician as a library to power Deadlinks, which scans a document root directory for dead links so I can fix them. I run this in GitHub Actions on push because it’s a little slow to run interactively.
A friend challenged me that no CMS is worth its salt if it doesn’t generate RSS feeds. So I made Feed to generate Atom feeds. RSS-the-idea is great but RSS-the-standard is silly.
For some reason I have genuinely forgotten, I made Frag, which extracts fragments of HTML documents. I use this functionality all over these codebases but why I decided it needed to be a command-line tool all its own, I can’t quite remember.
Finally, there’s Sitesearch, which indexes a document root directory and puts up a Lambda function that serves queries to it. I made this pretty much entirely to try to convince Travis we didn’t need to pay Gitbook to host the Substrate documentation.
I’m very pleased with myself for Mergician. Thank you for indulging me a moment to share it with you.
For a slightly more realistic example of it in action, view source on this page, which is the output of Mergician’s html.Merge
function; /raw/mergician/index.html, which is simply rendered Markdown; and /raw/mergician/index.md, which is the Markdown I actually wrote.