Back to work
In active development2026Solo — Full-Stack & Mobile (backend, crypto core, native apps)45% complete

Enigma

A privacy-focused native chat app — Nearby discovery plus an opt-in, truly end-to-end-encrypted private tier — with one Rust crypto core shared across iOS and Android.

Summary

Enigma is a modern, native take on a Telegram-style messenger built around two things most chat apps don't have together: discovering people physically Nearby (within a radius, or across a city), and an opt-in Private chat tier that is genuinely end-to-end encrypted via MLS (RFC 9420). It keeps the two tiers cleanly separated — an open cloud tier that syncs across devices with full history, and a private tier where the server only ever relays opaque ciphertext and cannot read the conversation. Native Swift (iOS, ~30k LOC) and Kotlin (Android, ~38k LOC) clients share a single Rust crypto + protocol core (~6.7k LOC) bridged into both apps via UniFFI, so there is one source of truth instead of two divergent crypto implementations. The backend is Elixir / Phoenix on the BEAM, built for holding many simultaneous realtime connections, with Phoenix Channels over WebSocket for delivery, PostgreSQL for users and messages, and phone-number login via Twilio Verify. The backend, realtime delivery, phone-number auth, and the encryption core are built and working; the native apps are in progress (Android first), with the iPhone client built to parity behind it.

Target user

People who want a modern, native messenger that does two things mainstream apps don't do together: discover and message people physically Nearby, and opt into a private tier where the server only relays opaque ciphertext and literally cannot read the conversation. The architecture targets a future where the realtime layer holds large numbers of concurrent connections on the BEAM.

§ 01Stack
01Primary
SwiftKotlinRustElixir / PhoenixPostgreSQL
02Infrastructure
Phoenix ChannelsOpenMLSUniFFIScyllaDB
03Integrations
Twilio VerifyMLS group messagingAPNs / push
04UI / Frontend
SwiftUIJetpack ComposeShared design-token system
§ 02Key features
  1. 01

    Two clearly separated chat tiers — an open cloud tier that syncs across devices and keeps full history, and an opt-in Private tier that is end-to-end encrypted so the server can only relay opaque ciphertext

  2. 02

    Nearby discovery — find and message people physically around you within a radius or across a city, distinct from the cloud-synced social graph

  3. 03

    One shared Rust security core for the crypto and message protocol, written once and bridged into both iOS and Android via UniFFI — no duplicated, divergent crypto implementations

  4. 04

    Real MLS (RFC 9420) end-to-end encryption via OpenMLS — encrypted messages round-trip between two parties, proven by the Rust core's test suite

  5. 05

    Realtime delivery on Phoenix Channels over WebSocket, running on the BEAM, designed for large numbers of concurrent connections

  6. 06

    Phone-number login with a one-time code (OTP) via Twilio Verify — no passwords

  7. 07

    Device-held encrypted store for the private tier (since it isn't stored server-side) that the user can back up themselves

  8. 08

    A single master design system — colors, type, spacing, motion — defined once as tokens and mirrored across the Swift and Kotlin apps

§ 03Hardest problems
§ 04What I learned
  • L01
    Write the dangerous code once.

    Putting all of the end-to-end encryption and protocol logic in a single Rust core and bridging it into both apps via UniFFI means there's exactly one place to audit and one place a bug can live — far safer than maintaining parallel Swift and Kotlin crypto that look identical until the day they aren't.

  • L02
    Separate the tiers at the architecture level, not the UI level.

    'Open cloud chat' and 'private end-to-end chat' aren't a toggle on the same pipe — they're two different trust models. Designing them as genuinely separate paths (server-as-source-of-truth vs. server-as-blind-relay) keeps the privacy guarantee honest instead of marketing.

  • L03
    Pick the backend for the shape of the load.

    Chat is a connection-count problem, not a throughput problem — most sockets are open and idle. The BEAM is built precisely for holding many simultaneous lightweight connections, which is why Elixir / Phoenix was the right base layer even before scale is a real constraint.

§ 05By the numbers
rust core loc
6717
rust core files
32
swift loc
29725
kotlin loc
38282
elixir loc
10374
elixir files
159
git commits
293
native platforms
2
chat tiers
2
team size
1
encryption
MLS / RFC 9420 (OpenMLS)
realtime
Phoenix Channels / WebSocket