A real-time multi-room chat application built with WebSockets, React, and Node.js.
chat-app/
├── be/ # Backend — Node.js + TypeScript
│ └── src/index.ts # Express HTTP server + ws WebSocket server
└── fe/ # Frontend — React + TypeScript + Vite
└── src/
├── main.tsx # React entry point
└── App.tsx # Single-component app (all state + UI)
fe/dist) as static files with SPA fallbackws (WebSocketServer on the same port)allSockets: User[] — tracks every live connection with its socket, room, and usernameroomMessages: Map<string, Message[]> — persists chat history per room for the lifetime of the processjoin, chat, typing, and close (disconnect)App component owns all state — no external state libraryjoin message to restore room membership| Direction | Type | Payload |
|---|---|---|
| Client → Server | join |
{ roomId, username } |
| Client → Server | chat |
{ message } |
| Client → Server | typing |
{ isTyping: boolean } |
| Server → Client | history |
{ messages: Message[] } — sent on join |
| Server → Client | chat |
{ message, username, timestamp } |
| Server → Client | system |
{ message } — join/leave notifications |
| Server → Client | typing |
{ username, isTyping } |
| Server → Client | users_list |
{ users: string[] } — broadcast on join/leave |
| Layer | Technology |
|---|---|
| Backend runtime | Node.js |
| Backend framework | Express 5 |
| WebSocket library | ws |
| Backend language | TypeScript (compiled to CommonJS) |
| Frontend framework | React 18 |
| Frontend build tool | Vite |
| Frontend styling | Tailwind CSS v4 |
| Frontend language | TypeScript |
# Terminal 1 — start the backend (compiles TS then runs)
cd be
npm install
npm run dev
# Terminal 2 — start the frontend dev server
cd fe
npm install
npm run dev
Frontend dev server proxies WebSocket connections to ws://127.0.0.1:8080.
Open http://localhost:5173 in your browser.
cd be
npm run build # installs deps, builds fe/dist, compiles backend TS
npm start # serves everything on port 8080
Open http://localhost:8080. The backend serves the compiled frontend.