Course project · archived
Realtime collaboration system
PeerPrep
A technical-interview practice platform where matched participants solve coding problems together in a synchronized Monaco editor.
- Role
- Collaboration service lead · NUS course team
- Period
- Jan – Apr 2026
- State
- Course project · archived
Problem
The problem
Pair-programming practice breaks down when concurrent edits diverge, reconnecting participants lose state, or a room accepts users who were not part of the match.
Outcome
Delivered the collaboration layer for synchronized editing, presence, authenticated room access, reconnect recovery, and persisted attempt history.
Contribution
Ownership boundary
I owned the collaboration service and editor integration: consuming match events, creating session state, issuing join credentials, synchronizing Yjs documents, handling participant presence and reconnects, and persisting completed attempts. The wider course team owned matching, questions, authentication, history, and deployment around that boundary.
- Built as an NUS software-engineering course project.
- The public repository is team-owned; this page scopes my contribution instead of presenting all repository work as mine.
- The deployment is retained as a live demo while it remains available; the repository is the durable source.
Under the hood
Tools & responsibilities
- Yjs + y-monaco
- CRDT document updates keep concurrent editor changes convergent.
- Socket.IO
- Carries document, presence, join, leave, and reconnect events.
- RabbitMQ
- Decouples collaboration-session creation from successful match events.
- Redis
- Stores active session state and debounced document snapshots.
- Supabase
- Authenticates joins and supports persisted attempt history.
System view
Collaboration service boundary
A match creates an authenticated collaboration session; participants then exchange convergent document and presence updates while snapshots protect reconnects.
- RabbitMQ match event
- Collaboration service
- Supabase-authenticated join
- Socket.IO room
- Yjs document updates
- Redis snapshot + attempt history
Engineering judgment
Engineering decisions
The constraints, alternatives, and trade-offs behind the implementation.
Make concurrent edits converge
- Constraint
- Two participants can type at the same time and receive updates in different network orders.
- Options
- Treat the server as the sole text authority, implement operational transforms, or use a CRDT designed for distributed editing.
- Decision
- Use Yjs with y-monaco and send encoded incremental updates through Socket.IO.
- Result
- Both editors converge without imposing a single keystroke ordering path in the UI.
Recover without reopening the room
- Constraint
- A short connection drop should not end a practice attempt or return a participant to an empty editor.
- Options
- End the room immediately, retain only in-memory state, or keep a reconnect window backed by snapshots.
- Decision
- Track participant presence, allow a reconnect grace period, and write debounced Yjs snapshots to Redis.
- Result
- A returning participant can rejoin the active room and receive a full document sync before incremental updates resume.
Keep room membership explicit
- Constraint
- Knowing a room identifier must not be enough to join another pair’s interview attempt.
- Options
- Trust client-provided user IDs, rely on an opaque room ID, or gate joins with authenticated match context.
- Decision
- Issue per-user join credentials when the match creates the session and validate them against Supabase-authenticated users.
- Result
- Room access is tied to the matched participants rather than to discoverability of a URL or socket event.
Reliability approach
When things go wrong
- Full document sync is sent on join and reconnect before normal incremental updates continue.
- Explicit leave handling and reconnect grace periods distinguish a temporary drop from a completed departure.
- Debounced snapshots reduce write frequency while retaining recoverable session state.
Limits and next evidence
Limitations & next steps
- The current public evidence does not claim a measured synchronization latency, recovery rate, or user count.
- Authored pull-request and service-folder links will be added after the exact contribution URLs are verified.
- Large local point-of-view recordings are excluded from production until optimized public versions and posters are hosted.
Next case study
Kawan
Shipped a working prototype in three days and won “Ah Gong, Ah Ma’s Favourite,” the audience-voted award at The Good Hack 2026.
Want to discuss the implementation boundary or trade-offs? Julius Gwee is available for software engineering opportunities.