Real-time DOCX collaboration with React, Vue 3, and Yjs
Connect React or Vue 3 DOCX editors through WebRTC, Hocuspocus, or Yjs. Synchronize documents, presence, comments, and tracked changes.
@docx-editor.dev/pro connects React and Vue 3 DOCX editors through Yjs. Each
participant edits a local document replica. A provider moves updates between
the replicas. Choose Web Real-Time Communication (WebRTC), Hocuspocus, or a
custom Yjs provider.
The collaboration module replicates the complete DOCX package. This includes text, formatting, tables, headers, footers, notes, drawings, relationships, and embedded parts. It also synchronizes participant presence and remote selections. When you enable review features, comments, tracked changes, and review decisions stay synchronized.
Install collaboration for React
Install the editor, Pro package, Yjs, and the WebRTC provider:
npm install @docx-editor.dev/core @docx-editor.dev/react \
@docx-editor.dev/pro yjs y-webrtcVue 3 applications use @docx-editor.dev/vue instead of
@docx-editor.dev/react.
Collaboration is part of @docx-editor.dev/pro. You can evaluate it under the
EigenPal Pro
License.
Production use requires a commercial agreement. See the pricing page
for available plans.
Connect a WebRTC room
Create one room ID and share it with each participant. Keep the room ID in application state or in the URL. Do not create a new ID during each render.
Create the room ID with createCollaborationRoomId:
import {
createCollaborationRoomId,
} from '@docx-editor.dev/pro/collaboration/webrtc';
const roomId = createCollaborationRoomId();The roomId identifies the signaling topic. It is not an authorization token.
For encrypted signaling, put a shared secret in the URL fragment as
#collab=<secret>. The WebRTC helper uses that fragment as its password. Do not
use the room ID as the password.
This React component creates or joins a room:
import { DocxEditor } from '@docx-editor.dev/react';
import { useWebrtcCollaboration } from '@docx-editor.dev/pro/react/webrtc';
interface CollaborativeEditorProps {
roomId: string;
bytes: Uint8Array;
actorId: string;
name: string;
}
export function CollaborativeEditor({
roomId,
bytes,
actorId,
name,
}: CollaborativeEditorProps) {
const { document, modules, session, pending, error } =
useWebrtcCollaboration({
room: {
roomId,
identity: { actorId, name },
bootstrap: { kind: 'create-or-join', document: bytes },
},
});
if (error) return <p>{error.detail ?? error.code}</p>;
if (pending || !document) return <p>Connecting…</p>;
return (
<DocxEditor
key={session?.sessionId}
document={document}
modules={modules}
/>
);
}Each participant must use a unique actorId. To prevent concurrent seeding in
this basic setup, open the first editor before the second editor. If two
isolated peers seed the same room simultaneously, every replica reports
concurrent-seed. To recover, create a new room from saved bytes.
Vue 3 provides the same composable at
@docx-editor.dev/pro/vue/webrtc. For a complete Vue 3 component, see Connect
with useWebrtcCollaboration.
Choose a provider
Use the provider that matches your deployment:
- WebRTC connects small peer rooms directly. Production deployments need private signaling and Traversal Using Relays around NAT (TURN) servers.
- Hocuspocus provides server-backed rooms, authentication, and persistence.
- A custom Yjs provider connects an existing Yjs deployment through
createDocumentCollaborationoruseDocumentCollaboration.
The WebRTC helper uses a public signaling service when you omit signaling.
Use this service only for development. Configure your own signaling URLs and
TURN servers for production.
If you use Hocuspocus, import useHocuspocusCollaboration from
@docx-editor.dev/pro/react/hocuspocus or
@docx-editor.dev/pro/vue/hocuspocus.
Handle room state
Always render error, even after document becomes available. A successful
initial connection does not prevent a later authentication, schema, resource,
or replication failure.
An error state is terminal for that replica. Save its current bytes and call
rejoin(bytes) to join the room again. The room copy wins after a successful
rejoin, so the operation can drop changes that never reached the room.
Editing pauses during a transport disconnection by default. If participants
must edit while disconnected, set offlineEditing: true. The session merges
those edits after reconnection. Continue to show the connection state because
the edits have not reached other participants yet.
Treat the room as the document
The room is authoritative while collaboration is active. A saved .docx is a
snapshot of the room at one moment. The API does not merge an externally edited
file back into the same room.
When collaboration ends, export the room and make that file authoritative again. To use an externally edited file, create a new room from those bytes and retire the old room.
Server code can export synchronized room state with
readCollaborationDocument(ydoc). DocxEditor.createCollaborative attaches an
editing API replica without a browser.
Watch room growth
A Yjs room grows as edits add records and tombstones. Deleted media also stays
in shared state. Use session.resourceUsage() to monitor the room and archive
it before it reaches a resource limit.
The default seed limit is 20 MB. One embedded file can use up to 32 mebibytes (MiB), and all embedded files can use up to 64 MiB. The collaboration reference documents the complete limits and typed failure codes.
Next steps
- Get started with DOCX collaboration: connect two React or Vue 3 editors through WebRTC.
- DOCX collaboration reference: configure presence, recovery, offline editing, Hocuspocus, and custom providers.
- Peer-to-peer collaboration example: run the WebRTC room locally.
- Server-backed collaboration example: add Hocuspocus authentication, persistence, and export.
- Build a DOCX agent: attach a headless agent to the synchronized room.
