Skill: WebSocket & Yjs Collaboration
SkillWeb & browsingModifying real-time collaboration features including WebSocket handlers, Yjs documents, and room lifecycle. Every change must ship with colocated tests (`*.spec.ts` server-side, `*.test.js` client-side), keep patch coverage ≥ 90% on changed lines, include or update a multi-user Playwright spec using the `collaboration.fixture`, and pass `make fix`, `make test-unit`, `make test-integration`, and `make test-e2e` before submission.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Skill: WebSocket & Yjs Collaboration skill
What this skill tells your AI
The instructions your AI receives, as published by exelearning/exelearning in .agents/skills/websocket-yjs/SKILL.md and read by ahel’s review.
Parent: AGENTS.md | Related: frontend-module, backend-service
When to Use
Modifying real-time collaboration, WebSocket handling, or Yjs document management.
Key Files
Server-side:
src/websocket/*.ts— WebSocket handlers (room management, persistence, asset coordination)src/websocket/room-manager.ts— room lifecycle managementsrc/websocket/yjs-websocket.ts— WebSocket route creationsrc/websocket/yjs-persistence.ts— Yjs document persistencesrc/yjs/*.ts— Yjs document helpers
Client-side:
public/app/yjs/YjsDocumentManager.js— Y.Doc management (source of truth)public/app/yjs/YjsStructureBinding.js— binds Yjs state to UIpublic/app/yjs/YjsProviderFactory.js— WebSocket provider creationpublic/app/yjs/AssetManager.js— Cache API asset managementpublic/app/yjs/ResourceCache.js— theme/library cachepublic/app/yjs/*.test.js— colocated tests
Documentation: doc/development/real-time.md
Architecture
CLIENT owns Y.Doc (source of truth)
↕ WebSocket (stateless relay)
SERVER: lightweight metadata only
- Does NOT store Y.Doc in memory
- Persists snapshots to yjs_documents table
- Forwards messages between clients
The server is a stateless relay. All document state lives in the browser's Y.Doc.
Concurrency Patterns
Deferred Page Reload
When User B creates an iDevice while User A is editing, User A's editor must not be force-closed. Instead, defer the reload:
// In YjsProjectBridge: defer reload when editor is active
const hasActiveEditor = document.querySelector('#node-content div.idevice_node[mode="edition"]');
if (hasActiveEditor) {
this._deferredPageReload = pageId;
return;
}
// In idevicesEngine: execute deferred reload when exiting edition
this.project._yjsBridge?.executeDeferredPageReload?.();
Late Joiner Resync
When a new user joins, the y-websocket handshake may be incomplete. Use awareness-triggered resync plus server trigger-resync as belt-and-suspenders.
Commands
bun test src/websocket/room-manager.spec.ts # Server tests
npx vitest run public/app/yjs/YjsDocumentManager.test.js # Client tests
make fix # Lint
Gotchas
- Server must NEVER store Y.Doc in memory — it's a stateless relay. Violations break the architecture.
connectWebSocket()—YjsDocumentManageruses this method, NOTsetupWebSocketProvider. Using the wrong method name will silently fail.MockWebsocketProviderneedsconnect()anddisconnect()— tests that test resync behavior will fail without these methods on the mock.- UUIDs in test data must be hex —
extractProjectUuidrejects non-hex characters. Use[0-9a-f-]{36}format. - Concurrent editing data loss — the most dangerous class of bug. When two users edit the same page, ensure neither loses work. Always test: User A editing + User B creates iDevice on same page → User A's editor must survive. Example: PR #1540.
- Asset coordination uses separate JSON protocol — over the same WebSocket connection, but distinct from Yjs binary messages.
- Reconnection safety —
AssetWebSocketHandler._handleStatusalready re-sets up the message handler on reconnect. It's safe to disconnect/connect.
Done When
- Server changes:
.spec.tsat 90%+ coverage - Client changes:
.test.jsat 80%+ coverage - Server remains stateless relay (no Y.Doc storage)
- Concurrent editing scenarios tested (two-user interactions)
-
make fixpasses clean
Signals
- GitHub stars
- 142
- Forks
- 32
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
websocket-yjs- Source
- github.com/exelearning/exelearning