Skip to content
Edytor
Esc
↑↓navigate↵open⌘Jpreview
On this page

Collaboration

How edytor shares one document between views, browser tabs and people, and which setup to pick.

Every edytor document is a CRDT: edits from any number of views, tabs and people merge on their own, without a central lock and without losing work made offline. This section covers the document object, the providers that persist and transport it, presence, and the editing rules users see when they edit together.

How it fits together

One document is one EdytorDocument. It owns the CRDT state, a document API (the facade), one undo history, one awareness instance for presence, and the local author identity. Views render it; providers keep it in sync.

  • The document is created with createDocument or restored with loadDocument. It works with no view at all (Node, SSR, tests) or behind any number of <Edytor> views. See Documents.
  • A sync attaches a provider to the document. On a view, the room and server props build it for you; for a shared document, attach a factory such as createWebsocketSync(options) with document.attachSync(…). The provider lives as long as the document, not the view.
  • Awareness carries presence: who is here, their name and color, and their selection. Every view and provider shares the document’s single awareness instance. See Presence.
  • The room is DocumentRoom, a Cloudflare Durable Object that edytor ships, or any Durable Object of yours with attachDocument(this). You deploy it on your own account; it authorizes sockets through your code, stores the document in SQLite and relays edits. See Server.

When two replicas meet, whether a tab and the server or two tabs, each tells the other what it already holds, and each sends back what the other lacks. There is no “last save wins”: offline edits merge the next time a connection opens.

Choose your setup

Local only

<script lang="ts">
  import { Edytor } from 'edytor';

  const value = { children: [{ type: 'paragraph', content: [{ text: 'Hello' }] }] };
</script>

<Edytor {value} />

IndexedDB

room alone names a local copy:

<Edytor room="notes/today" />

WebSocket room

Add a server, and the view joins the room <server>/<room>:

<Edytor
  server="wss://rooms.example.com/rooms"
  room="doc-42"
  params={{ token }}
  actor={{ id: userId, name: 'Ada' }}
/>

The room keeps a local IndexedDB copy too, so the third setup also covers the second. params travel with each connection (see the server quick start); actor names the author for undo, attribution and presence.

In this section

Was this page helpful?