# FRE-587: Real-time Collaboration Layer with WebSocket + WebRTC **Issue Key:** FRE-587 **Parent:** FRE-574 (Technical evaluation for WriterDuet competitor) **Priority:** High **Timeline:** Months 3-4 (after core editor foundation) **Status:** Planned --- ## 1. Architecture Overview ### High-Level Design The collaboration layer consists of three interconnected systems: ``` ┌─────────────────────────────────────────────────────────────┐ │ Tauri Desktop App │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ SolidJS UI │ │ CRDT Engine │ │ WebRTC Video │ │ │ │ (Editor) │◄─┤ (Yjs) │◄─┤ (PeerJS) │ │ │ └──────┬───────┘ └──────┬───────┘ └────────┬─────────┘ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ WebSocket Connection Manager │ │ │ │ (Auth, Presence, Sync, Conflict Resolution) │ │ │ └──────────────────────────┬───────────────────────────┘ │ └─────────────────────────────┼───────────────────────────────┘ │ ┌─────────▼─────────┐ │ WebSocket Server │ │ (Node.js + WS) │ └─────────┬─────────┘ │ ┌────────────────────┼────────────────────┐ │ │ │ ▼ ▼ ▼ ┌────────────────┐ ┌──────────────────┐ ┌────────────────┐ │ Presence Hub │ │ CRDT Sync Hub │ │ Signaling │ │ (Redis) │ │ (Yjs + Turso) │ │ (WebRTC) │ └────────────────┘ └──────────────────┘ └────────────────┘ ``` ### Data Flow 1. **Local Edit:** User types → SolidJS editor updates Yjs document → CRDT generates operation 2. **Sync:** Operation sent via WebSocket to server → Server broadcasts to other clients 3. **Merge:** Remote operations received → Yjs applies OT/CRDT merge → UI updates 4. **Presence:** Presence updates broadcast via WebSocket → UI shows active users 5. **Video:** WebRTC peer connection established via signaling → Audio/video streams exchanged ### Key Components | Component | Technology | Responsibility | |-----------|------------|----------------| | CRDT Engine | Yjs | Conflict-free document merging | | WebSocket Client | `ws` (Tauri) | Real-time communication layer | | WebSocket Server | Node.js + `ws` | Sync hub, presence broadcast | | WebRTC Manager | PeerJS | P2P video/audio streaming | | Presence Service | Redis + WebSocket | Track active users/editing state | | Change Tracker | Yjs + custom logic | Version history, merge logic | --- ## 2. Library Selection: Yjs vs Automerge ### Comparison Matrix | Criteria | Yjs | Automerge | |----------|-----|-----------| | **Maturity** | 8+ years, 500k+ npm downloads/week | 5 years, 50k+ npm downloads/week | | **Performance** | Excellent (incremental updates) | Good (full snapshot on read) | | **Bundle Size** | ~18KB (core) | ~25KB (core) | | **Binding Support** | Tauri (Rust), SolidJS, React, Vue | JavaScript, Rust (beta) | | **WebSocket Integration** | Excellent (y-websocket official) | Good (community implementations) | | **WebRTC Integration** | Excellent (y-webrtc official) | Limited (requires custom) | | **Tauri Compatibility** | Native Rust bindings available | Requires JS bridge | | **SolidJS Integration** | Reactive bindings available | Requires wrapper | | **Conflict Resolution** | CRDT (intention-based) | CRDT (Lamport timestamps) | | **Undo/Redo** | Built-in undo manager | Built-in undo stacks | | **Persistence** | IndexedDB, LevelDB, custom | Custom (requires implementation) | | **Community** | Large, active, well-documented | Smaller, niche | | **TypeScript Support** | Excellent (full types) | Good (improving) | | **Enterprise Adoption** | WriterDuet, Notion, Tldraw | Figma (early), Obsidian | ### Recommendation: **Yjs** **Rationale:** 1. **Ecosystem Fit:** Yjs has official `y-websocket` and `y-webrtc` bindings, reducing implementation complexity 2. **Tauri Integration:** Native Rust bindings align with our Tauri desktop architecture 3. **SolidJS Compatibility:** Reactive bindings available; works well with Solid's fine-grained reactivity 4. **Performance:** Incremental updates better suited for real-time collaboration on large documents 5. **Industry Validation:** WriterDuet (our primary competitor) uses CRDT-based sync; Yjs is battle-tested 6. **Bundle Size:** Smaller footprint important for Tauri app startup time (<2s target) 7. **Documentation:** More comprehensive docs and community examples accelerate development ### Yjs Architecture for Our Use Case ```typescript import { Doc } from 'yjs'; import { WebSocketProvider } from 'y-websocket'; import { WebrtcProvider } from 'y-webrtc'; // Document structure for screenplay const doc = new Doc(); const text = doc.getText('main'); // Screenplay content const meta = doc.getMap('metadata'); // Character refs, scene info const presence = doc.getMap('presence'); // User cursors/selections // WebSocket sync (primary) const wsProvider = new WebSocketProvider( 'wss://api.frenocorp.com/sync', 'project-{projectId}', doc ); // WebRTC fallback (P2P when both users online) const rtcProvider = new WebrtcProvider( 'project-{projectId}', doc, { signaling: ['wss://signaling.frenocorp.com'] } ); ``` --- ## 3. Component Breakdown ### 3.1 Core Collaboration Stack #### `WebSocketConnectionManager` **Location:** `src/lib/collaboration/websocket-connection.ts` **Responsibilities:** - Establish and maintain WebSocket connection to sync server - Handle connection state (connecting, connected, disconnected, reconnected) - Implement exponential backoff reconnection strategy - Authenticate connection with JWT token - Send/receive CRDT updates via WebSocket protocol **Interface:** ```typescript interface WebSocketConnectionManager { connect(token: string, projectId: string): Promise; disconnect(): void; sendUpdate(update: Uint8Array): void; onUpdate(callback: (update: Uint8Array, origin: string) => void): void; onStatusChange(callback: (status: 'connecting' | 'connected' | 'disconnected') => void): void; getProvider(): WebSocketProvider; // Yjs provider } ``` #### `CRDTDocumentManager` **Location:** `src/lib/collaboration/crdt-document.ts` **Responsibilities:** - Initialize and manage Yjs document lifecycle - Handle document loading from persistence (Turso/IndexedDB) - Manage Yjs shared types (Text, Map, Array) for screenplay structure - Coordinate local changes with remote sync - Implement undo/redo stacks **Interface:** ```typescript interface CRDTDocumentManager { initialize(projectId: string): Promise; getText(type: string): Text; getMap(type: string): Map; applyRemoteUpdate(update: Uint8Array, origin: string): void; createUndoStack(): UndoManager; destroy(): void; } ``` #### `WebRTCVideoManager` **Location:** `src/lib/collaboration/webrtc-video.ts` **Responsibilities:** - Establish P2P WebRTC connections between collaborators - Manage audio/video stream negotiation - Handle ICE candidate exchange via signaling server - Implement fallback to server-relayed (TURN) when P2P fails - Provide video component integration with SolidJS **Interface:** ```typescript interface WebRTCVideoManager { initialize(projectId: string, localStream: MediaStream): void; connectToPeer(peerId: string): Promise; disconnectFromPeer(peerId: string): void; getLocalStream(): MediaStream; getRemoteStreams(): Map; toggleAudio(enabled: boolean): void; toggleVideo(enabled: boolean): void; } ``` ### 3.2 Presence Layer #### `PresenceManager` **Location:** `src/lib/collaboration/presence.ts` **Responsibilities:** - Track local user's cursor position and selection - Broadcast presence updates to other collaborators - Receive and render remote users' cursors/selections - Implement idle timeout (user marked as inactive after 30s) - Handle user join/leave events **Interface:** ```typescript interface PresenceManager { initialize(doc: Doc, userId: string): void; updateCursorPosition(cursor: CursorPosition): void; updateSelection(selection: SelectionRange): void; getRemoteUsers(): Map; onUserJoin(callback: (user: RemoteUser) => void): void; onUserLeave(callback: (userId: string) => void): void; onUserUpdate(callback: (user: RemoteUser) => void): void; } interface CursorPosition { userId: string; userName: string; position: number; // Yjs text position color: string; // Cursor color for identification } interface RemoteUser { userId: string; userName: string; avatarUrl?: string; cursor?: CursorPosition; selection?: SelectionRange; isEditing: boolean; lastActive: Date; } ``` ### 3.3 Change Tracking & Merge #### `ChangeTracker` **Location:** `src/lib/collaboration/change-tracker.ts` **Responsibilities:** - Record all changes to the document with metadata (user, timestamp, type) - Implement version vector for conflict detection - Track change boundaries for revision highlighting - Support change acceptance/rejection workflow - Generate change diff for version history **Interface:** ```typescript interface ChangeTracker { recordChange(change: DocumentChange): void; getChangesInRange(start: number, end: number): DocumentChange[]; acceptChange(changeId: string): void; rejectChange(changeId: string): void; generateDiff(version1: Snapshot, version2: Snapshot): ChangeDiff; createSnapshot(): Snapshot; restoreSnapshot(snapshot: Snapshot): void; } interface DocumentChange { id: string; userId: string; timestamp: Date; type: 'insert' | 'delete' | 'format'; position: number; length: number; content?: string; accepted: boolean; } ``` #### `MergeLogic` **Location:** `src/lib/collaboration/merge-logic.ts` **Responsibilities:** - Handle complex merge scenarios (concurrent edits to same paragraph) - Implement screenplay-specific merge rules (dialogue vs action blocks) - Resolve conflicts when CRDT produces unexpected results - Provide manual conflict resolution UI fallback **Interface:** ```typescript interface MergeLogic { applyServerChange(change: ServerChange): MergeResult; handleConcurrentEdit(localChange: Change, remoteChange: Change): MergeStrategy; resolveConflict(conflict: Conflict): Resolution; validateMerge(result: MergeResult): boolean; } ``` ### 3.4 UI Components #### `CollaborativeEditor` **Location:** `src/components/editor/collaborative-editor.tsx` **Responsibilities:** - Wrap base screenplay editor with collaboration primitives - Integrate Yjs text binding with editor instance - Render remote cursors and selections - Handle editor focus/blur for presence updates **Props:** ```typescript interface CollaborativeEditorProps { doc: Doc; projectId: string; userId: string; onCollaboratorJoin?: (user: RemoteUser) => void; onCollaboratorLeave?: (userId: string) => void; } ``` #### `VideoChatOverlay` **Location:** `src/components/collaboration/video-chat-overlay.tsx` **Responsibilities:** - Display video feeds from WebRTC peers - Implement toggle for video/audio - Show connection quality indicator - Handle layout (grid view for multiple participants) **Props:** ```typescript interface VideoChatOverlayProps { videoManager: WebRTCVideoManager; position: 'bottom-right' | 'bottom-left' | 'floating'; size: 'mini' | 'normal'; } ``` #### `CollaboratorList` **Location:** `src/components/collaboration/collaborator-list.tsx` **Responsibilities:** - Display list of active collaborators - Show what each user is editing (scene, character, etc.) - Indicate online/offline status - Provide quick video call initiation --- ## 4. Implementation Phases ### Phase 1: Foundation (Weeks 1-2) **Goal:** Establish WebSocket connection and basic CRDT sync **Tasks:** - [ ] Set up Yjs document structure for screenplay - [ ] Implement `WebSocketConnectionManager` with reconnection logic - [ ] Create basic `CRDTDocumentManager` for text sync - [ ] Set up Node.js WebSocket server with `y-websocket` adapter - [ ] Implement JWT authentication for connections - [ ] Create SolidJS bindings for Yjs reactivity - [ ] Write unit tests for CRDT operations **Deliverables:** - Two instances of the app can sync text changes via WebSocket - Basic undo/redo functionality - Connection status indicator **Dependencies:** - FRE-586 (Core screenplay editor) - need editor to attach to - FRE-588 (Database schema) - for project metadata **Blockers:** - WebSocket server infrastructure deployment --- ### Phase 2: Presence & Visibility (Weeks 3-4) **Goal:** Show who is online and what they're editing **Tasks:** - [ ] Implement `PresenceManager` with cursor tracking - [ ] Set up Redis for presence state (optional, for scaling) - [ ] Create `CollaboratorList` component - [ ] Implement remote cursor rendering - [ ] Add user idle detection (30s timeout) - [ ] Create presence update protocol (WebSocket messages) - [ ] Design and implement "user is editing" indicators **Deliverables:** - Visual indicators showing active collaborators - Remote cursor positions in the editor - List of online users with editing context **Dependencies:** - Phase 1 (WebSocket connection) - FRE-596 (Authentication) - for user identity **Blockers:** - Design approval on presence UI --- ### Phase 3: WebRTC Video Integration (Weeks 5-6) **Goal:** Enable video chat during collaboration sessions **Tasks:** - [ ] Implement `WebRTCVideoManager` with PeerJS - [ ] Set up WebRTC signaling server (can reuse WebSocket server) - [ ] Create `VideoChatOverlay` component - [ ] Implement P2P connection negotiation - [ ] Add TURN server fallback for NAT traversal - [ ] Integrate audio/video permissions - [ ] Add mute/toggle controls **Deliverables:** - Video chat between collaborators - Audio/video toggle controls - Connection quality indicator **Dependencies:** - Phase 2 (Presence - for knowing who to call) - TURN server infrastructure **Blockers:** - WebRTC port firewall configuration - Media stream permission UX --- ### Phase 4: Change Tracking & Merge (Weeks 7-8) **Goal:** Full revision control and conflict resolution **Tasks:** - [ ] Implement `ChangeTracker` for version history - [ ] Create snapshot/restore functionality - [ ] Implement `MergeLogic` for screenplay-specific rules - [ ] Build change acceptance/rejection UI - [ ] Add revision highlighting (colored changes) - [ ] Create version diff viewer - [ ] Implement conflict resolution fallback UI **Deliverables:** - Full version history with snapshots - Change highlighting in editor - Accept/reject workflow for revisions - Conflict resolution UI **Dependencies:** - Phase 1-3 (all collaboration layers) - FRE-594 (Revision tracking - can be merged or parallel) **Blockers:** - Decision on revision workflow (automatic vs manual) --- ### Phase 5: Polish & Optimization (Weeks 9-10) **Goal:** Performance tuning and edge case handling **Tasks:** - [ ] Optimize WebSocket message batching - [ ] Implement offline-first mode with local Yjs persistence - [ ] Add conflict detection alerts - [ ] Tune reconnection backoff strategy - [ ] Implement bandwidth throttling simulation - [ ] Add collaboration analytics (latency, sync rate) - [ ] Write integration tests for all collaboration flows - [ ] Performance benchmarking (large documents, many users) **Deliverables:** - <100ms sync latency (meets KPI) - Offline editing with conflict resolution on reconnect - Comprehensive test coverage (>80%) - Performance benchmarks documented **Dependencies:** - All previous phases - FRE-589 (Tauri packaging) - for desktop-specific optimization **Blockers:** - Load testing environment setup --- ## 5. Dependencies and Blockers ### Hard Dependencies (Must Complete First) | Issue | Dependency | Reason | |-------|------------|--------| | FRE-586 | Core screenplay editor | Need editor component to attach collaboration layer | | FRE-588 | Database schema + Drizzle | Project metadata and user identity for sync | | FRE-596 | Authentication | User identity for presence and change tracking | ### Soft Dependencies (Can Parallelize) | Issue | Dependency | Reason | |-------|------------|--------| | FRE-589 | Tauri packaging | WebSocket integration differs for Tauri vs web | | FRE-594 | Revision tracking | Overlaps with change tracking phase | ### Infrastructure Blockers | Blocker | Description | Mitigation | |---------|-------------|------------| | WebSocket Server | Node.js server with `y-websocket` | Can use y-websocket official server initially | | TURN Server | WebRTC relay for NAT traversal | Use free coturn or Google's public TURN | | Redis Instance | For presence state at scale | Can start with in-memory, add Redis later | | JWT Auth | For WebSocket authentication | Reuse Clerk tokens from FRE-596 | ### Technical Blockers | Blocker | Description | Mitigation | |---------|-------------|------------| | Tauri WebSocket | Tauri's WebSocket API differs from browser | Use `tauri-plugin-websocket` or fallback to `ws` | | Yjs SolidJS Integration | Need reactive bindings | Use `y-sweet` or create custom Solid bindings | | WebRTC in Tauri | Tauri may need native WebRTC module | Use PeerJS with webview fallback | | Large Document Performance | Yjs may slow with 10k+ characters | Implement document chunking by scene | ### External Dependencies | Dependency | Source | Timeline | |------------|--------|----------| | Clerk Auth Tokens | FRE-596 | Month 1-2 | | Turso Project IDs | FRE-588 | Month 1 | | WebSocket Server URL | DevOps | Month 2 | | TURN Server Config | DevOps | Month 3 | --- ## 6. Risk Assessment | Risk | Probability | Impact | Mitigation | |------|-------------|--------|------------| | Yjs performance degradation with large documents | Medium | High | Implement scene-based document chunking | | WebRTC P2P failures due to corporate firewalls | High | Medium | Use TURN relay as fallback | | WebSocket connection instability on mobile | Medium | Medium | Aggressive reconnection with backoff | | CRDT conflicts produce unexpected results | Low | High | Implement manual conflict resolution UI | | Presence updates flood network | Medium | Low | Throttle updates (100ms debounce) | | Tauri WebSocket API limitations | Medium | Medium | Fallback to webview-based WebSocket | --- ## 7. Success Metrics | Metric | Target | Measurement | |--------|--------|-------------| | Sync Latency | <100ms | Time from local change to remote receipt | | Connection Uptime | >99% | WebSocket connected time / total time | | Conflict Resolution Time | <500ms | Time to auto-merge concurrent edits | | Video Call Setup Time | <2s | Time from invite to video visible | | Presence Accuracy | >95% | Correct user position displayed | | Offline Sync Recovery | 100% | All changes merged on reconnect | | Bundle Size Impact | <50KB | Yjs + WebSocket + WebRTC combined | --- ## 8. Future Enhancements (Post-MVP) 1. **Mobile Collaboration:** Extend WebRTC to iOS/Android via Capacitor 2. **Comment Threads:** Add comment CRDT type for inline feedback 3. **Voice Chat:** Add voice-only mode for low-bandwidth scenarios 4. **Screen Sharing:** Extend WebRTC to support screen capture 5. **AI Conflict Resolution:** Use AI to suggest merge strategies 6. **Collaboration Analytics:** Dashboard showing collaboration patterns 7. **Branching Workflows:** Git-like branches for screenplay variants 8. **Real-time Translations:** Collaborative multi-language editing --- **Document Version:** 1.0 **Last Updated:** May 22, 2026 **Author:** CTO (via Paperclip analysis) **Review Status:** Pending CMO/Engineering review