stack & components

Boring where it should be, opinionated where it counts.

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

LayerChoiceWhy this one
protocolMatrixOpen, federated, a decade of end-to-end encryption hardening. Validated hands-on before we committed.
homeserverSynapse (upstream, containerized)The reference implementation. Deployed and configured, never forked.
platform serverElixir + PhoenixMassive-concurrency messaging is the BEAM’s home turf; supervision trees make partial failure a normal day.
bridgeMatrix Application Service in the same Elixir appA Gupshup-v2-shaped HTTP API and HMAC-signed webhooks, with golden-fixture contract tests pinning the live-verified shapes.
jobsOban (open source)Postgres-backed queue: reliable retries for push, media and webhook delivery with no extra broker.
databasePostgreSQL 15One database technology for homeserver and platform state alike.
mediaS3-compatible storage + CDNContent-addressed media on any provider that speaks S3, so self-hosters aren’t locked in.
web clientReact + TypeScript + ViteMainstream, typed, fast to onboard into. Matrix crypto via the official JavaScript SDK.
mobile clientReact NativeOne client team across iOS and Android, sharing logic with the web client. Device encryption via the Matrix Rust SDK is the next tier.
mobile updatesself-hosted OTA deltas (planned)Binary-delta over-the-air updates from our own infrastructure, so fixes reach phones without store-review lag.
brandingtyped brand-config packageA schema-validated TypeScript package holding every brandable surface. This site consumes the same token shapes.
infranumbered scripts, GCP firstVM, networking, Postgres, Synapse, storage, CDN, reproducible from scripts 00 to 07; a local Docker Synapse for every verification run.
pipelinecheck → review → smoke, agent-drivenA scripted pipeline builds a task with a sandboxed agent, runs the suites, reviews against a written checklist, and verifies live. Two-strike breaker, auto-filed follow-ups.

How the repo is laid out

PathWhat lives there
server/The Elixir/Phoenix platform server: OTP auth, push fan-out, media pipeline, Oban workers, the Layer-2 bridge, contract fixtures, and the test suite.
clients/web/The React + TypeScript web client.
clients/mobile/The React Native mobile client for iOS and Android.
packages/brand-config/The white-label layer: brand schema, the Xoyo reference brand, and tooling for adding your own.
infra/Numbered provisioning scripts, Synapse config templates, the local Docker stack, and the ops runbook. Secrets stay out of git by convention and by ignore rules.
scripts/check.sh, smoke.sh, release-local.sh, the nightly pipeline orchestrator and its headless build and review hooks.
evidence/JSON evidence from every smoke run, kept as the record of what was verified when.
website/This site. Static, dependency-free, served by any static host or the included nginx container.

Tools we build with

Quality gates

One command runs the formatter, the server suite, the golden-fixture contract tests, and the client type checks and tests. It also runs as the push gate. A green run is the price of entry for every commit.

Live smoke evidence

A second command boots Synapse and the server, registers accounts, messages, exchanges media, checks cross-signing, round-trips the bridge, and writes JSON evidence. Green tests alone never mark a task done.

Decision records and a ledger

Architecture decisions are numbered and immutable. Every deferred fix gets a ledger row with a testable close condition, allocated under a lock so ids never collide.

Comfortable in this stack?

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