examples/live-notes Public
---id: presencetype: conceptowner: justinreviewed: 2026-10-15component: note-roomdescribes: - src/presence.ts - src/note-room.ts - client/editor.ts---# PresenceThe room knows who has each note open. It gives every editor a name and a color, tellseveryone when someone joins or leaves, and marks each op it passes on with who made it.## Who is hereWhen a socket connects, the room lists the editors on the sockets already open and picks aname and a color nobody there is using (`pickEditor()`). Names come from a fixed list oftwelve animals; past twelve editors they repeat with a number. The editor is stored on thesocket with `serializeAttachment`, and the room sends:- to the newcomer, after the snapshot: `presence` with everyone here and `you` set to itself;- to everyone else: `presence` with the new list.When a socket closes or errors, the room sends the remaining list to everyone left. Every`presence` message carries the whole list, so an editor that misses one is corrected by thenext, and the page never has to apply joins and leaves in order.The id is random per connection. The same person in two tabs is two editors, and a reloadgets a new name if the old one was taken in the meantime.## Why nothing is storedThe list of who is here is the list of open sockets, by definition. Writing it to SQLite wouldadd a second copy that can disagree with the first after a crash or a deploy. See[[0003-presence-lives-on-the-sockets]].## On the page`client/editor.ts` keeps the latest `here` list and renders it above the textarea, a coloreddot and a name per editor, with "(you)" on its own entry. When an `op` arrives, the pagelooks `by` up in that list and shows "typing" next to the name for a second and a half. Whilethe socket is down the list is cleared, since the page no longer knows.## Who made an edit`op` broadcasts carry `by`, the id of the sender, read from the sending socket's attachment.The room does not check `by` againstanything: it comes from the room itself, never from the editor.