From 288e9c07f2c93df57b84d2f9f46bb373be89db35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Mon, 23 Mar 2026 07:30:00 +0100 Subject: [PATCH] Fix cross-window Yjs sync: broadcast doc updates to all connections The Vite Yjs plugin was only sending sync responses back to the sender, not broadcasting updates to other WebSocket connections in the same room. This caused cross-window sync to only work via BroadcastChannel (same browser context), not across separate browser windows/incognito. Fix: Add doc.on('update') listener that broadcasts updates to all connections in the room except the origin sender. Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/planner/app/lib/vite-yjs-plugin.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/planner/app/lib/vite-yjs-plugin.ts b/apps/planner/app/lib/vite-yjs-plugin.ts index 13383ec..db10d9c 100644 --- a/apps/planner/app/lib/vite-yjs-plugin.ts +++ b/apps/planner/app/lib/vite-yjs-plugin.ts @@ -28,6 +28,21 @@ export function yjsDevPlugin(): Plugin { awareness = new awarenessProtocol.Awareness(doc); awarenessMap.set(docName, awareness); + // Broadcast doc updates to all connections in this room + doc.on("update", (update: Uint8Array, origin: unknown) => { + const encoder = encoding.createEncoder(); + encoding.writeVarUint(encoder, messageSync); + syncProtocol.writeUpdate(encoder, update); + const message = encoding.toUint8Array(encoder); + + for (const [ws, meta] of conns) { + // Don't send back to the origin connection + if (meta.docName === docName && ws !== origin && ws.readyState === ws.OPEN) { + ws.send(message); + } + } + }); + awareness.on("update", ({ added, updated, removed }: { added: number[]; updated: number[]; removed: number[] }) => { const changedClients = added.concat(updated, removed); const encoder = encoding.createEncoder();