Prototypes DuetP14 · Editor for two
The relay

What the editor’s relay holds

Every document the relay keeps and the latest entries of its log, read every 2 seconds. The relay numbers each update, keeps it and passes it to the other people on the document. It never has the key, so it cannot read a letter of the text, a name or where anyone’s cursor is.

Documents

DocumentEntriesSizePeople nowMerged

The latest entries

EntryKindSizeCiphertext
How Duet is built
  1. The document is a Yjs document bound to ProseMirror, drawn with the design system’s blocks. Letters typed at the same time on two devices merge in place.
  2. The key is 32 random bytes in the link, after the #. A browser never sends that part to a server. The document’s id on the relay is a hash of the key.
  3. Every Yjs update and every cursor position is encrypted with AES-GCM before it leaves the browser. The relay keeps the updates in order and passes them on over a WebSocket.
  4. With no network, the edits are kept on the device and sent when the connection is back. A socket that stops answering is closed after 9 seconds, so an edit is never sent into a dead connection.
  5. Versions are Yjs snapshots kept in the document itself, so they are encrypted too. A version is shown with what changed since the one before, and a restore is a new edit, so every later version stays in the history.
  6. The relay cannot merge what it cannot read, so a device sends the whole document, encrypted, when the log grows past 60 entries, and the relay replaces the entries it covers.

Keys: ⌘B bold, ⌘⇧X strike, ⌘E code, ⌘Z undoes only your own edits. Type # for a heading, a hyphen for a list, 1. for a numbered list, [] for a checklist and > for a quote.