Skip to main content
Open a document in two tabs, two browsers, or two continents: keystrokes appear live, and everyone always converges on the same result. There are no locks, no merge dialogs, and no “refresh to see changes.”

CRDT sync with Yjs

Each document is a Yjs CRDT shared with every connected editor over a WebSocket. Edits are exchanged as small incremental updates, and the CRDT guarantees that all replicas converge to the same state regardless of the order updates arrive in — including edits made by two people in the same word at the same time. Because convergence is a property of the data type, brief disconnections are harmless: a client that drops offline keeps editing locally, resyncs its missed updates on reconnect, and merges cleanly with whatever happened while it was away. Undo is scoped per user: Cmd+Z reverts your own edits, never a collaborator’s.

Presence

Everyone connected to a document sees:
  • Remote cursors and selections, colored per user and labeled with their name.
  • Avatars of active collaborators in the document header.
Presence uses the Yjs awareness protocol on the same WebSocket as document sync, so it costs no extra connections.

One Durable Object per document

Every document is backed by its own Cloudflare Durable Object — a single-threaded authority that holds the live Y.Doc:
  • Sync and awareness run over hibernating WebSockets, so an idle document costs nothing while connections stay open.
  • Access control is enforced at connect time and per message: users with viewer or commenter roles get a read-only connection that receives every update live but cannot write.
  • The REST API goes through the same object. PUT /api/docs/{id}/content applies its change to the live CRDT as a diff, so an API write shows up in every open editor instantly — and concurrent human edits merge with it instead of being overwritten.
  • Snapshots of the CRDT state and its serialized markdown are persisted, so a document survives eviction, hibernation, and deploys.

Comments stay anchored

Comment and suggestion threads reference Yjs relative positions rather than plain text offsets, so discussions stay attached to the right text while everyone edits around them.