https://github.com/howardsun-dev/quickchat
Proof of concept
https://github.com/howardsun-dev/quickchat
Last synced: about 1 month ago
JSON representation
Proof of concept
- Host: GitHub
- URL: https://github.com/howardsun-dev/quickchat
- Owner: howardsun-dev
- License: mit
- Created: 2025-12-18T18:12:29.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2026-05-21T01:39:14.000Z (about 1 month ago)
- Last Synced: 2026-05-21T08:00:18.140Z (about 1 month ago)
- Language: TypeScript
- Size: 9.34 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# QuickChat
[](https://quickchat-v72jh.sevalla.app/)
[](./LICENSE)
[](https://www.typescriptlang.org/)
A full-stack real-time chat application with JWT authentication, optimistic UI updates, online presence detection, and secure media uploads.
> Built with React, Node.js, Express, Socket.IO, MongoDB, and TypeScript.
---
## Features
- **Real-time messaging** — WebSocket-powered chat via Socket.IO with sub-second delivery
- **JWT authentication** — Secure login, signup, session management, and password reset flow
- **Optimistic UI updates** — Messages appear instantly in the UI before the server confirms delivery
- **Online presence** — Real-time online/offline detection with `lastSeen` tracking
- **Media uploads** — Image and file attachments stored via Cloudinary
- **Rate limiting & bot protection** — Arcjet shields the API from abuse
- **Responsive design** — Tailwind CSS + DaisyUI, works on desktop and mobile
- **Keyboard sound effects** — Optional audio feedback while typing
- **Forgot / reset password** — Email-based password recovery via Resend
## Architecture
▶ **[View Interactive Architecture Diagram on Excalidraw](https://excalidraw.com/#json=JwKDclbwls3OlS8_aU59l,4iiiypHTpFIY25fQ3lx1sw)**
### Overview
```
┌──────────────┐ HTTP REST ┌──────────────┐ Mongoose ┌────────────┐
│ React App │ ◄──────────────► │ Express API │ ◄────────────► │ MongoDB │
│ (Vite) │ │ (Node.js) │ │ (Atlas) │
│ │ WebSocket │ │ └────────────┘
│ Zustand + │ ◄──────────────► │ Socket.IO │ ┌──────────────────────────┐
│ Socket.IO │ │ (presence) │ │ Cloudinary · Resend · │
│ Client │ │ │ │ Arcjet (external svcs) │
└──────────────┘ └──────────────┘ └──────────────────────────┘
```
### Frontend
| Layer | Technology | Purpose |
|---|---|---|
| Framework | React 19 + Vite + TypeScript | SPA with fast HMR |
| State | Zustand | Global stores for auth and chat state |
| Routing | React Router | Client-side navigation |
| HTTP | Axios | REST API calls with cookies |
| Real-time | Socket.IO Client | WebSocket messaging, presence |
| Styling | Tailwind CSS + DaisyUI | Responsive, component-ready UI |
| Auth | useAuthStore | JWT token handling, session check |
### Backend
| Layer | Technology | Purpose |
|---|---|---|
| Server | Node.js + Express | REST API, static file serving (prod) |
| Database | MongoDB + Mongoose | User profiles, messages |
| Real-time | Socket.IO | Bidirectional event-based communication |
| Auth | JWT (jsonwebtoken) | Token-based authentication with cookies |
| Email | Resend | Password reset emails |
| Media | Cloudinary | Image/file uploads and transformations |
| Security | Arcjet | Rate limiting, bot detection |
| Validation | Zod (via Arcjet) | Request validation |
### Data Flow (Sending a Message)
1. User types and sends → React updates UI **optimistically** via Zustand
2. Axios POSTs to `/api/messages/send/:id`
3. Express stores the message in MongoDB via Mongoose
4. Socket.IO emits `newMessage` event to the recipient
5. Recipient's app receives the event → Zustand updates → UI re-renders
Online status, typing indicators, and unread counts all flow through the same Socket.IO channel.
## Project Structure
```
/
├── backend/ # Express API server
│ └── src/
│ ├── controllers/ # Route handlers (auth, messages, users)
│ ├── middlewares/ # JWT auth, socket auth, Arcjet
│ ├── models/ # Mongoose schemas (User, Message)
│ ├── routes/ # Express route definitions
│ ├── lib/ # DB, Socket.IO, Cloudinary, email config
│ └── server.ts # Entry point
├── frontend/ # React SPA
│ └── src/
│ ├── pages/ # Route-level components
│ ├── components/ # Reusable UI components
│ ├── store/ # Zustand stores (auth, chat)
│ ├── hooks/ # Custom hooks (keyboard sounds)
│ ├── lib/ # Axios instance, error helpers
│ └── App.tsx # Root component with routing
├── package.json # Root scripts (build, start, test)
└── README.md
```
## Getting Started
### Prerequisites
- Node.js 20+
- MongoDB instance (local or [Atlas](https://www.mongodb.com/atlas))
- [Cloudinary](https://cloudinary.com/) account
- [Arcjet](https://arcjet.com/) account
- [Resend](https://resend.com/) account (for password reset emails)
### Environment Variables
Copy the example file and fill in your local credentials:
```bash
cp backend/.env.example backend/.env
```
The backend reads environment variables from `backend/.env`. The most important values are:
```bash
MONGO_URI= # MongoDB connection string
JWT_SECRET= # Secret key for JWT signing
CLOUDINARY_CLOUD_NAME= # Cloudinary cloud name
CLOUDINARY_API_KEY= # Cloudinary API key
CLOUDINARY_API_SECRET= # Cloudinary API secret
ARCJET_KEY= # Arcjet API key
PORT= # Server port (default: 3000)
CLIENT_URL= # Frontend origin, e.g. http://localhost:5173
```
Optional password-reset email values:
```bash
RESEND_API_KEY=
EMAIL_FROM=
EMAIL_FROM_NAME=
```
See [`backend/.env.example`](./backend/.env.example) and `backend/src/lib/env.ts` for the full list of supported variables.
### Install & Run
```bash
# Install all dependencies
npm install
# Start in production mode (serves frontend from backend)
npm start
```
**Development mode** (separate terminals):
```bash
# Terminal 1 — Backend
cd backend
npm install
npm run dev
# Terminal 2 — Frontend
cd frontend
npm install
npm run dev
```
The backend must be running before starting the frontend. In development, the frontend proxies API calls to `localhost:3000`.
## API Endpoints
### Authentication — `/api/auth`
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | `/signup` | No | Create a new account |
| POST | `/login` | No | Sign in |
| POST | `/logout` | No | Clear session |
| GET | `/check` | JWT | Verify active session |
| POST | `/forgot-password` | No | Send reset email |
| POST | `/reset-password/:token` | No | Reset password with token |
| POST | `/change-password` | JWT | Change password (authenticated) |
| PUT | `/update-profile` | JWT | Update display name, avatar, etc. |
### Messages — `/api/messages`
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | `/contacts` | JWT | List all contacts |
| GET | `/chats` | JWT | List recent conversations |
| GET | `/:id` | JWT | Get messages with a specific user |
| POST | `/send/:id` | JWT | Send a message to a user |
### Users — `/api/user`
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | `/status/:id` | JWT | Get user online/lastSeen status |
## Testing
```bash
npm test
```
Tests are run with [Vitest](https://vitest.dev/).
## Deployment
QuickChat is deployed on [Sevalla](https://sevalla.app/). The production build serves the React frontend as static files from the Express server.
## License
MIT — see [LICENSE](./LICENSE) for details.