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.
| Layer | Choice | Why this one |
|---|---|---|
| protocol | Matrix | Open, federated, a decade of E2EE hardening — and we validated it hands-on before committing. |
| homeserver | Synapse (Python, upstream) | The reference implementation. We deploy and configure it; we don’t fork it. |
| platform server | Elixir + Phoenix | Massive-concurrency messaging workloads are the BEAM’s home turf; supervision trees make partial failure a normal day. |
| jobs | Oban (open source) | Postgres-backed queue — reliable retries for push and media work with no extra broker to operate. |
| database | PostgreSQL 15 | One database technology for homeserver and platform state alike. |
| media | S3-compatible storage + CDN | Content-addressed media behind a CDN; works on any provider that speaks S3, so self-hosters aren’t locked in. |
| web client | React + TypeScript + Vite | Mainstream, typed, fast to onboard into. |
| mobile client | React Native (planned) | One client team across iOS and Android, sharing logic with the web client. |
| mobile updates | self-hosted OTA deltas (planned) | Binary-delta over-the-air updates from our own infrastructure — fixes reach phones without store-review lag. |
| branding | typed brand-config package | A schema-validated TypeScript package holding every brandable surface. The site you’re reading consumes the same token shapes. |
| infra | GCP, as numbered scripts | VM, networking, Postgres, Synapse, storage, CDN — reproducible from infra/scripts/00…07. Nothing exists only in a console. |
How the repo is laid out
| Path | What 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.