Skip to content

1Kyryll/Lychee-Chat

Repository files navigation

Lychee Chat

Real-time chat application built with Next.js and Socket.IO.

Tech Stack

Frontend

  • Next.js 16 (App Router, Server Components, Server Actions)
  • React 19
  • Tailwind CSS 4
  • Radix UI (Dialog, Label, Slot)
  • Socket.IO Client (real-time messaging)
  • jose (JWT verification)
  • bcryptjs (password hashing)

Backend

  • Express 5 + Socket.IO 4 (WebSocket server)
  • MongoDB + Mongoose 9 (database)
  • Redis + ioredis (pub/sub, caching)

Infrastructure

  • Docker + Docker Compose (containerized deployment)
  • Nginx (reverse proxy)
  • BullMQ + sharp (background image processing)

Architecture

apps/web        Next.js frontend (port 3000)
apps/ws         Express + Socket.IO server (port 4000)
packages/db     Mongoose models + MongoDB connection
packages/redis  Redis client, pub/sub, and cache utilities
nginx/          Nginx reverse proxy configuration

Monorepo managed with npm workspaces.

How it works

  1. Authentication via JWTs stored as HTTP-only cookies
  2. Client connects to Socket.IO for real-time messaging
  3. Messages are saved to MongoDB and published to Redis
  4. Redis pub/sub broadcasts messages to all connected clients in the room
  5. Contact lists and message history are cached in Redis

BullMQ — Background Image Processing

When a user sends images in a chat message, the WebSocket server handles them in two phases:

  1. Immediate save & broadcast — The raw images are converted to base64 data URIs, saved to the message in MongoDB, and included in the real-time Socket.IO broadcast. This means all clients see the images instantly.

  2. Async compression via BullMQ — A job is queued for each image on the processMedia queue. A BullMQ worker (apps/ws/workers/media.worker.ts) picks up each job, compresses the image using sharp (quality 70, preserving the original format), and replaces the uncompressed base64 in MongoDB with the compressed version using $set on the specific array index.

Client sends image
    -> message.send handler converts to base64, saves to MongoDB, broadcasts via Redis pub/sub
    -> addMediaJob() enqueues a job per image with { messageId, index, buffer, mimeType }
    -> media.worker picks up the job, compresses with sharp, overwrites media[index] in MongoDB

The queue and worker both use a dedicated Redis connection with maxRetriesPerRequest: null (required by BullMQ for its blocking commands). Jobs retry up to 3 times with exponential backoff and are removed on completion or failure.

Key files:

  • apps/ws/queues/media.queue.ts — Queue definition and addMediaJob helper
  • apps/ws/workers/media.worker.ts — Worker that compresses images with sharp
  • apps/ws/events/message.send.ts — Event handler that saves, broadcasts, and enqueues

Running with Docker Compose

Prerequisites

Setup

  1. Clone the repository:
git clone https://github.com/your-username/lychee-chat.git
cd lychee-chat
  1. Create a .env file in the project root:
DATABASE_URI=mongodb://MONGO_ROOT_USER:MONGO_ROOT_PASSWORD@mongo:27017/MONGO_DB?authSource=admin
REDIS_URL=redis://default:REDIS_PASSWORD@redis:6379
JWT_SECRET_KEY=your-secret-key

MONGO_ROOT_USER=admin
MONGO_ROOT_PASSWORD=password
MONGO_DB=lychee-chat

REDIS_PASSWORD=password
  1. Build and start all services:
docker compose up --build
  1. Open http://localhost:8080 in your browser.

Services

Service Description
web Next.js frontend
ws WebSocket server
mongo MongoDB database
redis Redis cache + pub/sub
nginx Reverse proxy (exposed on port 8080)

Useful commands

# Start in detached mode
docker compose up -d --build

# View logs
docker compose logs -f

# Stop all services
docker compose down

# Stop and remove volumes (resets database)
docker compose down -v

Local Development

# Install dependencies
npm install

# Start the Next.js dev server (port 3000)
cd apps/web && npm run dev

# Start the WebSocket server (port 4000)
cd apps/ws && node index.ts

Requires MongoDB and Redis running locally or via cloud services. Configure connection strings in .env.

About

A Chat web-application, build on NextJS, ExpressJS using Redis, MongoDB, BullMQ and WebSockets. Utilizes WebSockets, Redis caching and pub/sub, BullMQ workers and jobs.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors