
Why I built a CMS that nobody else can use
A weekend, a local server, and a folder of plain text — and why every limit I built in turned out to be the point.
The content management system behind this site has no login page, no database, and no URL you could visit. It runs on my laptop, on localhost, and it shuts off the moment I close the terminal. I built it in a weekend, and it is the best writing tool I have ever used — precisely because it would be useless to anyone else.
That last part is the interesting bit. For years the honest answer to "why not just build your own?" was because building one is expensive. A real CMS meant a database, an auth system, a hosting bill, and a few weeks you didn't have. So you rented one. You shaped your writing around someone else's idea of what a post is, and you paid for the privilege.
That math has quietly flipped. And once it does, the question stops being can I afford to build it and becomes what would I build if it only had to fit me?
The mismatch was never features
Here's what I actually am: one person, with one website, whose posts are MDX files sitting in a git repository. Each post is a text file. Each image lives in a folder next to it. The "publish" step is a commit.
Every off-the-shelf CMS I looked at wanted me to give that up. It wanted my words in its database, behind its account, exported through its API, formatted in its flavor of rich text. None of these tools were bad. They were just built for a different writer — a team of them, usually, editing concurrently, with roles and permissions and a publishing calendar.
The gap was never a missing feature. It was shape. I was being asked to reshape a thing I already had — plain files in version control — to fit a tool designed for a problem I don't have. So I stopped trying to find the right CMS and asked a smaller question instead: what would it take to remove the friction between I have a draft and it's live, without giving up the files?
The answer turned out to be small enough to build over a weekend.

Built for me, not for everyone
The whole design comes down to a handful of constraints I chose on purpose. Each one looks like a limitation. Each one is the reason the tool is good.
It only runs on localhost. The editor is a tiny local server bound to 127.0.0.1. It is not on the internet and never will be. That single decision deletes an entire category of work I'll never have to do — no login, no password reset, no session handling, no "secure the admin panel," no hosting to pay for, nothing to patch when a dependency has a vulnerability. The most secure admin panel is the one that doesn't exist on any network.
Plain MDX in git is the database. There's no database at all. Every post is a text file I own outright; git is the edit history and the undo button; and there is nothing to export, because nothing was ever locked away in the first place. If I delete the tool tomorrow, every post I've written is still sitting right there, perfectly readable, exactly as it was.
The editor and the build agree, by construction. This is the one piece I'm quietly proud of. The site has a build-time check that validates every post — broken image links, wrong aspect ratios, oversized files. Rather than reimplement those rules inside the editor, the editor imports the same module the build uses to read and write a post's metadata. There is one source of truth, used in two places. So "it looked fine in the editor" and "it passed the build" can never drift apart, because they're running the same code. The tool can't lie to me about whether a post is ready.
There's a smaller pleasure in how it handles images, too: it keeps the original I dropped in and writes a separate optimized copy for the web, so I can re-crop or regenerate a picture later without re-uploading anything. But that's a detail. The structure is the point.

The constraints are the feature
It's tempting to read all of that as a list of compromises — the cheap version, the thing you build when you can't afford the real one. It isn't. Run the list again and notice what each limit bought me. No auth, because no network. No migration risk, because no database. No drift between draft and published, because one piece of code does both jobs.
The limits weren't compromises. They were the design.
A general CMS can't make any of those choices, because it can't assume my situation. It has to support teams I don't have, scale I'll never reach, and content models I'll never use. Generality is the right call when you're selling to thousands of people. It's pure overhead when the user count is one.
That's the part worth taking with you, whatever you build. The cost of building exactly the tool you need has fallen far enough that "it has to work for everyone" is no longer free — it's a tax you pay in complexity for users who may not exist. Sometimes the sharpest thing you can do is design for precisely your own situation and refuse, on purpose, to handle anyone else's.
Mine runs on localhost, ships to nobody, and fits like a hand in a glove. That was always the point.