Open Source Project: Why I Built the ScribeCMS ecosystem on AT Protocol

Open Source Project: Why I Built the ScribeCMS ecosystem on AT Protocol

Anthony Cregan
Anthony Cregan

UI Developer (react.js), Designer Of Webs, Home Entertainment Device Surgeon, Cycling Enthusiast, Militant Atheist, Mancunian Separatist. Most productive 4:45am

@anthonycregan.dev

Estimated Reading Time

5 Minutes

Published

08:32 Thursday 9th July 2026

Updated

07:49 Monday 13th July 2026

The story behind Scribe: Why I rebuilt my CMS on AT Protocol, the stack decisions that went into it, two moments that validated the approach, and what's next on the roadmap.

Why I Built Scribe on AT Protocol

Whenever I want to properly learn a new technology, I rebuild my CMS. ScribeCMS v5 is the latest result of that habit and this time, the technologies I was interesting in exploring were AT Protocol and Agentic Coding with Claude Code.

Scribe is a custom content management system, designed to be lightweight and built specifically for writing longform content. That's a deliberate reaction to what's on offer elsewhere. WordPress, for a lot of people, is overkill; a large, general-purpose platform that brings with it an ongoing maintenance burden: plugin updates, security patches, and general upkeep, all of that is a lot of overhead just to run a blog. Scribe is built to do one thing well instead.

Why AT Protocol?

Previous versions of Scribe stored content in a database on the server. It worked, but it wasn't portable. Moving that content anywhere else meant a migration project in its own right. AT Protocol solved that problem structurally rather than procedurally. Your PDS, where your data is stored, is always yours and you can move it anywhere you want without breaking any external references to your content.

AT Protocol's ethos is about giving users true ownership of the content they create. The best way I've found to explain it is with an analogy: if you write your content on a typical CMS (particularly a paid one), you're putting your content in someone else's box. AT Protocol gives you your own box. You can take it off Bluesky and move it to your own PDS (Personal Data Server), or to a different one entirely, and none of the references to that content, links from other sites or links from your own site, need to change. Your content stays resolvable wherever it lives, because a user's DID (their decentralized identifier) describes where their content is currently stored. I haven't yet put that migration through its paces myself, but that resolution mechanism is the actual guarantee AT Protocol is built on. It's not a nice-to-have bolted on top, it's the founding ethos that drove the development of ATproto in the first place.

That ownership model was a natural fit for what a CMS is supposed to do, and a clear improvement on server-side storage that doesn't move.

The stack, and why each part earned its place

Scribe's storage decision was about learning something new. The rest of the stack wasn't, it was about picking and using the right tool for the job.

I needed server-side rendering, and I have a lot of experience with Remix and React Router Framework, so that's what I reached for. TypeScript is my preferred language for web application development, full stop. Neither of those choices was an experiment; they were the correct, boring answer to "what should this be built in", which left the AT Protocol integration as the one genuinely new variable to learn from.

Around the CMS itself, I built and published `@scribe-atp/core` and a set of framework adapters as an SDK (NPM), alongside companion apps like Reader and the accompanying Documentation Site. That's more upfront engineering than a single application strictly needs, and it was a deliberate choice: I'm building Scribe for my own use, but with a view to it being useful to the wider AT Protocol community too. Providing production-ready solutions for the problems people will hit integrating AT Protocol content into their own sites, rather than leaving them to solve DID resolution and PDS queries from scratch. This is the value proposition ScribeCMS provides that makes it a genuinely better option to other developers and authors and not just a personal project other people happen to be able to see.

Validation, and a rough edge worth mentioning

Two moments from building Scribe are worth calling out, because they say more than any feature list could about how this was actually built.

The first was realising that the schema we'd built ourselves, app.scribe.article, looked remarkably similar to site.standard.document lexicon, a standard emerging independently, collaboratively, across the AT Protocol community (Read more Here). When your own conclusions about how to store and resolve articles converge with what an entire collaborative ecosystem arrives at separately, that's a strong signal you're solving the problem the right way. It's also why migrating from our own schema to the shared standard was reasonably smooth, and clearly worth doing.

The second was less about AT Protocol and more about how I used AI coding assistance to work with it. I'd built smaller AT Protocol projects before Scribe (NoRobots.blog was the first attempt) but that integration was hacky: I wasn't resolving the user's DID at all, just pulling data directly from my own PDS. Having Claude Code work through the correct approach for Scribe (properly resolving a user's DID, querying their PDS, and handling the result in a typesafe way) didn't just fix that gap, it was a clear demonstration of the right way to integrate with AT Protocol, and it changed how I use coding assistants generally: not just for speed, but as a way of learning the correct pattern while building the real thing. That's really the throughline of this whole project; the only way to actually understand a new technology or tool is to take it in hand, stress test it, and find out where the rough edges are. That applies as much to AT Protocol as it does to the coding assistants I used to build on top of it.

Where Scribe is going

Scribe has passed MVP. Today, it supports writing, storing, and editing content, decorating articles with images from the fully featured built-in image library, integrating that content into public websites via the SDK, and letting readers like, subscribe to, and share content. Right now, it's also integrated with Umami for engagement analytics, though I plan to support other analytics providers over time.

The next challenge is collaboration, letting an author invite other people to contribute articles to their site. That sounds simple until you consider that a contributor's content lives on their own PDS, entirely separate from the site owner's. Making that work means solving both an organisational problem (inviting someone, having them accept, having them submit an article, having the owner review and approve it) and the underlying engineering problem of coordinating that safely across two independent accounts. It's a genuinely interesting problem, and it's the one I'm working through right now.

Beyond that, the roadmap includes closer integration with Bluesky itself, comment threads and messaging built directly on the content and richer subscription options, including email notifications alongside the existing Bluesky-based ones.

Why this matters beyond Scribe

I'm sharing this because the same approach applies to any project: pick the stack that's actually right for the problem, be able to explain why, and when a new piece of the puzzle is genuinely unfamiliar, don't just read about it, build with it until you've found where it breaks. If you're weighing whether to move content or data off a platform that's locked you in, or you need a modern, server-rendered site built quickly and correctly the first time, that's exactly the kind of problem this approach is built for.