Wednesday, 30 April 2025 · vwwwv.org
vwwwv
opinion

The case for treating drafts as state, not files

I built a CMS this weekend in which the editor is a chat window and the publish action is a tool call. There is no editor. There is no draft folder. There is, instead, a row in a database with a status column, and a conversation that knows how to read and write that row.

I built a CMS this weekend in which the editor is a chat window and the publish action is a tool call. There is no editor. There is no draft folder. There is, instead, a row in a database with a status column, and a conversation that knows how to read and write that row.

The architecture follows from a simple observation: I had been using Claude as my drafting tool for six months. Every "blog post I should write" was already a conversation. The only step I never finished was the part where I copy-pasted to a markdown file, committed it, and pushed.

So I removed that step. Here's what fell out.

Drafts stop being files

When the source of truth is a database row with status = 'draft', you don't have to decide where the file lives, what its filename should be, whether the slug is final, what branch it's on, or whether your laptop or your phone has the latest copy. The row knows. The row is the same row regardless of which device you opened the conversation from.

The "publish" affordance becomes a button

In a chat surface, "publish" is a one-tap prompt suggestion that fires an authenticated request to a Worker. The Worker writes to the database and the next request to the homepage sees the post. End-to-end propagation: thirty seconds, mostly DNS.

What you give up

A code-based escape hatch, mostly. If you want to publish a post by writing a markdown file in your editor and pushing, you have to build that path separately — a CLI that hits the same Worker endpoint. I haven't yet. It's on the list.

What you don't give up

Git. The site code is still in git. Backups, history, branches — all the normal version-control affordances continue to apply to the system. The content is in a database, where revisions are first-class rows and the publish-state is a column that can be flipped without a deploy.

This is not for everyone. If you like writing in your editor, keep writing in your editor; that workflow has been good for thirty years and will continue to be. But I've been writing fewer blog posts every year, and the bottleneck was always the saving and committing. Removing it has moved the number from zero to nonzero, which is a much larger improvement than people give it credit for.