Collaborative editor integration

The collaborative editor uses CollabSession from @modula/editor plus a signaling endpoint.

Runtime responsibilities

CollabSession handles:

  • Peer discovery/presence.
  • Soft block locks.
  • Signal fanout for lock/unlock/transaction/version events.
  • WebRTC negotiation (offer, answer, ice-candidate) and DataChannel messaging.

Server endpoint contract

Default route pattern in Modula REST:

  • GET /api/collab/:ref_id/signal?peer_id=<uuid>&held_locks=id1,id2
  • POST /api/collab/:ref_id/signal
  • DELETE /api/collab/:ref_id/signal?peer_id=<uuid>

GET returns:

{
  "peers": {
    "peer-id": { "userId": "u1", "name": "Alice", "image": null }
  },
  "signals": [
    { "id": "s1", "from": "peer-id", "type": "transaction", "data": [] }
  ],
  "locks": {
    "block-id": { "peerId": "peer-id", "userId": "u1", "name": "Alice", "image": null }
  }
}

Client integration

import { CollabSession, setCollabSessionContext } from '@modula/editor';

const session = new CollabSession(`/api/collab/${refId}/signal`).start();
setCollabSessionContext(session);

// Keep state aligned with remote operations.
session.on('transaction', (ops) => {
  editorState.apply(...ops);
});

// Optional: version reconciliation.
session.on('version', (versionId) => {
  console.info('Remote version', versionId);
});

On teardown:

await session.destroy();

Wiring locks in UI

Form already consumes collab context and applies lock semantics:

  • On focus: lock current block (collab.lock(block.id)).
  • On blur: unlock block (collab.unlock(block.id)).
  • Remote locks disable editing and can display lock badges.

Suggested save + version flow

  1. User applies local edits (transactions).
  2. Broadcast operations via session.transaction(tx).
  3. Save snapshot to backend.
  4. Broadcast canonical version id via session.setVersion(versionId).

This pattern reduces divergence and gives peers a stable synchronization boundary.

Notes

  • Locks are soft, TTL-based (presence heartbeat refreshes them).
  • Collaboration authorization is enforced server-side per ref_id.
  • If collaboration is unavailable, set collab context to null and keep editor in local mode.