A real-time full-stack chat application built with React, Node.js, MongoDB, Redis, and Socket.io.
Live Demo: yap-yap-gamma.vercel.app
- Real-time messaging via Socket.io
- Online presence β see who's currently online
- Typing indicators β live "user is typing..." feedback
- JWT authentication stored in HTTP-only cookies
- Persistent sessions using Zustand with localStorage
- Conversation management β create and browse DM threads
- Fully typed frontend with TypeScript + Zod validation
| Technology | Purpose |
|---|---|
| React 19 + TypeScript | UI framework |
| Vite | Build tool & dev server |
| Tailwind CSS v4 | Styling |
| Zustand | Global state management |
| TanStack Query | Server state & data fetching |
| React Hook Form + Zod | Form handling & validation |
| Socket.io Client | Real-time communication |
| Axios | HTTP client |
| Lucide React | Icons |
| Sonner | Toast notifications |
| React Router v7 | Client-side routing |
| Technology | Purpose |
|---|---|
| Node.js + Express 5 | REST API server |
| MongoDB + Mongoose | Primary database |
| Redis (ioredis) | Online user tracking & socket ID mapping |
| Socket.io | WebSocket server |
| JSON Web Tokens | Authentication |
| bcrypt | Password hashing |
| cookie-parser | HTTP-only cookie handling |
YapYap/
βββ backend/
β βββ config/
β β βββ db.js # MongoDB connection
β β βββ redis.js # Redis client setup
β βββ controllers/
β β βββ authController.js
β β βββ conversationController.js
β β βββ messageController.js
β βββ middlewares/
β β βββ authMiddleware.js # JWT verification
β β βββ errorHandling.js
β βββ models/
β β βββ userModel.js
β β βββ conversation.js
β β βββ message.js
β βββ routes/
β β βββ authRouter.js
β β βββ conversationRouter.js
β β βββ messageRouter.js
β βββ services/
β βββ socket/
β β βββ socketHandler.js # Socket.io init, online users, typing events
β βββ utils/
β βββ app.js # Express app setup & CORS
β βββ server.js # HTTP server + Socket.io bootstrap
β βββ docker-composer.yaml # Local MongoDB & Redis via Docker
β
βββ frontend/
βββ src/
β βββ components/
β β βββ ChatWindow/ # Message list, MessageInput
β β βββ Sidebar/ # Conversation list, user search
β β βββ common/ # Shared UI (SplashScreen, Avatar, etc.)
β βββ context/
β β βββ SocketContext # Socket.io client provider
β βββ hooks/ # Custom React hooks
β βββ pages/ # Route-level pages (Auth, Home, etc.)
β βββ services/ # Axios API service functions
β βββ stores/
β β βββ authStore.ts # Zustand auth state (persisted)
β β βββ chatStore.ts # Zustand chat/conversation state
β βββ utils/
βββ index.html
- Node.js 18+
- Docker (for running MongoDB & Redis locally)
git clone https://github.com/your-username/YapYap.git
cd YapYapcd backend
docker compose -f docker-composer.yaml up -dThis spins up:
- MongoDB on
localhost:27017 - Redis on
localhost:6379
cd backend
cp .env.example .envEdit .env:
FRONTEND_URI=http://localhost:5173
PORT=3000
MONGO_URI=mongodb://localhost:27017/yapyap
REDIS_URI=redis://localhost:6379
JWT_SECRET=your_strong_secret_here
NODE_ENV=developmentcd backend
npm install
npm run devThe API server runs on http://localhost:3000.
cd frontend
cp .env.example .env.env should contain:
VITE_API_URL=http://localhost:3000/api
VITE_SOCKET_URL=http://localhost:3000cd frontend
npm install
npm run devThe app runs on http://localhost:5173.
| Method | Endpoint | Description |
|---|---|---|
POST |
/register |
Register a new user |
POST |
/login |
Login (returns HTTP-only JWT cookie) |
POST |
/logout |
Clear auth cookie |
GET |
/me |
Get the currently authenticated user |
| Method | Endpoint | Description |
|---|---|---|
GET |
/ |
List all conversations for the current user |
POST |
/ |
Create or fetch a DM conversation |
| Method | Endpoint | Description |
|---|---|---|
GET |
/:conversationId |
Get all messages in a conversation |
POST |
/:conversationId |
Send a message |
| Event | Direction | Payload | Description |
|---|---|---|---|
online_users |
Server β Client | string[] |
Emitted on connect/disconnect with full online user list |
new_message |
Server β Client | Message |
Delivers a new message to the recipient |
new_conversation |
Server β Client | Conversation |
Notifies recipient of a new conversation |
typing_start |
Client β Server | { receiverId } |
User started typing |
typing_stop |
Client β Server | { receiverId } |
User stopped typing |
user_typing |
Server β Client | { userId, isTyping } |
Forwarded typing state to recipient |
| Variable | Description | Example |
|---|---|---|
PORT |
Server port | 3000 |
FRONTEND_URI |
Allowed CORS origin (no trailing slash) | https://yap-yap-gamma.vercel.app |
MONGO_URI |
MongoDB connection string | mongodb+srv://... |
REDIS_URI |
Redis connection string | redis://... |
JWT_SECRET |
Secret for signing JWTs | a_long_random_string |
NODE_ENV |
Environment | production |
| Variable | Description | Example |
|---|---|---|
VITE_API_URL |
Backend API base URL | https://yapyap-7bk9.onrender.com/api |
VITE_SOCKET_URL |
Backend socket URL | https://yapyap-7bk9.onrender.com |
- Connect the
backend/directory as the root of your Render web service. - Set Build Command:
npm install - Set Start Command:
node server.js - Add all environment variables from the table above in the Render dashboard.
- Set
FRONTEND_URIto your exact Vercel URL (no trailing slash).
- Connect the
frontend/directory as the root of your Vercel project. - Set Framework Preset: Vite
- Set Build Command:
npm run build - Set Output Directory:
dist - Add
VITE_API_URLandVITE_SOCKET_URLpointing to your Render backend URL.
Note: Both services must be deployed for the app to function. Socket.io requires the backend to be publicly accessible.
MIT