TalkBox is structured as two independent processes — a Node.js server and a React client — that communicate over two distinct channels: a conventional HTTP REST API for authentication and data loading, and a persistent WebSocket connection powered by Socket.IO for instant message delivery. Every layer has a single, well-defined responsibility, which keeps the codebase predictable and easy to extend.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/abdelhafid37/talkbox/llms.txt
Use this file to discover all available pages before exploring further.
System layers
Frontend (React + Vite)
The client is a single-page application built with React 19 and bundled by Vite. It exposes four routes —
/, /login, /register, and the JWT-protected /chat — managed by React Router v7. An AuthContext holds the current user and token in memory, a thin api.js Axios instance handles all REST calls, and socket.js exports a single Socket.IO client that is connected and disconnected alongside the user’s session.Backend API (Express)
The Express 5 server mounts three route groups under
/api: /api/auth for registration and login, /api/users for the current user profile and the full user list, and /api/messages for creating and fetching messages. Every route except the auth endpoints is guarded by a JWT authMiddleware that validates the Authorization: Bearer <token> header before the controller runs.Real-Time Layer (Socket.IO)
Socket.IO is attached to the same HTTP server instance as Express. A middleware step verifies
socket.handshake.auth.token before any connection is accepted, so the WebSocket channel is as secure as the REST API. Once connected, clients fire join to register themselves in an in-memory onlineUsers Map, emit sendMessage to send a message, and listen for newMessage and onlineUsers broadcasts from the server.Message send flow
When a user sends a message, the following sequence occurs end-to-end:- User types and submits — the React UI calls
socket.emit("sendMessage", { receiverId, text })on the client-side Socket.IO instance. - Server receives
sendMessage— thesendMessagehandler insocket.jspicks up the event. The sender’s identity is already attached tosocket.userfrom the authentication middleware, so no extra token check is needed at this point. - Persistence — the handler calls
Message.create({ sender: socket.user._id, receiver: data.receiverId, content: data.text }), writing the message to MongoDB. - Population — the newly created document is immediately populated with
sender.usernameandreceiver.usernameso that both parties receive a fully resolved object. - Delivery — the server emits
newMessageback to the sender’s socket (socket.emit) and, if the receiver is online, to their socket viaio.to(receiverSocketId).emit("newMessage", populatedMessage). Offline recipients will load missed messages through the REST API on their next visit.
Authentication flow
Authentication is handled entirely over REST and then re-used by the WebSocket layer:- Login — the client
POSTs credentials to/api/auth/login. On success the server returns a signed JWT. - Storage — the client stores the token in
localStorageand keeps it inAuthContextfor the lifetime of the session. - REST requests — every subsequent Axios call attaches the token as an
Authorization: Bearer <token>header. TheauthMiddlewareon the server decodes and verifies it before the controller runs. - Socket connection — when the chat page mounts, the client sets
socket.auth = { token }and callssocket.connect(). The Socket.IO middleware on the server verifies the same JWT, looks up the user in MongoDB, and attaches theUserdocument tosocket.userfor the entire connection lifetime.
Because
autoConnect is false, the socket is only opened after a successful login, ensuring the JWT is always available before the handshake begins.Separation of concerns
TalkBox deliberately keeps REST and WebSocket responsibilities separate rather than routing everything through one channel:- REST (
/api/auth,/api/users,/api/messages) handles stateless, request-response interactions: registering an account, logging in, fetching the user list, and loading conversation history on initial page load. These operations map cleanly onto HTTP semantics and benefit from standard status codes and caching. - WebSocket (
sendMessage,newMessage,onlineUsers) handles stateful, push-based interactions: delivering messages in real time and broadcasting presence changes. Because the server maintains theonlineUsersMap for the lifetime of the process, it can push to any connected user without the client polling.