The Problem
Real-time collaboration is one of those features that sounds straightforward until you try to implement it. Drag-and-drop task reordering across multiple connected clients - where everyone sees the same board state instantly - involves synchronisation challenges most tutorials skip entirely.
What I Built
Socket.io for real-time board updates: every drag-and-drop action emits to a room, the server validates the new order, updates MongoDB, and broadcasts the confirmed state to all connected clients. Conflicts resolve server-side - last write wins with client-side optimistic updates.
Socket.io rooms per project - users join a room when they open a board and leave when they navigate away. Task updates emit to the room, not to individual users. The server is the source of truth; clients optimistically update and roll back if the server rejects.
The tricky part was reconciling the optimistic client-side order with the persisted MongoDB order during concurrent drags. Solved with a position field on each task and a debounced persist - the client shows the new order immediately, the server confirms within 300ms.
MongoDB schema with workspaces → projects → task lists → tasks. Flexible enough to support Kanban and List views without separate collections. Task assignments and comment threads are embedded documents - reduces join complexity at the cost of document size.
What Happened
Real-time board sync working across multiple simultaneous connected clients
Drag-and-drop with instant optimistic updates and server-confirmed persistence
WebSocket room management handles users moving between projects without stale listeners
In the Wild
In Hindsight
Embedded comments in task documents works until a task has hundreds of comments and every read pulls the full history. A separate comments collection with a task reference would have been cleaner at scale.
