The write-up above is the design. This is the build log: actually standing up Wavelink, phase by phase, bugs included.
No password, just a name. But that name is real now: claim it once, and coming back later with the same one resumes the same inbox instead of erroring out or starting over. Two tabs, two names, is the whole test of "a phone and a laptop."
A message gets written to the recipient's queue first, then pushed if they're connected. That's the offline-delivery design from the write-up above, actually running. Close a tab mid-conversation, reopen it, the messages are exactly where you left them.
Sent, delivered, read, each one its own event, not a guess. Getting "delivered" right took a real bug first: the status :delivered did not exist as an Erlang atom until the moment two people actually messaged each other, and the channel crashed the first time anyone tried. Fixed, and now tested for it.
An earlier version marked a message "read" the moment it arrived, whether anyone was looking or not. It only flips green now when that specific conversation is the thing actually open on screen, closing the gap between what the tick claims and what a person did.
Online and offline dots come from Phoenix Presence, not a fake timer. Open the same username in two tabs and both agree on who's around, updating live, including the moment either one disconnects.
Signing in as the same user on two tabs used to mean they didn't know about each other: a message sent from one never showed up on the other. Every send now also reaches your own other devices, the same idea as WhatsApp Web staying in sync with your phone.
Two layers, on purpose. A real browser notification when a chat isn't the thing on screen, and a Notifications page inside the app for everything missed while the tab was closed, because a push can always get lost and a durable list can't.
It still looks and feels like a demo, not a product, so that's first. After that: group chats, media messages, real end-to-end encryption, access control, and actually deploying this instead of running it on a laptop.