Background
Full StackApril 2025

Coordly

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

Coordly — screenshot 1
01 — Why I Built It

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.

02 — The Workspace

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.

03 — Architecture

System Architecture

Coordly Workspace (Client)
DocsYjs / Tiptap
ChatSocket.IO
VideoWebRTC / PeerJS
y-websocket
socket.io signaling
Peer signaling
documentServer.js (Node) Multiplexed Realtime Server
peerServer.js Peer Broker
MongoDBApp Data & Yjs Buffers

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.

04 — Real-Time Systems

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.

05 — WebRTC Media

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.

06 — Persistence

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.

07 — Security

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.

08 — Engineering Challenges

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.

09 — Trade-offs

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.
10 — What I Learned

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."

11 — Tech Stack

Technology Stack

TechnologyRole
Next.js 15Frontend framework and API routes
Yjs & TiptapCRDT real-time collaborative text editing
Socket.IOChat, signaling, and presence
WebRTC & PeerJSPeer-to-peer media streaming
Node.jsMultiplexed WebSocket & Signaling servers
MongoDBDatabase for app metadata and CRDT storage
NextAuthAuthentication and JWT session management
Framer MotionFluid UI animations and draggable PiP