Full-stack real-time chat with a FastAPI backend and a Next.js UI. Supports WebSocket messaging, PostgreSQL persistence, Redis pub/sub, JWT auth, presence, typing indicators, read receipts, reactions, and an AI assistant DM.
flowchart LR
Web[Next.js Web App] -->|HTTP + WS| API[FastAPI App]
API --> DB[(PostgreSQL)]
API --> R[(Redis Pub/Sub)]
API --> M[Metrics /health /ready /metrics]
app/FastAPI backend (API + WebSocket)next-js-chat-app/Next.js frontend
docker compose up --buildBackend will be available at http://localhost:8000.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export DATABASE_URL=postgresql://postgres:postgres@localhost:5432/chatdb
export REDIS_URL=redis://localhost:6379/0
export JWT_SECRET_KEY=change-me
uvicorn app.main:app --reloadcd next-js-chat-app
pnpm install
pnpm devSet the API base if you are not using the default backend URL:
export NEXT_PUBLIC_API_BASE_URL=http://localhost:8000Frontend will be available at http://localhost:3000.
Make sure Postgres and Redis are running (docker-compose is easiest):
docker compose up -d db redis
pytestThe tests expect DATABASE_URL to point to a reachable Postgres instance.
const token = "YOUR_JWT";
const ws = new WebSocket(`ws://localhost:8000/ws/chat?token=${token}`);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data);
};
ws.onopen = () => {
ws.send(JSON.stringify({ type: "join_room", room_id: "ROOM_UUID" }));
ws.send(JSON.stringify({
type: "send_message",
room_id: "ROOM_UUID",
content: "Hello from WebSocket!"
}));
};- Register and login:
curl -X POST http://localhost:8000/auth/register \
-H "Content-Type: application/json" \
-d '{"username":"alice","email":"alice@example.com","password":"Password123!"}'- Create a direct room:
curl -X POST http://localhost:8000/api/rooms \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d '{"room_type":"direct","member_ids":["OTHER_USER_UUID"]}'- Connect via WebSocket:
ws://localhost:8000/ws/chat?token=<TOKEN>
- Join room and send message:
{ "type": "join_room", "room_id": "ROOM_UUID" }
{ "type": "send_message", "room_id": "ROOM_UUID", "content": "Hi" }POST /auth/registerPOST /auth/loginGET /auth/mePOST /api/roomsGET /api/rooms/ai-dmGET /api/rooms/{room_id}/messagesPOST /api/rooms/{room_id}/readGET /api/rooms/{room_id}/online-usersGET /api/users/{user_id}/statusGET /metrics,/health,/ready
- Redis is used for pub/sub, presence, and rate limiting.
- Message history supports pagination, search, and filters.