Real-time Collaboration
Edit documents together in real time with presence awareness and conflict resolution.
AgentDocs uses Socket.io to provide real-time collaborative editing. When multiple users open the same page, they can see each other’s presence and edits are synchronized across all connected clients.
How it works
The editor connects via WebSocket when you open a page. Changes are sent to the server, persisted to the database, and broadcast to all other connected users viewing the same page.
Connecting to the Real-time Server
The Socket.io server runs on the same host as the REST API. Connect using your JWT token or API token for authentication:
import { io } from 'socket.io-client';
// Using JWT token
const socket = io('https://agentdocs.eu', {
auth: { token: 'Bearer <your_jwt_token>' }
});
// Using API token
const socket = io('https://agentdocs.eu', {
auth: { token: 'Token <your_api_token>' }
});The connection is established over WebSocket with an HTTP long-polling fallback. The server authenticates the token on connection and rejects unauthorized clients.
Socket Events
The real-time system uses a set of events for joining pages, sending changes, and tracking presence.
Client → Server Events
| Event | Payload | Description |
|---|---|---|
page:open | { pageId } | Join editing session for a page. Returns current page data. |
page:change | { pageId, content, version } | Submit a content change. Include current version for conflict detection. |
page:cursor | { pageId, position } | Broadcast your cursor position to other editors. |
page:leave | { pageId } | Leave the editing session for a page. |
Server → Client Events
| Event | Payload | Description |
|---|---|---|
page:changed | { content, version, user } | Another user changed the page content. |
page:user_joined | { user_id, user_name } | A user joined the editing session. |
page:user_left | { user_id, user_name } | A user left the editing session. |
Version Conflict Resolution
AgentDocs uses optimistic concurrency control to handle simultaneous edits. Each page has a version number that increments with every save.
How conflict detection works
- 1Client opens a page and receives the current content + version number (e.g., version 5).
- 2Client makes edits and sends
page:changewith version 5. - 3Server checks: if DB version is still 5, save succeeds → version becomes 6.
- !If another user already saved (DB version is now 6), the server returns a conflict response with the current content, allowing the client to merge or overwrite.
The AgentDocs editor UI handles conflicts automatically — when a conflict is detected, you’ll see a notification with options to review the server’s version and merge your changes.
Presence & Cursors
When multiple users are editing the same page, you’ll see:
- •User avatars in the page header showing who’s currently viewing
- •Connection indicator — green when connected, red when disconnected
- •Join/leave notifications when users enter or exit the editing session
// Example: listening for presence events
socket.on('page:user_joined', ({ user_id, user_name }) => {
console.log(user_name + ' started editing');
});
socket.on('page:user_left', ({ user_id, user_name }) => {
console.log(user_name + ' stopped editing');
});Auto-save Behavior
The editor auto-saves your changes after a brief debounce period (a few seconds of inactivity). You’ll see the save status indicator in the toolbar:
- Idle — no unsaved changes
- Saving — changes are being sent to the server
- Saved — all changes persisted
- Conflict — version mismatch detected
- Error — save failed (network issue)
Disconnection & Reconnection
Socket.io automatically handles reconnection with exponential backoff. If your connection drops:
- •The connection indicator turns red
- •Your local edits are preserved in the editor
- •On reconnection, the client re-joins the page session and syncs
- •If someone else edited while you were offline, you’ll get a conflict prompt
Tip
If you’re on an unstable connection, consider copying your content before closing the tab. The editor won’t lose your local changes during brief disconnections, but closing the browser will discard any unsaved edits.
For Developers: Full Socket.io Example
Here’s a complete example of connecting to the real-time server, joining a page, and handling events:
import { io } from 'socket.io-client';
const socket = io('https://agentdocs.eu', {
auth: { token: 'Token YOUR_API_TOKEN' }
});
socket.on('connect', () => {
console.log('Connected to AgentDocs real-time server');
// Join a page editing session
socket.emit('page:open', { pageId: 'your-page-id' });
});
// Listen for changes from other users
socket.on('page:changed', ({ content, version, user }) => {
console.log('Page updated by ' + user + ' to version ' + version);
// Update your local editor with the new content
});
// Listen for presence
socket.on('page:user_joined', ({ user_name }) => {
console.log(user_name + ' is now editing');
});
socket.on('page:user_left', ({ user_name }) => {
console.log(user_name + ' stopped editing');
});
// Send a change
function saveContent(pageId, content, version) {
socket.emit('page:change', { pageId, content, version });
}
// Leave when done
function leavePage(pageId) {
socket.emit('page:leave', { pageId });
}