Subchapter 157.13
examples/collaborate-mode.mdMarkdown4 KBView on GitHub
Real-time shared app state across all meeting participants.
Collaborate mode lets participants share an app experience simultaneously - like Google Docs for Zoom Apps. When one user makes a change, all participants see it in real time.
import zoomSdk from '@zoom/appssdk';
await zoomSdk.config({
capabilities: [
'startCollaborate', 'onCollaborateChange',
'connect', 'postMessage', 'onConnect', 'onMessage',
'getMeetingUUID'
],
version: '0.16'
});
// Host starts collaborate mode
await zoomSdk.startCollaborate({
shareScreen: true // Also share the app screen
});
// Listen for collaborate state changes
zoomSdk.addEventListener('onCollaborateChange', (event) => {
console.log('Collaborate state changed:', event);
});Best for apps with a backend. Server is the source of truth.
// Frontend
const socket = io('https://your-server.com');
const meetingUUID = await zoomSdk.getMeetingUUID();
socket.emit('join-room', { roomId: meetingUUID.meetingUUID });
// Send state changes
function updateState(key, value) {
socket.emit('state-update', { key, value });
}
// Receive state changes
socket.on('state-update', ({ key, value }) => {
applyStateChange(key, value);
});No server needed. Direct peer messaging via connect() + postMessage().
// All participants connect
await zoomSdk.connect();
zoomSdk.addEventListener('onConnect', () => {
console.log('Connected to other instances');
});
// Send state to all connected instances
async function broadcastState(state) {
await zoomSdk.postMessage({
payload: JSON.stringify({ type: 'state-sync', data: state })
});
}
// Receive state from other instances
zoomSdk.addEventListener('onMessage', (event) => {
const message = JSON.parse(event.payload);
if (message.type === 'state-sync') {
applyState(message.data);
}
});Best for collaborative editing (text, whiteboards). Conflict-free resolution.
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
// Use meeting UUID as room name
const meetingUUID = await zoomSdk.getMeetingUUID();
const ydoc = new Y.Doc();
const provider = new WebrtcProvider(meetingUUID.meetingUUID, ydoc, {
signaling: ['wss://your-signaling-server.com']
});
// Shared state automatically syncs via CRDT
const sharedMap = ydoc.getMap('app-state');
// Update state (syncs to all peers automatically)
sharedMap.set('counter', (sharedMap.get('counter') || 0) + 1);
// Observe changes
sharedMap.observe((event) => {
event.keysChanged.forEach((key) => {
console.log(`${key} changed to:`, sharedMap.get(key));
});
});Note: The texteditor sample app uses public Y.js signaling servers. For production, host your own signaling server.
import zoomSdk from '@zoom/appssdk';
let count = 0;
async function init() {
await zoomSdk.config({
capabilities: ['connect', 'postMessage', 'onConnect', 'onMessage'],
version: '0.16'
});
await zoomSdk.connect();
zoomSdk.addEventListener('onMessage', (event) => {
const msg = JSON.parse(event.payload);
if (msg.type === 'count-update') {
count = msg.count;
render();
}
});
render();
}
async function increment() {
count++;
render();
await zoomSdk.postMessage({
payload: JSON.stringify({ type: 'count-update', count })
});
}
function render() {
document.getElementById('counter').textContent = count;
}Use getMeetingUUID() to get a unique room ID for state synchronization:
const { meetingUUID } = await zoomSdk.getMeetingUUID();
// Use as Socket.io room, Y.js document name, Redis key, etc.This UUID is unique per meeting instance and consistent across all participants.