
Coordly
A unified workspace consolidating real-time collaborative documents, Kanban tasks, team chat, and WebRTC video conferencing into a single cohesive architecture.

On this page
Why I Built Coordly
"The motivation for this project came from the constant friction of using multiple disparate tools for team collaboration. A typical workflow involves Jira or Trello for tasks, Google Docs for writing, Zoom or Google Meet for calls, and Slack for chatting."
"Managing one project across several applications felt unnecessarily fragmented. The primary goal of Coordly was to explore how to build a unified workspace where a team could handle these collaboration activities natively under one roof."
From CollabHub to Coordly
The project was originally named CollabHub. However, the name was later changed to Coordly because CollabHub felt too generic and was already associated with other products.
Coordly was chosen as it is shorter, more modern, brandable, and closely aligns with the application's core goal of team coordination.
The Unified Workspace
Coordly is built around the concept of 'Collabs'—workspace container namespaces.
When users join a Collab, they gain immediate, synchronized access to a Tiptap-powered rich-text document, a drag-and-drop Kanban task board, a real-time messaging channel, and a persistent video call interface.
This architecture eliminates context-switching, allowing teams to reference a document, chat about a task, and speak via video simultaneously within the same browser tab.
System Architecture
Because Yjs operates natively over raw WebSockets and the chat/signaling system operates over Socket.IO (which also uses WebSocket/HTTP upgrades), the backend node server needed to securely route traffic to the correct protocol handler over a single HTTP port.
To solve this, the server intercepts the HTTP `upgrade` event. It analyzes the incoming request path—routing requests prefixed with `/socket.io/` to the Socket.IO engine, while passing all other relevant upgrade requests to the raw `wss.handleUpgrade` handler for Yjs document synchronization.
Three Real-Time Systems, One Workspace
Collaborative Documents (Yjs)
Uses Yjs CRDTs over raw WebSockets (`y-websocket`) to coordinate document state across concurrent editors.
Chat & Signaling (Socket.IO)
Employs Socket.IO for ephemeral, room-based message broadcasting, including typing indicators and emoji reactions.
Video Calling (WebRTC & PeerJS)
Uses PeerJS and WebRTC for peer-to-peer media streaming, keeping the media path outside the application's main realtime server.
WebRTC Media Hot-Swapping
A significant UX challenge in building the video component was allowing users to toggle their camera or microphone without dropping and rebuilding the entire peer-to-peer call.
Rather than tearing down the WebRTC connection, Coordly uses `RTCPeerConnection.getSenders().find(s => ...)` combined with `sender.replaceTrack()`. `replaceTrack()` swaps the active media track without tearing down the existing peer connection. This keeps the network connection alive while instantly reflecting the new hardware state.
Persistence Strategy
The application splits persistence based on data characteristics. Application metadata, user profiles, tasks, and chat history are structured via Mongoose and stored in standard MongoDB collections.
Conversely, the real-time document state is decoupled from the REST API. It is captured by `y-mongodb-provider`, which stores the binary Yjs update buffers into a specialized MongoDB collection directly from the Node WebSocket server.
Authentication & Authorization
Coordly uses NextAuth for identity management, supporting OAuth flows (GitHub, Google) with a JWT session strategy.
Security is enforced server-side via `getServerSession` checks. API routes explicitly validate a user's `CollabParticipant` role before authorizing database operations, preventing unauthorized access to private workspaces.
Engineering Challenges
1. Multiplexing Real-Time Protocols
Problem: Running Yjs (raw WebSockets) and Socket.IO concurrently on the same backend port.
Approach: Intercepting the Node HTTP `upgrade` event and dynamically routing the socket based on the request URL path.
Result: A single Node.js server can route the two realtime protocols to their appropriate handlers.
2. Coordinating Systems
Problem: Ensuring video, chat, and document states remained consistent without overwhelming the client.
Approach: Isolating component lifecycles and utilizing React Context to prevent unnecessary top-level re-renders.
Result: An interface where users can keep the video call in a floating PiP window while working in Docs or Tasks.
3. REST & CRDT Consistency
Problem: Maintaining consistency between standard REST data (document titles/permissions) and CRDT document content.
Approach: Decoupling the storage mechanisms—using Mongoose for metadata and `y-mongodb-provider` for binary state.
Result: Keeps CRDT document state separate from conventional REST-managed metadata and permissions.
Trade-offs & Limitations
- The `documentServer.js` maintains connection state in memory. Horizontal scaling would require a shared infrastructure adapter (like Redis) to bridge Socket.IO and Yjs instances.
- PeerJS relies on default STUN/TURN configurations, which may struggle to negotiate WebRTC connections across strict corporate firewalls.
- No explicit API rate-limiting is currently implemented on the Node backend.
What I Learned
This was my first major backend and real-time heavy project. It taught me the fundamentals of backend architecture, especially how and when to use different communication technologies like WebSockets, WebRTC, and HTTP APIs.
I also learned the stark differences between local development and production deployments, handling database schemas, and managing session authentication securely.
Midway through development, my laptop crashed and I lost the entire uncommitted codebase. Rebuilding it from scratch made the value of Git, version control, and remote repositories very real to me.
What I Would Build Differently Today
"If I were starting this project today, I would prioritize a much stricter architecture plan from day one, establishing cleaner system boundaries between the real-time servers."
"I would also architect the platform with AI integration as a foundational pillar, rather than an afterthought, allowing for features like automated task generation or meeting summaries."
Technology Stack
| Technology | Role |
|---|---|
| Next.js 15 | Frontend framework and API routes |
| Yjs & Tiptap | CRDT real-time collaborative text editing |
| Socket.IO | Chat, signaling, and presence |
| WebRTC & PeerJS | Peer-to-peer media streaming |
| Node.js | Multiplexed WebSocket & Signaling servers |
| MongoDB | Database for app metadata and CRDT storage |
| NextAuth | Authentication and JWT session management |
| Framer Motion | Fluid UI animations and draggable PiP |