The End of Server-Dependent Messaging
What if your messaging app didn’t need a server?
Not “serverless” in the cloud-marketing sense. Actually serverless. Messages stored as encrypted files on any static host. GitHub Pages as your message broker. An S3 bucket as your chat server. A USB drive as your air-gapped secure channel.
That’s what we shipped this week.
The Static File Insight
Every encrypted messaging system I’ve studied — Signal, Matrix, WhatsApp, Keybase — requires server-side logic for at least one of these:
- Message routing (who gets what)
- Message storage (holding messages until delivery)
- Key exchange (establishing shared secrets)
- Presence/delivery (online status, read receipts)
We eliminated all four.
Routing: Messages are published to a known URL path. Clients poll or subscribe. No routing logic needed.
Storage: Encrypted JSON files on a static host. Append-only. The host doesn’t even need to know it’s hosting a messaging system.
Key exchange: A single JSON file (we call it an “egg”) contains the conversation key. Share it however you want — iMessage, QR code, hand-delivered USB.
Presence: Head hash comparison. Fetch the manifest, compare the hash of the latest message. Changed? Pull the new messages. Same? Do nothing. Incremental sync over HTTP GET.
Why This Matters for AI
When AI agents communicate, they shouldn’t depend on a specific platform’s infrastructure. An agent running on your laptop should be able to message an agent running on your phone, or an agent running in a cloud VM, or an agent running on a Raspberry Pi.
The common denominator isn’t WebSockets. It isn’t gRPC. It isn’t any particular messaging protocol.
It’s HTTP GET.
Every device on Earth can fetch a file from a URL. That’s the only primitive you need for messaging. Everything else — encryption, signing, PII protection — is layered on top at the application level.
The Sync Model
Our system uses what I’d call “campfire sync”:
- Messages are written to the local store immediately (instant display)
- The local store is the source of truth
- A background process publishes new messages to the static host
- Other clients fetch from the static host on their own schedule
- Optional: bridge to platform-native messaging (iMessage, Telegram) for push notifications
This means:
- Offline-first: You can compose and read messages without network access
- Latency-tolerant: The UI shows messages instantly; network sync is eventual
- Platform-independent: The static host could be anything
- Censorship-resistant: If one host goes down, mirror the files elsewhere
The Digital Twin Pattern
We call the local-first, instant-display layer the “digital twin.” It’s a real-time representation of the conversation that exists ahead of any network sync.
When you send a message:
- It appears in the digital twin immediately (status: instant)
- Background: PII is stripped, content is encrypted, HMAC is computed
- Background: published to the static host (status: syncing)
- Background: optionally delivered via iMessage (status: delivered)
The user sees step 1 immediately. Steps 2-4 happen asynchronously. If any of them fail, the message is still in the digital twin — nothing is lost.
What We Didn’t Build
We didn’t build:
- A federation protocol (files + HTTP is simpler)
- A custom transport layer (HTTP GET is enough)
- A key server (eggs are shared out-of-band)
- A user directory (participants are just names in a channel)
Every feature we didn’t build is a feature that can’t break, can’t be compromised, and can’t be shut down by a third party.
Try It
RappterSignal is part of OpenRappter. Start the gateway, open /signal.html, create a channel. Share the egg with a friend. Their device fetches the encrypted files, verifies the signatures, decrypts with the shared key.
No account. No server. No platform.
Just encrypted files and a key.
Building in the open at github.com/kody-w/openrappter.