WebChat is a full-stack real-time messaging platform built with React, Express, MongoDB, and Socket.IO. It combines credential-based authentication, Google OAuth 2.0 sign-in, profile management, image sharing, unread message tracking, and live online presence into a clean split frontend/backend architecture.
The project is structured like a production web app rather than a demo-only SPA: the frontend is a Vite-powered client, the backend exposes versioned REST APIs, authentication is JWT-based, media is handled through Cloudinary, and real-time updates are delivered through WebSockets.
- Real-time one-to-one messaging with Socket.IO-powered delivery
- Email/password authentication with bcrypt password hashing
- Google OAuth 2.0 login with account linking for existing users
- JWT-based session management with access and refresh tokens
- Profile management with editable name, bio, and avatar
- Media messaging with image upload support
- Unread message counters and automatic seen-state updates
- Online presence indicators driven by socket connection state
- Searchable conversation sidebar
- Protected routes and staged onboarding for newly created accounts
- Frontend loading overlay for in-flight API requests
- Split deployment model for independent frontend and backend hosting
- React 19
- React Router
- Vite
- Tailwind CSS
- Axios
- Socket.IO Client
- React Hot Toast
- Lottie React
- Node.js
- Express 5
- Socket.IO
- JWT (
jsonwebtoken) - bcrypt
- Multer
- Google Auth Library
- MongoDB
- Mongoose
- Cloudinary
- ESLint
- Nodemon
- Vercel
The backend follows a lightweight MVC-style structure:
routes/define the public HTTP API surfacecontrollers/implement request validation and business logicmodels/define MongoDB schemas and indexesmiddleware/handles auth, uploads, and timeoutsutils/centralize response wrappers, Cloudinary uploads, and error helpers
Typical request flow:
Client -> Express Route -> Middleware -> Controller -> Mongoose Model -> MongoDB -> JSON Response
The frontend uses React Context as its application-level state layer:
AuthContextmanages authentication, token persistence, session restoration, logout, profile updates, and socket connection bootstrapChatContextmanages users, active conversation, unread counts, message retrieval, and optimistic message insertion
This keeps view components focused on rendering and user interaction while the contexts own network orchestration.
- The authenticated client connects to Socket.IO with its user ID.
- The backend maps
userId -> socketId. - When a message is sent, it is first persisted in MongoDB.
- If the recipient is online, the backend emits
newMessageto the matching socket. - The client updates unread counts or appends the message directly if the conversation is open.
This design ensures messages remain durable even if the recipient is offline.
webChat/
โโโ Frontend/
โ โโโ context/
โ โ โโโ AuthContext.jsx
โ โ โโโ ChatContext.jsx
โ โโโ public/
โ โโโ src/
โ โ โโโ assets/
โ โ โโโ components/
โ โ โโโ lib/
โ โ โโโ pages/
โ โ โโโ App.jsx
โ โ โโโ main.jsx
โ โโโ .env
โ โโโ package.json
โ โโโ vercel.json
โโโ Backend/
โ โโโ src/
โ โ โโโ controllers/
โ โ โโโ database/
โ โ โโโ middleware/
โ โ โโโ models/
โ โ โโโ routes/
โ โ โโโ utils/
โ โ โโโ constants.js
โ โ โโโ server.js
โ โ โโโ socket.js
โ โโโ .env
โ โโโ package.json
โโโ README.md
Frontend/contextholds shared app state and API interaction logicFrontend/src/pagescontains the main route-level screensFrontend/src/componentscontains reusable chat and auth UI piecesBackend/src/controllerscontains user and messaging workflowsBackend/src/modelsdefinesUserandMessagepersistence logicBackend/src/middlewarecontains JWT auth, file upload, and timeout handlingBackend/src/socket.jsmanages connection lifecycle and presence broadcasting
git clone https://github.com/your-username/webChat.git
cd webChatcd Frontend
npm install
cd ../Backend
npm installCreate:
Frontend/.envBackend/.env
Use the environment variable reference below.
cd Backend
npm run servercd Frontend
npm run devFrontend: http://localhost:5173
Backend: http://localhost:8000
| Variable | Required | Description |
|---|---|---|
VITE_BACKEND_URL |
Yes | Base URL for the backend API and Socket.IO connection |
VITE_GOOGLE_CLIENT_ID |
For Google login | Google OAuth Web Client ID used by Google Identity Services |
| Variable | Required | Description |
|---|---|---|
PORT |
Yes | Express server port for local development |
MONGODB_URI |
Yes | MongoDB connection string prefix used with webchat_db |
CORS_ORIGIN |
Yes | Allowed frontend origin for API and socket access |
ACCESS_TOKEN_SECRET |
Yes | Secret used to sign access JWTs |
ACCESS_TOKEN_EXPIRY |
Yes | Access token lifetime, e.g. 1h or 1d |
REFRESH_TOKEN_SECRET |
Yes | Secret used to sign refresh JWTs |
REFRESH_TOKEN_EXPIRY |
Yes | Refresh token lifetime |
CLOUDINARY_CLOUD_NAME |
For image uploads | Cloudinary cloud name |
CLOUDINARY_API_KEY |
For image uploads | Cloudinary API key |
CLOUDINARY_API_SECRET |
For image uploads | Cloudinary API secret |
GOOGLE_CLIENT_ID |
For Google login | Google OAuth client ID used to verify ID tokens on the server |
Base URL:
/api/v1
| Method | Route | Description |
|---|---|---|
POST |
/users/signUp |
Register a new user with email and password |
POST |
/users/login |
Log in with email/password |
POST |
/users/google |
Authenticate with Google OAuth 2.0 |
POST |
/users/logout |
Clear refresh token and end session |
GET |
/users/me |
Fetch the currently authenticated user |
PUT |
/users/update-profile |
Update name, bio, and avatar |
| Method | Route | Description |
|---|---|---|
GET |
/messages/getUsers |
Fetch users for the conversation sidebar plus unread counts |
GET |
/messages/messages/:id |
Fetch message history with a selected user |
PUT |
/messages/mark-as-seen/:id |
Mark a message as seen |
POST |
/messages/send-message/:id |
Send a text and/or image message |
Add product screenshots here for a stronger GitHub presentation:


Recommended captures:
- Authentication screen
- Main chat layout
- Mobile responsive layout
- Profile editing flow
- Image messaging flow
WebChat supports two authentication paths:
- Traditional email/password signup and login
- Google OAuth 2.0 via Google Identity Services
Passwords are hashed with bcrypt, JWT access and refresh tokens are issued on login, and protected routes rely on a verifyJWT middleware that accepts either cookies or Authorization: Bearer <token> headers. The frontend currently persists the access token in local storage to simplify SPA session restoration.
The Google auth flow is implemented as a popup-based login experience. The frontend obtains a Google ID token, sends it to the backend, and the backend verifies it using google-auth-library. If a matching email already exists, the account is linked rather than duplicated.
Real-time updates are handled by Socket.IO. When a user connects, the backend stores their socket ID in an in-memory map and broadcasts the online user list. When a message is created, it is first stored in MongoDB and then emitted to the recipient if they are online.
This gives the system two important properties:
- messages are durable because persistence happens before emission
- the UI remains responsive because online/offline state is pushed in real time
The data model is intentionally compact:
Userstores identity, auth metadata, profile fields, and refresh token stateMessagestores sender, receiver, text, optional image URL, seen state, and timestamps
The Message schema also includes compound indexes for common query patterns:
- sender + receiver + createdAt
- receiver + sender + createdAt
- receiver + seen
These indexes support fast conversation retrieval and unseen message counts.
Profile images and chat images are received through multer, written to a temporary directory, uploaded to Cloudinary, and then removed from local disk. A dedicated timeout wrapper protects long-running uploads and returns a clear 408 response when an upload takes too long.
The app has a focused state domain: authentication, current user, selected chat, messages, unread counts, and socket events. React Context keeps this state close to the app without adding Redux/Zustand-level complexity.
JWTs make the frontend/backend split easy to manage across environments, especially when the frontend and backend are deployed independently. The backend also supports cookie-based token delivery, which leaves room for future hardening.
Socket.IO provides a pragmatic real-time layer for chat applications:
- simple client/server integration
- connection lifecycle events
- event-driven messaging
- easier local development than raw WebSocket handling
Chat data is document-friendly, and MongoDB works well for user/message entities with evolving profile fields and lightweight relational needs. Mongoose adds schema validation, indexes, and model methods for tokens/password workflows.
Offloading media storage keeps the backend stateless and avoids handling binary asset storage directly on the application server. It also simplifies CDN-friendly image delivery.
A split deployment model improves portability and keeps responsibilities clean:
- frontend focuses on UX and client state
- backend focuses on auth, persistence, media, and real-time events
This mirrors how many production systems are deployed and maintained.
- Move Socket.IO to a stateful production runtime or dedicated realtime service for full production-grade WebSocket support beyond serverless constraints
- Add message pagination and virtualized chat history for large conversations
- Introduce refresh-token rotation and stronger cookie-first auth for improved browser security
- Add typing indicators and delivery/read receipts at the conversation level
- Add user blocking, account linking management, and password reset flows
- Add conversation metadata and last-message snapshots to reduce sidebar query cost
- Add automated tests for auth, messaging, and upload flows
- Add observability for API latency, upload failures, and socket lifecycle events
- Add a stable avatar synchronization strategy for third-party OAuth profile images
If you found this project useful:
- star the repository
- open an issue for bugs or feature suggestions
- fork it and extend the platform
If you are a recruiter or engineer reviewing the project, the most relevant files to inspect first are:
Frontend/context/AuthContext.jsxFrontend/context/ChatContext.jsxBackend/src/controllers/user.controller.jsBackend/src/controllers/message.controller.jsBackend/src/socket.js