Real-time collaboration
Apollon's collaboration layer is built on Yjs. Set collaborationEnabled: true in the constructor options, then wire your transport. The editor doesn't care whether messages travel over WebSocket, WebRTC, BroadcastChannel, or anything else — it hands you opaque base64 strings to ship and accepts them back.
const editor = new ApollonEditor(container, {
type: UMLDiagramType.ClassDiagram,
collaborationEnabled: true,
})
// Outbound: the editor calls your callback when it has bytes to send.
editor.sendBroadcastMessage((base64) => transport.send(base64))
// Inbound: forward every received frame back to the editor.
transport.onMessage((base64) => editor.receiveBroadcastedMessage(base64))
Backing transports
Any Yjs-compatible transport works. The standalone server uses a custom WebSocket relay (see standalone/server/src/ws.ts); other deployments commonly use:
y-websocketfor self-hosted WebSocket relaysy-webrtcfor peer-to-peery-indexeddbfor offline persistence (layered alongside any other transport)- Any HTTP/3 stream or BroadcastChannel if your room is browser-local
Awareness (cursors, selections)
Awareness state — who's online, where their cursor is, what they have selected — rides on the same channel as document updates. The editor manages awareness internally; you don't need to wire anything beyond sendBroadcastMessage / receiveBroadcastedMessage.
Server-side integration
If you want to drive the wire protocol from a Node server (integration tests, headless conversion, replication), use the unstable @tumaet/apollon/internals subpath:
import {
createHeadlessSync,
MessageType,
type YjsSync,
} from "@tumaet/apollon/internals"
/internals is explicitly not covered by SemVer. The standalone server's integration tests pin against it.