CollaborationExtension
Headless, transport-agnostic real-time collaboration for LexKit, built on Lexical's own collaboration binding and Yjs (a CRDT — offline edits merge conflict-free on reconnect).
Live demo
Open this page in a second browser tab and start typing. Same-origin tabs sync peer-to-peer via the browser's BroadcastChannel, so this demo needs no server at all.
Collaborative editor
Open in two tabs and type — synced peer-to-peer, no server.
Install
The extension ships with LexKit. You add yjs and a transport of your choice — they are optional peer dependencies.
Quick start
The only required option is providerFactory — the single seam where you plug in a transport. LexKit never bundles one, and the extension stays inert until it's set.
Choose a transport
Anything implementing the Yjs Provider interface works.
y-websocket
y-webrtc
y-indexeddb (offline)
Presence
Build any presence UI with the headless useCollaborators() hook, or drive it imperatively through commands.collab.
useCollaborators()
commands.collab
Themeable cursors
Remote carets are rendered by Lexical's reliable cursor binding into a container you can style via the theme, and each user's color comes from cursorColor. Supply your own cursorsContainerRef to portal carets anywhere.
theme.collab
Offline & reliability
Yjs is a CRDT: when a client drops offline and keeps editing, then reconnects, all edits merge automatically with no data loss and every replica converges to the same state. Add y-indexeddb to persist a client's edits locally so they survive reloads and replay on reconnect. This behaviour is identical no matter how content is imported (Markdown, HTML or JSON) — collaboration syncs the editor state itself.
Notes
- Undo/redo & history: Yjs owns history while collaborating. Lexical's collaboration binding does not wire a Yjs undo manager, so do not register
historyExtensionat the same time as the collaboration extension. - Initial content: exactly one client should seed the document (
shouldBootstrap, defaulttrue). Set it tofalseon clients that join an existing room. - Multiple editors on one page: wrap each editor in its own collaboration context so they don't share a Yjs document map.
- Custom nodes: exclude transient props (e.g. an image's
uploadingflag) from sync viaexcludedProperties.