Omicron: A Home for Free Expression on the Fediverse
There are a lot of places to write online. Fewer places where the platform doesn't own your voice.
Omicron is a federated blogging platform — Medium-like in feel, but built on ActivityPub instead of a walled garden. You write, you publish, you follow other writers, and none of it is locked behind a company's servers or subject to a company's rules. If you can run a Docker container, you can run your own instance and own your words, permanently.
Why Omicron exists
Most blogging platforms ask you to trade reach for control. Publish on a big platform and you get an audience, but the platform can change the rules, bury your posts, monetize your attention, or shut down entirely — and your writing goes with it. Run your own blog instead, and you get control, but you write into a void: no built-in audience, no feed, no way for readers on other platforms to follow you without leaving their own.
ActivityPub — the same open protocol behind Mastodon, and the broader fediverse — solves that trade-off. Every Omicron instance is a full participant in a decentralized social network. A writer on one instance can be followed by a reader on a completely different instance, on a completely different platform, without either of them signing up for a third party's service. Federation is the whole point: reach without lock-in.
Omicron's mission rests on three ideas:
Fediverse-native. No vendor lock-in, no gatekeepers. Every user is an ActivityPub actor from day one, not a bolt-on feature.
Modern and simple. A clean, distraction-free reading and writing experience, backed by a small, readable codebase — simple over clever, everywhere.
Freedom of expression. Your instance, your rules, your data. Omicron is built so that running your own space is realistic, not just theoretically possible.
What it feels like to use
Underneath, Omicron is a blog. Rich-text posts written in a real editor (Tiptap, with full Markdown support), a personalized feed built from who you follow, and profile pages that read like a clean writing space rather than a dashboard. Nothing about the day-to-day experience should feel like "federated software" — it should just feel like a good place to write and read.
The federation happens underneath that experience, not instead of it. Follow a writer on another Omicron instance, or on any ActivityPub-speaking service, and their posts show up in your feed like anyone else's. Publish a post, and it's delivered out to your followers across the network as a standard ActivityPub Create(Note), signed and verified the way the rest of the fediverse expects.
Self-hosting that doesn't feel like a chore
A federated platform is only as free as it is easy to run yourself, so Omicron treats setup as a first-class feature, not an afterthought:
curl -fsSL https://raw.githubusercontent.com/the-jk-labs/omicron/main/install.sh | shOne command, no config file to hand-edit — the database password and session secret are generated on first boot. Point a domain at the box, and the bundled Caddy reverse proxy fetches a Let's Encrypt certificate on demand; there's no certbot dance, no domain hardcoded anywhere. The first account you create becomes the instance admin, and everything else — federation toggles, instance name, users — is managed from a web admin panel, not a text editor.
Upgrades are git pull and a rebuild. Migrations run automatically and are additive-only within a version, so an upgrade never breaks a running instance. Your data, uploads, and certificates live in named volumes untouched by the rebuild.
The stack is engine-agnostic by design — Docker or Podman, rootless or not — because "self-hostable" that only works on one specific setup isn't really self-hostable.
Architecture: clean layers, no shortcuts
Omicron's codebase follows one hard rule: layers never mix.
apps/backend (Deno + Hono)
routes/ HTTP only — parse the request, call a service, serialize the response
services/ business logic — no HTTP, no SQL
db/ Drizzle schema + repositories — the only place SQL runs
federation/ ActivityPub (Fedify) — fully isolated, loaded only when enabled
queue/ a queue.add(name, payload) abstraction, in-process today, swappable later
apps/frontend (SvelteKit)
routes/ pages (SSR) + a reverse-proxy to the backend
lib/api/ typed API client, same-origin, cookies flow naturally
lib/components/ui/ bits-ui headless component wrappers
lib/editor/ Tiptap integration, lazy-loaded on the compose pageA few decisions fall directly out of the "keep it simple, keep it correct" goal:
Repository pattern, no exceptions. Routes and services never call Drizzle directly — every database access goes through a repository function. It's a small amount of ceremony that buys a codebase where you can find every query in one place.
Cursor pagination everywhere. Keyset pagination on
(created_at, id), neverOFFSET, because offset pagination quietly gets slower and less correct as a table grows.Server-side sessions, not JWTs. A Postgres
sessionstable plus an httpOnly cookie. The app stays stateless at the process level; all real state lives in the database, which makes horizontal scaling and backups straightforward.Federation is fully isolated. The entire
federation/tree and the Fedify library are only imported whenFEDERATION_ENABLED=true. Run Omicron as a plain standalone blog, and none of the ActivityPub code even loads — federation is additive, never a tax you pay by default.Queue-ready from day one.
queue.add("federate_post", …)runs in-process now, but the call sites and payload shapes already match a future Redis/broker-backed queue. When an instance needs to scale delivery, it's a swap of one file, not a rewrite of the call sites scattered through the codebase.
On the frontend, the same philosophy shows up as a strict UI rule: every primitive — buttons, dialogs, tooltips, tabs — comes from bits-ui, styled with a single consistent set of design tokens, rather than one-off Tailwind colors sprinkled across the app. The aim is a UI that looks and behaves like one coherent system, not a collage of components each styled slightly differently.
What "federated" actually gets you
With federation enabled and a real domain, every Omicron user becomes a discoverable ActivityPub actor: a WebFinger lookup, an actor document, an inbox and outbox, exactly like the account model the rest of the fediverse already understands. Inbound follows are auto-accepted, new posts go out to remote followers, and Fedify handles the unglamorous but essential parts — HTTP signatures, delivery retries — so that the protocol correctness doesn't leak into product code.
The practical result: a small Omicron instance run by one person can be followed, read, and boosted by people on Mastodon, on other Omicron instances, or on any future platform that speaks ActivityPub. The network effect belongs to the protocol, not to a single company's servers.
License and the promise behind it
Omicron is licensed AGPL-3.0-or-later. That choice isn't incidental — it's the license clause that matters most for a project built around "your instance, your rules, your data." Because Omicron is normally run as a network service, AGPL §13 means that anyone who runs a modified version and lets others use it over the network must make that modified source available to those users. Omicron surfaces a "Source" link in the UI specifically so instance operators can point it at their fork. The freedom to fork, modify, and run your own version is protected the same way the freedom to read and write on it is.
Where this is headed
Omicron is still early, but the shape is intentional: a genuinely federated blog, a codebase simple enough that a newcomer (human or AI) can read it end to end, and a self-hosting experience that respects people's time. Every design decision gets weighed against the same three questions — does this keep the platform federation-friendly, does this keep the codebase simple, and does this make it easier for someone to speak freely on their own terms. If a feature would restrict expression to make something else more convenient, that's the wrong trade.
Write your own words. Host them yourself. Let them travel across the network without asking anyone's permission.
