DevRoom is a collaborative software-planning workspace where teams can create rooms, sketch system architecture on a shared canvas, connect components, add notes, attach files to nodes, manage collaborators, and review activity history. The project uses a React + Vite frontend, a Node.js + Express backend, MongoDB for persistence, and Socket.IO for realtime collaboration.
DevRoom is designed for software teams that want one place to:
- create shared project rooms
- build architecture diagrams with draggable nodes and edges
- add sticky notes for design discussion
- upload text-based project files and keep version history
- link files to specific architecture nodes
- invite collaborators with room roles
- see live user presence and remote cursors
- review room activity through a history panel
- JWT-based authentication
- room creation, listing, update, and archive flow
- role-based room membership (
owner,editor,viewer) - React Flow-based collaborative canvas
- node, edge, and note persistence in MongoDB
- file upload using stored text content plus file versioning
- file-to-node linking
- Socket.IO presence, cursor sharing, and live canvas event broadcast
- activity logging through
HistoryLog
- React 19
- Vite 8
- React Flow
- Axios
- Socket.IO Client
- Lucide React
- Node.js
- Express 5
- MongoDB with Mongoose
- Socket.IO
- JWT
- bcryptjs
- CORS
- dotenv
- Playwright
- nodemon
+-------------------+ HTTP / REST +----------------------+
| React + Vite UI | ---------------------------> | Express API Server |
| React Flow Canvas | | Auth, Rooms, Canvas |
| Files + Members | <--------------------------- | Files, History |
+---------+---------+ JSON responses +----------+-----------+
| |
| Socket.IO |
v v
+-------------------+ +------------------+
| Realtime Clients | <-------------------------------> | MongoDB |
| Presence, Cursor | | App persistence |
| Canvas Sync | | and history |
+-------------------+ +------------------+
DevRoom/
|-- backend/
| |-- package.json
| `-- src/
| |-- config/
| |-- controllers/
| |-- middleware/
| |-- models/
| |-- routes/
| `-- server.js
|-- frontend/
| |-- package.json
| |-- public/
| `-- src/
| |-- components/
| |-- context/
| |-- hooks/
| |-- services/
| `-- templates/
|-- scripts/
|-- APIs/
|-- README.md
`-- DevRoom_IEEE_Paper.tex
backend/src/server.js: server bootstrap, route mounting, Socket.IO setupbackend/src/config/db.js: MongoDB connectionbackend/src/controllers/: request handlersbackend/src/routes/: API route definitionsbackend/src/models/: Mongoose schemasbackend/src/middleware/authMiddleware.js: JWT verification
frontend/src/App.jsx: top-level application flowfrontend/src/context/AuthContext.jsx: login, register, logout statefrontend/src/context/RoomContext.jsx: room list and active room statefrontend/src/services/api.js: Axios clients and API wrappersfrontend/src/components/Layout/RoomWorkspace.jsx: main workspace shellfrontend/src/components/Canvas/ReactFlowCanvas.jsx: active canvas implementationfrontend/src/components/Panels/FilesPanel.jsx: file managementfrontend/src/components/Panels/MembersPanel.jsx: collaborator managementfrontend/src/components/Panels/HistoryPanel.jsx: room activity timelinefrontend/src/templates/nodeTemplates.js: available node template types
| Model | Purpose | Key Fields |
|---|---|---|
User |
platform users | name, email, passwordHash, profileImage, status |
Room |
shared workspace metadata | name, description, createdBy, isArchived |
RoomMember |
room membership and role | roomId, userId, role, joinedAt |
CanvasNode |
architecture blocks on canvas | roomId, title, type, position, width, height, createdBy |
CanvasEdge |
node-to-node connections | roomId, sourceNodeId, targetNodeId, createdBy |
CanvasNote |
sticky notes on canvas | roomId, text, position, createdBy |
File |
latest file snapshot | roomId, fileName, fileType, fileSize, filePath, fileContent, uploadedBy, isDeleted |
FileVersion |
saved revisions of a file | fileId, versionNumber, filePath, fileContent, uploadedBy, changeNote |
FileNodeLink |
relation between file and node | nodeId, fileId, linkedBy |
HistoryLog |
room activity trail | roomId, userId, actionType, message, entityId |
All backend APIs run from the Node server on http://localhost:5002.
| Method | Route | Auth | Purpose |
|---|---|---|---|
POST |
/api/register |
No | register a new user |
POST |
/api/login |
No | login and receive JWT |
GET |
/api/me |
Yes | fetch current user |
POST |
/api/logout |
Yes | client logout acknowledgement |
| Method | Route | Auth | Purpose |
|---|---|---|---|
POST |
/rooms |
Yes | create room |
GET |
/rooms |
Yes | list rooms for current user |
GET |
/rooms/:roomId |
Yes | get room details |
PUT |
/rooms/:roomId |
Yes | update room |
DELETE |
/rooms/:roomId |
Yes | archive room |
GET |
/rooms/:roomId/validate |
Yes | validate room membership |
| Method | Route | Auth | Purpose |
|---|---|---|---|
GET |
/rooms/:roomId/members |
Yes | list room members |
POST |
/rooms/:roomId/members |
Yes | invite member |
PATCH |
/rooms/:roomId/members/:memberId |
Yes | update member role |
DELETE |
/rooms/:roomId/members/:memberId |
Yes | remove member |
| Method | Route | Auth | Purpose |
|---|---|---|---|
GET |
/api/canvas/:roomId |
Yes | load nodes, edges, notes, file links |
POST |
/api/canvas/save |
Yes | save full canvas snapshot |
POST |
/api/canvas/load |
Yes | replace canvas with incoming payload |
| Method | Route | Auth | Purpose |
|---|---|---|---|
POST |
/api/nodes |
Yes | create node |
GET |
/api/nodes/:roomId |
Yes | get nodes in room |
PUT |
/api/nodes/:nodeId |
Yes | update node title or position |
DELETE |
/api/nodes/:nodeId |
Yes | delete node and linked graph data |
POST |
/api/edges |
Yes | create edge |
DELETE |
/api/edges/:edgeId |
Yes | delete edge |
POST |
/api/notes |
Yes | create note |
PUT |
/api/notes/:noteId |
Yes | update note |
DELETE |
/api/notes/:noteId |
Yes | delete note |
| Method | Route | Auth in current code | Purpose |
|---|---|---|---|
POST |
/api/files/upload |
No | create file or new file version |
POST |
/api/files/:fileId/version |
No | add file version |
GET |
/api/files/download/:fileId |
No | return file and versions |
GET |
/api/files/link/:fileId |
No | return file metadata and generated download URL |
GET |
/api/files/:fileId/content |
No | get latest file content |
GET |
/api/files/:fileId/versions |
No | get version list |
GET |
/api/files/room/:roomId |
No | list files in a room |
GET |
/api/files/:fileId |
No | get latest file content |
DELETE |
/api/files/:fileId |
No | soft delete file |
POST |
/api/files/link |
Yes | link file to node |
GET |
/api/files/node/:nodeId |
Yes | get file links for node |
DELETE |
/api/files/unlink |
Yes | unlink file from node |
| Method | Route | Auth | Purpose |
|---|---|---|---|
GET |
/api/history/:roomId |
Yes | room activity timeline |
Socket.IO is configured in backend/src/server.js.
| Event | Payload |
|---|---|
presence-join |
{ userId, roomId, userName } |
cursor-move |
{ userId, roomId, x, y, userName } |
node-drag |
{ roomId, nodeId, x, y } |
note-drag |
{ roomId, noteId, x, y } |
| Event | Payload |
|---|---|
presence-update |
current room users |
cursor-update |
remote cursor coordinates |
cursor-remove |
disconnected cursor id |
node-created |
created node document |
node-updated |
updated node document |
node-deleted |
{ nodeId } |
edge-created |
created edge document |
edge-deleted |
{ edgeId } |
note-created |
created note document |
note-updated |
updated note document |
node-drag |
live node position |
note-drag |
live note position |
Install the following before running the project:
- Node.js 18 or later
- npm
- MongoDB instance, local or cloud
git clone <your-repo-url>
cd DevRoomThe root package.json only exists for helper scripts such as Playwright checks.
npm installcd backend
npm installCreate backend/.env with:
MONGO_URI=mongodb://127.0.0.1:27017/devroom
JWT_SECRET=replace_this_with_a_secure_secret
PORT=5002Start the backend:
npm run devThe API server starts on http://localhost:5002.
Open a new terminal:
cd frontend
npm install
npm run devThe frontend starts on http://localhost:5173.
Visit:
http://localhost:5173
Register a new account, sign in, create a room, and begin using the workspace.
- open the frontend
- go to the registration screen
- create an account with name, email, and password
- sign in using the registered email and password
- the JWT token is stored in local storage under
devroom_token
- use the sidebar
+button or landing page CTA - enter room name and optional description
- the logged-in user becomes room
owner
The main workspace contains these tabs:
CanvasOverviewFilesMembersHistory
- add predefined node templates such as frontend, backend, database, service, cache, queue, gateway, JWT generator, and note
- drag nodes around the canvas
- connect nodes using React Flow handles
- save the full canvas using the
Savebutton - use right-click delete actions or keyboard delete for selected items
- move around the board with mini map and controls
- upload a file from the Files panel
- optionally link the file to a specific node during upload
- open a file in the editor modal
- save updates as new versions
- inspect version history for each file
- other users in the same room appear in the top bar
- cursor movements are broadcast through Socket.IO
- node and note updates are emitted to connected clients
- owners and editors can invite members by email
- owners can change roles and remove members
- new members immediately gain access to room data
- open the History tab
- inspect room actions such as node creation, edge creation, note updates, file linking, and canvas save operations
AuthContexthandleslogin,register, andlogoutAuthContextdoes not auto-restore the user from an old token on page refreshRoomContextloads rooms after successful loginRoomWorkspaceopens tabs and creates the shared socket connection for presenceReactFlowCanvasis the active canvas used in the appTldrawCanvas.jsxstill exists in the repo as legacy code, but the workspace currently renders React Flowfrontend/src/services/api.jsuses hard-coded backend URLs pointing athttp://localhost:5002
- the backend connects to MongoDB through
MONGO_URI - JWT verification reads
Authorization: Bearer <token> - rooms are protected with membership checks
- room deletion is a soft delete implemented through
isArchived - full canvas save replaces the room's previous canvas data
- edge saving uses a temp-id mapping strategy and a proximity fallback
- history is written during many create, update, delete, and save actions
- Socket.IO uses a memory-based presence map, so presence is not persisted across server restarts
The full save endpoint expects a payload similar to:
{
"roomId": "ROOM_ID",
"nodes": [
{
"tempShapeId": "shape:temp_123",
"title": "API Gateway",
"type": "gateway",
"position": { "x": 160, "y": 120 },
"width": 160,
"height": 80,
"createdBy": "USER_ID",
"roomId": "ROOM_ID"
}
],
"edges": [
{
"sourceTempId": "shape:temp_123",
"targetTempId": "shape:temp_456",
"sourcePoint": { "x": 160, "y": 120 },
"targetPoint": { "x": 400, "y": 120 },
"createdBy": "USER_ID"
}
],
"notes": [
{
"_id": "NOTE_ID",
"text": "Remember to cache token validation",
"position": { "x": 260, "y": 240 },
"createdBy": "USER_ID",
"roomId": "ROOM_ID"
}
]
}The repository includes helper scripts under scripts/.
node scripts/apiTest.jsRegisters a temporary user and checks login.
node scripts/canvasEdgeTest.mjsCreates a room, saves sample nodes and edges, then fetches the canvas.
node scripts/browserTest.mjs
node scripts/playwrightEdgeDebug.mjsThese scripts were written during earlier canvas work. Some of them still reference older Tldraw behavior, so treat them as development utilities rather than guaranteed production-grade tests.
These values are currently hard-coded in the codebase:
- backend REST base URL:
frontend/src/services/api.js - backend socket URL:
frontend/src/components/Layout/RoomWorkspace.jsx - canvas socket URL:
frontend/src/components/Canvas/ReactFlowCanvas.jsx - allowed Socket.IO and CORS origins:
backend/src/server.js
If you deploy the project to a different host or port, update those files or refactor them to use environment variables.
- file routes under
/api/files/*are not protected by JWT middleware in the current backend implementation - the frontend does not automatically restore the logged-in user after a page refresh, even if a token is still present
- the note template path currently tries to create empty notes, while the backend requires non-empty note text
- presence is stored in memory and is lost when the backend restarts
- helper test scripts are partly based on older canvas behavior
- there is no Docker, CI pipeline, or
.env.examplefile in the current repository
- move frontend and backend base URLs into environment variables
- add authentication middleware to file routes
- fix empty-note creation flow in React Flow
- restore session state from stored JWT on refresh
- add automated API and end-to-end test coverage
- introduce Docker and environment templates
- persist richer audit metadata for history entries
README.md: complete end-to-end project documentationDevRoom_IEEE_Paper.tex: IEEE-style LaTeX source for a research/project paper based on this project
Check:
- MongoDB is running
backend/.envexistsMONGO_URIis validJWT_SECRETis set
Check:
- backend is running on port
5002 - frontend is running on port
5173 - the hard-coded URLs in
frontend/src/services/api.jsstill match your environment
Check:
- Socket.IO server is running with the backend
- both users joined the same room
- your frontend origin is allowed in
backend/src/server.js
Check:
- you are logged in
devroom_tokenexists in local storage- your member role allows the attempted action
DevRoom is a solid full-stack prototype for collaborative architecture planning and lightweight project documentation. The current codebase already covers authentication, room management, collaborative canvas editing, file versioning, realtime presence, and history tracking. The next step is to harden configuration, security, and automated testing so the project can move from prototype quality to production readiness.