A full-stack real-time chat application with Socket.io, Redis presence tracking, and a React frontend.
- JWT authentication with refresh tokens
- Real-time messaging via Socket.io with Redis adapter (horizontal scaling ready)
- Room-based chat: create, join, leave rooms
- Typing indicators with debounce
- Message soft-delete
- Read receipts
- Online/offline presence tracking via Redis
- Dark theme React frontend with Zustand state management
| Layer | Technology |
|---|---|
| Backend | NestJS 11 |
| Database | MongoDB 7 + Mongoose |
| Real-time | Socket.io + @socket.io/redis-adapter |
| Presence | Redis 7 (ioredis) |
| Auth | JWT (access + refresh tokens) |
| Frontend | React + Vite + TypeScript |
| State | Zustand |
┌─────────────────────────────────────────────────────┐
│ React Frontend │
│ Login/Register → Chat (Sidebar + Messages + Input) │
│ Zustand stores: auth, chat │
│ Socket.io client: real-time events │
└───────────────────────┬─────────────────────────────┘
│ HTTP + WebSocket
┌───────────────────────▼─────────────────────────────┐
│ NestJS Backend │
│ AuthModule → JWT + bcrypt │
│ RoomsModule → CRUD, membership │
│ ChatGateway → Socket.io WebSocket events │
│ PresenceService → Redis SETEX/DEL/GET │
└───────────┬───────────────────────┬─────────────────┘
│ │
┌───────▼──────┐ ┌────────▼────────┐
│ MongoDB │ │ Redis │
│ Users │ │ presence:* │
│ Rooms │ │ Socket adapter │
│ Messages │ └─────────────────┘
└──────────────┘
| Event | Direction | Payload | Description |
|---|---|---|---|
join-room |
Client → Server | { roomId } |
Join a chat room |
send-message |
Client → Server | { roomId, content, replyTo? } |
Send a message |
typing |
Client → Server | { roomId, isTyping } |
Typing indicator |
mark-read |
Client → Server | { roomId, messageId } |
Mark message read |
delete-message |
Client → Server | { messageId } |
Soft-delete message |
new-message |
Server → Client | Message object | New message in room |
user:typing |
Server → Room | { userId, username, isTyping } |
Typing broadcast |
message:deleted |
Server → Room | { messageId } |
Message deleted |
message:read |
Server → Room | { messageId, userId } |
Read receipt |
user:online |
Server → All | { userId } |
User came online |
user:offline |
Server → All | { userId } |
User went offline |
# 1. Start MongoDB and Redis
cd backend && docker compose up -d
# 2. Start backend
cd backend && cp .env.example .env && npm install && npm run start:dev
# 3. Start frontend
cd frontend && cp .env.example .env && npm install && npm run devBackend API: http://localhost:3000/api
Frontend: http://localhost:5173
cd backend && npm testTests cover: RoomsService (ForbiddenException on non-member, $addToSet safe joins, $pull operator).