A full-stack, real-time messaging application inspired by WhatsApp and Discord. Built with a modern TypeScript stack, it supports private and group conversations, a friend system, file sharing, and live presence — all over WebSockets.
Most chat tutorials stop at "send a string over Socket.IO." This project goes further and implements the features users actually expect from a production messaging app:
- Dual-token auth — short-lived access tokens + long-lived refresh tokens with silent renewal.
- Cursor-based pagination — efficient message loading that scales with conversation history.
- Optimistic UI — messages appear instantly while the server confirms in the background.
- Real-time everything — not just messages, but typing indicators, read receipts, presence, and friend request notifications are all pushed over WebSockets.
- Security defaults — Helmet, CORS whitelist, per-endpoint rate limiting, bcrypt password hashing, and no hardcoded secrets.
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | React 19 + Vite 7 | SPA with HMR, TypeScript, dark theme UI |
| Backend | Express 5 + Node.js | RESTful API, middleware pipeline |
| Real-Time | Socket.IO 4.8 | Bidirectional WebSocket communication |
| Database | PostgreSQL + Prisma 5 | Relational data, type-safe ORM |
| Auth | JWT (jsonwebtoken 9) + bcrypt | Access/Refresh token pair |
| File Upload | Multer 2 | Local disk storage with MIME validation |
| Security | Helmet, CORS, express-rate-limit | HTTP hardening, origin control, abuse prevention |
- Register / Login / Logout
- JWT access token (15 min) + refresh token (7 days)
- Automatic silent token refresh via Axios interceptor
- Passwords hashed with bcrypt (cost factor 12)
- Rate-limited API endpoints
- Private (1-on-1) and group conversations
- Real-time message delivery over Socket.IO
- Edit and delete sent messages
- Reply to specific messages (threaded replies)
- File & image attachments (10 MB limit, MIME-type validated)
- Unread message counter per conversation
- Typing indicators
- Date separators (Today, Yesterday, full date)
- Cursor-based pagination for message history
- User search by username
- Send / accept / reject friend requests
- Real-time friend request notifications
- Friend list with quick-message action
- Online / Offline / Away / Busy status tracking
- Last-seen timestamps
- Real-time status broadcast to contacts
- Dark theme with gradient avatars
- Responsive layout (sidebar collapses below 768 px)
- Inter font family
- Smooth CSS transitions and animations
├── client/ # React frontend (Vite + TypeScript)
│ ├── src/
│ │ ├── components/ # Auth, Chat, Sidebar, Friends, Group, Profile
│ │ ├── contexts/ # AuthContext, SocketContext, ChatContext
│ │ ├── services/api.ts # Axios instance + token refresh interceptor
│ │ ├── types/ # Shared TypeScript interfaces
│ │ └── styles/global.css # Dark theme styles
│ └── vite.config.ts # Dev proxy → backend
│
├── server/ # Express backend (TypeScript)
│ ├── index.ts # App entry — Express + Socket.IO bootstrap
│ ├── prisma/schema.prisma # 8 models (User, Conversation, Message, …)
│ └── src/
│ ├── config/database.ts # Prisma client singleton
│ ├── middleware/ # JWT auth, Multer upload
│ ├── routes/ # auth, users, conversations, messages, friends
│ └── socket/index.ts # Real-time event handlers
│
├── schema.sql # Raw SQL DDL (alternative to Prisma migrate)
├── .env.example → server/ # Environment variable template
└── README.tr.md # Turkish documentation
| Tool | Minimum Version |
|---|---|
| Node.js | 18+ |
| PostgreSQL | 14+ |
| npm | 9+ |
git clone https://github.com/cekYc/be-like-whatsapp-or-discord.git
cd be-like-whatsapp-or-discordpsql -U postgres -c "CREATE DATABASE mesajlar_db;"cp server/.env.example server/.envEdit server/.env and set your values:
DATABASE_URL="postgresql://postgres:YOUR_PASSWORD@localhost:5432/mesajlar_db?schema=public"
JWT_SECRET="generate-a-strong-random-string"
JWT_REFRESH_SECRET="generate-another-strong-random-string"
PORT=3000
CLIENT_URL="http://localhost:5173"Generate secure secrets:
openssl rand -base64 64
cd server
npm install
npx prisma db push # Create tables
npx prisma generate # Generate Prisma client
npm run dev # Start with hot-reload (nodemon)Backend runs at http://localhost:3000.
cd client
npm install
npm run devFrontend runs at http://localhost:5173.
Vite's dev proxy forwards /api/* and /socket.io requests to the backend automatically.
cd client && npm run build # Outputs to client/dist/Serve client/dist/ with any static file server, or configure Express to serve it with express.static.
All variables are defined in server/.env.example.
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection URI | — (required) |
JWT_SECRET |
Signing key for access tokens | — (required) |
JWT_REFRESH_SECRET |
Signing key for refresh tokens | — (required) |
PORT |
Backend listening port | 3000 |
CLIENT_URL |
Allowed CORS origin | http://localhost:5173 |
UPLOAD_DIR |
File upload directory | ./uploads |
NODE_ENV |
development or production |
development |
The server will not start if
JWT_SECRETorJWT_REFRESH_SECRETis missing — fail-fast by design.
| Method | Endpoint | Description |
|---|---|---|
| POST | /register |
Create a new account |
| POST | /login |
Authenticate and receive tokens |
| POST | /logout |
Invalidate session |
| POST | /refresh |
Exchange refresh token for new access token |
| GET | /me |
Get current authenticated user |
| Method | Endpoint | Description |
|---|---|---|
| GET | /search?q= |
Search users by username |
| GET | /:id |
Get user profile |
| PUT | /profile |
Update own profile |
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
List all conversations |
| POST | /private |
Start a private (1-on-1) chat |
| POST | /group |
Create a group conversation |
| Method | Endpoint | Description |
|---|---|---|
| GET | /:conversationId |
Get messages (cursor-paginated) |
| POST | /:conversationId |
Send a text message |
| POST | /:conversationId/upload |
Send a message with file attachment |
| PUT | /:id |
Edit a message |
| DELETE | /:id |
Delete a message |
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
List friends |
| POST | /request |
Send a friend request |
| GET | /requests/incoming |
List received requests |
| GET | /requests/outgoing |
List sent requests |
| PUT | /accept/:id |
Accept a request |
| PUT | /reject/:id |
Reject a request |
| DELETE | /:id |
Remove a friend |
| Event | Payload | Description |
|---|---|---|
join:conversation |
conversationId |
Join a conversation room |
leave:conversation |
conversationId |
Leave a room |
message:send |
{ conversationId, content, type, replyToId } |
Send a message |
message:edit |
{ messageId, content } |
Edit a message |
message:delete |
{ messageId } |
Delete a message |
message:read |
{ conversationId } |
Mark conversation as read |
typing:start |
conversationId |
Broadcast typing start |
typing:stop |
conversationId |
Broadcast typing stop |
| Event | Description |
|---|---|
message:new |
New message received |
message:edited |
Message was edited |
message:deleted |
Message was deleted |
message:read |
Read receipt update |
conversation:updated |
Conversation list changed |
user:status |
User online/offline status changed |
typing:start / typing:stop |
Typing indicator toggle |
friend:request:received |
Incoming friend request |
friend:request:accepted |
Friend request was accepted |
8 tables managed via Prisma ORM:
users · conversations · conversation_members · messages · attachments · message_reads · blocked_users · friendships
Full schema: server/prisma/schema.prisma — Detailed Turkish documentation: VERITABANI.md
- Profile editing UI (avatar, display name, status message)
- Message context menu (edit / delete / reply)
- Group management (add/remove members, rename)
- Browser push notifications
- Emoji picker
- In-chat message search
- User blocking (backend ready, UI pending)
- Read receipt indicators (double-check marks)
- Image lightbox preview
- Voice / video messages
- Link previews (Open Graph)
- Light / dark theme toggle
- i18n (multi-language support)
- Email verification & password reset
- Two-factor authentication (TOTP)
- Cloud file storage (S3 / Cloudinary)
- End-to-end encryption (E2EE)
- Docker Compose setup
- Test suite (Jest / Vitest)
- CI/CD pipeline (GitHub Actions)
This project is for personal and educational use.