stack & components

Boring where it should be, opinionated where it counts

Every dependency earns its place. The rule of thumb: protocol and crypto come from Matrix’s hardened implementations; everything we write ourselves stays in two languages (Elixir on the server, TypeScript on the clients) so a contributor can hold the whole system in their head.

LayerChoiceWhy this one
protocolMatrixOpen, federated, a decade of E2EE hardening — and we validated it hands-on before committing.
homeserverSynapse (Python, upstream)The reference implementation. We deploy and configure it; we don’t fork it.
platform serverElixir + PhoenixMassive-concurrency messaging workloads are the BEAM’s home turf; supervision trees make partial failure a normal day.
jobsOban (open source)Postgres-backed queue — reliable retries for push and media work with no extra broker to operate.
databasePostgreSQL 15One database technology for homeserver and platform state alike.
mediaS3-compatible storage + CDNContent-addressed media behind a CDN; works on any provider that speaks S3, so self-hosters aren’t locked in.
web clientReact + TypeScript + ViteMainstream, typed, fast to onboard into.
mobile clientReact Native (planned)One client team across iOS and Android, sharing logic with the web client.
mobile updatesself-hosted OTA deltas (planned)Binary-delta over-the-air updates from our own infrastructure — fixes reach phones without store-review lag.
brandingtyped brand-config packageA schema-validated TypeScript package holding every brandable surface. The site you’re reading consumes the same token shapes.
infraGCP, as numbered scriptsVM, networking, Postgres, Synapse, storage, CDN — reproducible from infra/scripts/00…07. Nothing exists only in a console.

How the repo is laid out

PathWhat lives there
server/The Elixir/Phoenix platform server: OTP auth, messaging glue, push fan-out, media pipeline, Oban workers, and its test suite.
clients/web/The React + TypeScript web client.
packages/brand-config/The white-label layer: brand schema, the Xoyo reference brand, and build tooling for adding your own.
infra/Numbered provisioning scripts, Synapse config templates, and the ops runbook. Secrets stay out of git by convention and by .gitignore.
spike/The validation spike that proved the architecture before we built on it — kept as evidence, with its full report.

Tools we build with

Quality gates

The server ships with formatter, static analysis, and tests wired into one command; the clients use TypeScript strictness and Vitest. Green checks are the price of entry for every commit.

Decision records

ADRs capture every irreversible call — protocol, licensing, trust boundary, auth model, platform separation — so newcomers inherit the why, not just the what.

Docker for the heavy pieces

Synapse and its dependencies run containerized in dev and on the server, so “works on my machine” stays true on everyone’s machine.

Comfortable in this stack?

If Elixir, TypeScript, or Matrix internals are your thing — or you want them to be — there’s well-scoped work waiting.