There’s a persistent gap in the federated web tooling landscape. On one side you have full-featured applications like WriteFreely or Plume that speak ActivityPub natively but require a database, a running web server, and real operational overhead. On the other side you have static site generators that produce fast, portable, zero-dependency sites but sit completely outside the social graph of the fediverse. Madblog sits in the middle, and examining where exactly it draws the line reveals something useful about what federation actually costs.
The premise is disarmingly simple: point Madblog at a folder of markdown files, and it federates them. Posts show up in Mastodon timelines. People can follow your blog from their fediverse account. Replies and likes come back to you. The content lives in plain files you can version-control, back up, or move to another machine without running a migration script.
What ActivityPub Actually Requires
ActivityPub is a W3C specification from 2018 that defines a server-to-server and client-to-server federation protocol built on top of Activity Streams 2.0. The mental model is simple enough: every user is an Actor with a public URL, an inbox (a POST endpoint), and an outbox (a GET endpoint). Publishing means pushing Activity objects (specifically Create wrapping an Article or Note) to your followers’ inboxes.
For a blog to participate in this network, the minimum required surface is:
- WebFinger at
/.well-known/webfingerso other servers can discover your actor URL from anacct:user@domainhandle - Actor JSON at some stable URL, including your public key for HTTP signature verification
- Inbox at a POST endpoint that can receive
Follow,Undo(Follow),Like, andAnnounceactivities - Outbox as a paginated
OrderedCollectionof your posts - A delivery mechanism that signs and sends
Createactivities to every follower’s inbox when you publish something new
Items 1, 2, and 4 can be static files. Items 3 and 5 cannot. This is the fundamental constraint that prevents any truly static site generator from being a first-class ActivityPub participant without an external bridge.
The HTTP Signature Problem
The part that trips up most DIY federation attempts is HTTP signatures. When your server delivers a Create activity to mastodon.social’s shared inbox, the request must be signed with your RSA private key. Mastodon and most other servers will silently drop unsigned deliveries. The signature covers the Date, Host, Digest, and (request-target) headers using the format defined in the HTTP Signatures draft.
The public key half of this keypair gets embedded in your Actor JSON under publicKey.publicKeyPem. Every server that wants to verify your deliveries fetches your Actor, extracts the key, and checks the signature. Rotating that key requires re-fetching your Actor from every server that has ever cached it, which is why most implementations treat it as effectively immutable.
Madblog handles key generation on first startup and stores the keypair alongside your markdown content. It’s a small detail but a meaningful one: the signing key becomes part of your blog’s identity in the same way your domain name does.
Why the Follower List Can’t Be a Static File
One tempting shortcut is to treat the followers collection as read-only data you maintain by hand. In practice, this breaks almost immediately. When a Mastodon user clicks Follow, their server sends a Follow activity to your inbox and expects an Accept in return within a reasonable timeout. If you don’t respond, they’re not actually following you and your deliveries won’t reach them. The protocol is interactive.
This means your inbox handler needs to be live, not a static endpoint. Madblog runs a lightweight server process that listens for incoming activities, updates the followers list on disk, and sends Accept responses. The followers list itself is just a JSON file in your content directory, which preserves the portability of the overall approach. There’s no separate database process, no schema to migrate.
The tradeoff is that your blog needs an always-on process with a routable IP, which is the same requirement any other self-hosted ActivityPub server has. What Madblog avoids is the operational complexity that typically comes with that requirement: no PostgreSQL, no Redis, no separate application server, no migration tooling.
Note vs. Article: What Shows Up in Mastodon
ActivityPub defines both Note (short-form, think microblog post) and Article (long-form, with a title and URL) object types. Madblog publishes your blog posts as Article objects, which is semantically correct. The problem is that Mastodon’s rendering of Article objects is minimal: it shows the title and a link, not the full content. The full text is only visible if the viewer clicks through to your actual blog.
This isn’t a bug in Madblog; it reflects a real tension in the ActivityPub ecosystem. Most fediverse clients were built for microblogging first and treat anything that isn’t a Note as a second-class object. WriteFreely has dealt with the same issue since its early days, and its solution was to post a truncated Note alongside the Article so the preview renders cleanly in Mastodon timelines. It’s an inelegant workaround, but it works.
The Comparison Landscape
WriteFreely is the most direct comparison. It’s a Go application that implements ActivityPub properly, supports multi-user instances, and has a clean writing interface. But it requires a database (SQLite or MySQL), produces no portable artifact you can store in git, and adds meaningful deployment complexity if you’re self-hosting.
Plume aimed at a similar niche with Rust and ActivityPub support, but development has been slow for years and the deployment story involves PostgreSQL and a full web stack.
The more philosophically interesting comparison is Bridgy Fed, Ryan Barrett’s project that bridges IndieWeb-style sites to ActivityPub. If your blog publishes h-entry microformats and handles webmentions, Bridgy Fed can act as a proxy that makes you visible in the fediverse without you running any ActivityPub code at all. Your content stays fully static; the bridge handles all the federation mechanics. The cost is that your fediverse identity lives at bridgy-fed.domain rather than your own domain.
Ghost added ActivityPub support in late 2024, but positioned it specifically around newsletter distribution rather than general federation. It’s useful if you already run Ghost, but it’s not a solution for someone who wants simplicity.
What the File-First Approach Gets Right
The substantive advantage of Madblog’s design is portability and longevity. Your blog content exists as plain markdown files. You can move it between machines with rsync. You can version-control it with git. You can read it with any text editor. If Madblog stops being maintained in five years, your content is fully intact and readable without any data export step.
This is meaningfully different from a database-backed blog, where your content is effectively locked in a schema until you run an export tool, hope the export format is stable, and find an import path to wherever you’re going next.
The approach also makes the code surface small enough to actually audit. The ActivityPub implementation in a focused tool like this is a few hundred lines rather than the layered complexity of a full platform. For a personal blog where you’re the only user, most of the feature surface of WriteFreely or Ghost is irrelevant anyway.
The real question is whether your hosting environment supports a persistent process. Shared hosting with PHP usually doesn’t. A small VPS running systemd does. The infrastructure requirement is modest, but it is a real requirement. You can’t deploy Madblog to Netlify or Cloudflare Pages and get federation for free.
A Useful Point on the Spectrum
What makes Madblog worth thinking about is where it sits: past static site generators that can’t federate at all, but short of heavyweight platforms that bring in operational complexity you don’t need for a personal blog. The tradeoffs are honest. You give up zero-infrastructure hosting; you get a writing workflow that’s just a text editor and a folder, federation that works without a database, and content you actually own in a format that will outlast the software.
For personal blogging specifically, that’s a trade most people who care about the fediverse would take.