Collaborative Features
Collaborative Code Editor
Used in live interview rooms (live_1on1, culture_fit_hr) and AI-assisted sessions.
Technology Stack
- Yjs — CRDT (Conflict-free Replicated Data Type) for real-time collaboration
- y-codemirror.next — Yjs binding for the CodeMirror 6 editor
- y-webrtc — Yjs WebRTC provider (syncs via WebRTC Data Channels, same P2P connection as video)
How It Works
Interviewer types code in CodeMirror
↓
CodeMirror change → Yjs operation
↓
Yjs encodes operation as binary update
↓
y-webrtc sends update via WebRTC Data Channel
↓
Peer receives update → Yjs merges (CRDT = no conflicts)
↓
Peer's CodeMirror editor reflects the changeCursor Awareness
The awareness protocol syncs cursor positions and selections between all participants in real time. Each user's cursor is shown with their name label.
Visibility
The IDE panel in the room is visible to all participants (interviewer + candidate). It is controlled by StageTypeConfig.toolsConfig.ide — the panel only renders when true.
Whiteboard
Real-time shared canvas using Excalidraw.
- Excalidraw's built-in collaboration API is used to broadcast element changes
- Changes are sent to all room participants via the existing WebSocket connection
- The whiteboard is visible to all participants
- Controlled by
StageTypeConfig.toolsConfig.whiteboard
Screen Sharing
For live sessions where toolsConfig.screenShare: true:
- Uses
navigator.mediaDevices.getDisplayMedia()to capture screen - Screen track replaces (or adds alongside) the camera video track in the WebRTC connection
- Visible to all participants in the room
Private Question Panel (Interviewer-Only)
The "My Questions" panel in the live room is only visible when:
- The user is authenticated (recruiter role)
interview.stageTypeKey === 'live_1on1'or'culture_fit_hr'
The panel fetches questions from GET /v1/interviews/:id/private-questions. This endpoint is auth-gated to the interviewer only. The interviewerHints and expectedAnswerGuide fields are returned to the interviewer but are never sent to the candidate's browser.
When the interviewer clicks "Push to candidate":
- Socket event
push_questionemitted with{ questionText }only - Candidate's screen shows a floating card with the question text
interviewerHints/expectedAnswerGuidenever leave the interviewer's session
Tool Visibility Matrix
All tool panels are rendered or hidden based on StageTypeConfig.toolsConfig:
| Tool | automated_screening | technical_dsa | technical_ai_assisted | live_1on1 |
|---|---|---|---|---|
whiteboard | ❌ | ❌ | ✅ | ✅ |
ide | ❌ | ✅ | ✅ | ✅ |
screenShare | ❌ | ❌ | ❌ | ✅ |
audio | ❌ | ❌ | ✅ | ✅ |
video | ❌ | ❌ | ✅ | ✅ |
aiChatbot | ❌ | ✅ | ✅ | ✅ |
webcamProctoring | ❌ | ✅ | ❌ | ❌ |
voiceInterface | ✅ | ❌ | ❌ | ❌ |
TIP
The frontend checks stageTypeConfig.toolsConfig.<tool> to decide whether to render each panel — not a hardcoded switch statement.