Overview
The@yoopta/collaboration package enables real-time collaborative editing in Yoopta Editor. Multiple users can edit the same document simultaneously with automatic conflict resolution powered by Yjs CRDT.
The package provides:
withCollaborationextension — connects your editor to a collaboration server- Collaborative undo/redo — Cmd+Z only undoes your own changes, not other users’
- Remote cursors — see where other users are editing
- Awareness — track connected users and their presence
- React hooks — access collaboration state in your components
Installation
@yoopta/collaboration requires @yoopta/editor >= 6.0.0-beta.19 and React >= 18.2.0 as peer dependencies.Quick Start
Wrap your editor withwithCollaboration — similar to how withMentions works:
Configuration
withCollaboration(editor, config)
Extends a YooEditor instance with collaboration capabilities. Returns a CollaborationYooEditor.
The editor instance from
createYooptaEditor().Configuration object for the collaboration session.
CollaborationConfig
WebSocket server URL. Example:
"wss://collab.yoopta.cloud"Unique identifier for the document/room. All users with the same
roomId will collaborate on the same document.Information about the current user. Used for cursor labels and presence indicators.
Authentication token sent to the server on connection. Use this to verify users and check subscription access on the server side.
Initial content to seed the document if no remote state exists. When the first user connects to an empty room, this value populates the shared document.
Whether to connect to the server immediately. Set to
false to connect manually later via editor.collaboration.connect().Optional: provide your own Yjs
Y.Doc instance. If not provided, one is created automatically. Useful for advanced integrations or testing.Editor API
After applyingwithCollaboration, the editor gains an editor.collaboration namespace:
editor.collaboration.state
Read-only access to the current collaboration state.
editor.collaboration.connect()
Manually connect to the WebSocket server. Only needed if connect: false was passed in config.
editor.collaboration.disconnect()
Disconnect from the server. The editor remains usable for local editing.
editor.collaboration.destroy()
Disconnect and clean up all resources (WebSocket, observers, awareness). Call this on component unmount.
editor.collaboration.getDocument()
Returns the underlying Y.Doc instance for advanced use cases.
Components
<RemoteCursors />
Renders visual indicators showing which block each remote user is currently editing.
<YooptaEditor>. Displays a colored bar and name label next to the block each remote user is editing.
Hooks
All hooks must be used within a<YooptaEditor> component that has collaboration enabled.
useCollaboration()
Returns the full collaboration state. Re-renders on any state change.
useConnectionStatus()
Returns only the connection status string. Lighter than useCollaboration() when you only need the status.
useRemoteCursors()
Returns an array of remote cursor data for all connected users.
Deferred Connection
If you need to connect after the editor is rendered (e.g., after authentication), setconnect: false:
Custom Y.Doc
For advanced use cases (e.g., testing two editors in the same page), you can provide your ownY.Doc:
Self-Hosted Setup
@yoopta/collaboration uses Yjs only as a sync layer — it does not store your documents. Your content remains standard Yoopta JSON (YooptaContentValue) that you store in your own database.
Persisting to Your Database
Load content from your database asinitialValue, and save back on change:
The
initialValue is only used when the first user connects to an empty room. Once the Y.Doc has content (from any client), subsequent connections load from the Y.Doc state, not from initialValue.Running Your Own WebSocket Server
Any Yjs-compatible WebSocket server works. The simplest option is y-websocket:Yoopta Cloud
For teams that don’t want to run their own collaboration infrastructure, Yoopta Cloud provides a managed solution:- Managed WebSocket infrastructure with automatic scaling
- Built-in document persistence and version history
- Authentication and room-level permissions
- Comments and threads
- REST API for document access
- Webhooks for integrations (search indexing, backups, workflows)
- Analytics dashboard
Yoopta Cloud is coming soon. The self-hosted path described above will always remain free and open-source.
How It Works
Under the hood,@yoopta/collaboration maintains a bidirectional binding between the Yoopta editor and a Yjs shared document:
- Local changes flow through
editor.applyTransformsand are automatically synced to the Y.Doc, then sent to the server via WebSocket. - Remote changes arrive via WebSocket, update the Y.Doc, and are applied to the editor without entering the local undo/redo history.
- Conflict resolution is handled by the Yjs CRDT — concurrent edits are merged automatically at the character level.
- Undo/redo uses Yjs
UndoManagerto selectively reverse only local changes (see below).
Undo / Redo
When collaboration is active,editor.undo() and editor.redo() (Cmd+Z / Cmd+Shift+Z) automatically use Yjs UndoManager instead of the default history stack. This means:
- Only your changes are undone — if Alice types “Hello” and Bob types “World”, Alice pressing Cmd+Z removes only “Hello”. Bob’s text stays intact.
- Works at all levels — text edits, block insertions, deletions, splits, merges, formatting, and metadata changes are all tracked.
- No extra setup needed —
withCollaborationoverrides undo/redo automatically. When collaboration is destroyed, the default history behavior is restored.
The initial document content (loaded from the server or seeded via
initialValue) is not undoable — only edits made after the document loads can be undone.TypeScript
All types are exported from the package:WebSocketProvider
For advanced server integrations, theWebSocketProvider class is exported:

