A production-ready real-time chat application built with the MERN stack (MongoDB, Express.js, React, Node.js) and WebSocket for bidirectional communication. Features modern gradient UI design, horizontal scalability with Redis Pub/Sub, and comprehensive security measures.
- Real-time messaging with WebSocket connections
- User authentication with JWT (Access + Refresh tokens)
- Online/Offline status tracking
- Message persistence with MongoDB
- Optimistic UI updates for instant message feedback
- Cross-worker messaging with Redis Pub/Sub
- Automatic token refresh with seamless UX
- Modern gradient design with glass-morphism effects
- Responsive layout for mobile and desktop
- Dynamic user status (online/offline indicators)
- Message timestamps and delivery indicators
- Smooth animations and transitions
- Empty state with engaging visuals
- Horizontal scalability with Node.js cluster mode
- Redis Pub/Sub for cross-worker communication
- Input validation with Joi schemas
- Rate limiting for API endpoints
- Centralized error handling
- Database connection resilience with retry logic
- Health check endpoints (liveness/readiness)
- Request logging with structured format
- JWT-based authentication with HttpOnly cookies
- Password hashing with bcrypt
- Input sanitization to prevent XSS attacks
- CORS configuration for allowed origins
- Rate limiting to prevent brute-force attacks
- Helmet.js for security headers
- Environment variable validation
ui/src/
├── Component/
│ ├── Main.jsx # Main container (orchestration)
│ ├── ChatSidebar.jsx # Sidebar with user list
│ ├── ChatArea.jsx # Chat messages and input
│ ├── Messages.jsx # Message display component
│ ├── UserList.jsx # Online/offline user list
│ └── ChatNav.jsx # Chat header with status
├── hooks/
│ ├── useChat.js # Chat state management hook
│ └── useWebSocket.js # WebSocket connection hook
├── redux/ # Redux store for auth
├── axios.js # Axios instance with interceptors
└── constant.js # API URLs and constants
api/src/
├── controller/
│ └── userController.js # User and message controllers
├── middleware/
│ ├── tokenmiddleware.js # JWT verification & refresh
│ ├── validationMiddleware.js # Input validation
│ ├── rateLimitMiddleware.js # Rate limiting
│ └── errorMiddleware.js # Error handling
├── model/
│ ├── user.js # User schema
│ └── Message.js # Message schema
├── routes/
│ ├── userRoutes.js # API routes
│ └── healthRoutes.js # Health check routes
├── services/
│ └── pubSubManager.js # Redis Pub/Sub manager
├── config/
│ ├── db.js # MongoDB connection
│ └── validateEnv.js # Environment validation
├── validation/
│ └── schemas.js # Joi validation schemas
└── websocketHandler.js # WebSocket logic
- Node.js (v18 or higher)
- MongoDB (v5.0 or higher)
- Redis (v6.0 or higher)
- npm or yarn
git clone <repository-url>
cd chat-appcd api
npm installcd ../ui
npm installCreate a .env file in the api directory:
# Server
PORT=5000
# Database
MONGODB_URI=mongodb://localhost:27017/chatdb
# Redis
REDIS_URL=redis://localhost:6379
# JWT Secrets (generate strong random strings)
ACCESS_TOKEN_SECRET=your_access_token_secret_here
REFRESH_TOKEN_SECRET=your_refresh_token_secret_here
# CORS (comma-separated list)
ALLOWED_ORIGIN=http://localhost:3000,http://192.168.1.100:3000
# Optional
LOG_LEVEL=infoUpdate ui/src/constant.js if needed:
export const WS_URL = 'http://localhost:5000'; // Backend URL-
Start MongoDB:
# Windows (if installed as service) net start MongoDB # macOS/Linux mongod --dbpath /path/to/data
-
Start Redis:
# Windows (with WSL or Redis for Windows) redis-server # macOS brew services start redis # Linux sudo systemctl start redis
-
Start the backend (from
apidirectory):npm start
This will start the server in cluster mode with multiple workers on port 5000.
-
Start the frontend (from
uidirectory):npm start
This will start the React development server on port 3000.
-
Open your browser:
http://localhost:3000
-
Build the frontend:
cd ui npm run build -
Set production environment variables in
api/.env:NODE_ENV=production
-
Start the backend with PM2 (recommended):
cd api npm install -g pm2 pm2 start src/index.js --name chat-api pm2 save pm2 startup -
Serve the frontend with Nginx or serve the build folder directly.
POST /api/register- Register new userPOST /api/login- Login userPOST /api/logout- Logout user
GET /api/profile- Get current user profileGET /api/alluser- Get all users (online/offline)
GET /api/messages/:userId- Get messages with specific user- Query params:
limit(default: 50),before(cursor for pagination)
- Query params:
GET /health/liveness- Check if server is runningGET /health/readiness- Check if server can serve traffic (DB + Redis)
// Send message
{
recipient: "userId",
text: "message text"
}
// Heartbeat (ping)
"ping"// Online/offline users update
{
online: [{ userId, username, profilePhoto }],
offline: [{ userId, username, profilePhoto }]
}
// New message
{
_id: "messageId",
text: "message text",
sender: "senderId",
recipient: "recipientId",
createdAt: "timestamp"
}
// Heartbeat response
"pong"-
Frontend Refactoring:
- Reduced Main.jsx from 486 lines to 153 lines (68% reduction)
- Extracted logic into custom hooks (
useChat,useWebSocket) - Created reusable presentational components
- Improved code maintainability and testability
-
Backend Production Readiness:
- Fixed token refresh middleware bug (now calls
next()) - Implemented Redis Pub/Sub for cross-worker messaging
- Added comprehensive input validation
- Implemented rate limiting on all endpoints
- Added centralized error handling
- Database connection resilience with retry logic
- Fixed token refresh middleware bug (now calls
-
Modern UI Design:
- Gradient color scheme (indigo → purple → pink)
- Glass-morphism effects with backdrop blur
- Smooth animations and transitions
- Responsive mobile-first design
- Token Refresh: Uses custom header (
X-New-Access-Token) to avoid double responses - Redis Pub/Sub: Preferred over Socket.IO for minimal code changes and better control
- Optimistic Updates: Messages appear instantly, improving perceived performance
- Cluster Mode: Utilizes all CPU cores for better performance
- Memoization: Uses React hooks (
useMemo,useCallback) to prevent unnecessary re-renders
-
Chat area not showing when selecting user:
- Ensure backend server has been restarted after code changes
- Check browser console for errors
- Verify API is returning
{ messages: [...] }format
-
WebSocket connection errors:
- Verify Redis is running:
redis-cli ping(should return "PONG") - Check CORS configuration in backend
.env - Ensure WebSocket URL uses correct protocol (
ws://orwss://)
- Verify Redis is running:
-
Token expired errors:
- Clear browser localStorage and re-login
- Verify
REFRESH_TOKEN_SECRETis set in.env - Check cookie settings allow HttpOnly cookies
-
Messages not appearing across workers:
- Verify Redis Pub/Sub channels are subscribed:
redis-cli PUBSUB CHANNELS - Check backend logs for Pub/Sub initialization messages
- Ensure all workers are connected to the same Redis instance
- Verify Redis Pub/Sub channels are subscribed:
- Check backend logs for detailed error messages
- Monitor Redis with:
redis-cli MONITOR - Check MongoDB connection:
mongoshand verify database exists - Use browser DevTools Network tab to inspect API requests/responses
- Enable verbose logging by setting
LOG_LEVEL=debugin.env
- User registration and login
- Real-time message sending/receiving
- Online/offline status updates
- Message persistence (refresh page)
- Token refresh (wait 25+ minutes)
- Cross-worker messaging (if using cluster mode)
- Mobile responsiveness
- Logout functionality
Use Artillery for load testing:
npm install -g artillery
artillery quick --count 100 --num 10 http://localhost:5000/api/alluser- Frontend: React.memo for components, useMemo/useCallback for expensive computations
- Backend: Database indexes on frequently queried fields, Redis caching for online users
- WebSocket: Heartbeat mechanism to detect stale connections, connection throttling
- Database: Pagination for message fetching, lean queries for better performance
- Never commit
.envfiles to version control - Use strong random strings for JWT secrets (32+ characters)
- Regularly update dependencies:
npm audit fix - Enable HTTPS in production
- Set secure cookies in production (
secure: true) - Implement additional validation for file uploads if adding that feature
- Monitor logs for suspicious activity
- Use environment-specific configurations
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit changes:
git commit -am 'Add some feature' - Push to branch:
git push origin feature/your-feature - Submit a pull request
This project is open source and available under the MIT License.
- Built with the MERN stack
- WebSocket implementation using native
wslibrary - UI design inspired by modern gradient aesthetics
- Redis Pub/Sub for scalable real-time architecture
For issues, questions, or contributions, please open an issue on GitHub.
Happy Chatting! 🚀💬