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
createDocumentor restored withloadDocument. 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
roomandserverprops build it for you; for a shared document, attach a factory such ascreateWebsocketSync(options)withdocument.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 withattachDocument(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
One browser, no persistence. Pass a value or a document and edit. Several views can share it.
IndexedDB
Keep the document in the browser. Survives reloads and syncs open tabs, with no server.
WebSocket room
Real-time editing between people through the Durable Object room, with a local copy for offline work.
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
Documents
createDocument, loadDocument, readiness, several views and headless use.
Persistence
IndexedDB, the local copy, offline behavior and cross-tab sync.
WebSocket
createWebsocketSync options, provider events, saved state and reconnects.
Presence
User names and colors, remote carets and selections.
Concurrent editing
What people see when they delete, undo, split and move at the same time.
Server
Deploy the Durable Object room in a few steps.