This is a full-stack, real-time drawing and collaboration application that allows multiple users to join rooms, draw on a shared canvas, and exchange data in real-time.
Screencast.from.2025-12-22.19-59-16.webm
The application uses a decoupled, scalable architecture. A Next.js client communicates with an HTTP backend for authentication and room management, while a dedicated WebSocket server handles all real-time data exchange. A message queue is used to process and persist data asynchronously.
graph TD
subgraph "Client (Next.js)"
A[Browser]
end
subgraph "Backend Infrastructure"
B(HTTP Backend - Express.js)
C(WebSocket Backend - ws)
D(Database - PostgreSQL)
H(Message Queue - Redis & BullMQ)
end
subgraph "Services"
E(Authentication)
F(Room Management)
G(Real-time Data Events)
end
A -- "HTTP Requests (Login, Signup, etc.)" --> B
A -- "WebSocket Connection" --> C
B -- "User Authentication" --> E
B -- "Room Creation/Validation" --> F
B -- "Database Queries (Prisma)" --> D
C -- "Publishes Drawing & Chat Data" --> G
C -- "Adds Jobs to Queue" --> H
C -- "Broadcasts to Clients" --> A
H -- "Worker Processes Jobs (e.g., Save Chat)" --> D
E -- "Manages User Data" --> D
F -- "Manages Room Data" --> D
- User Authentication: Secure user registration and login with JWT-based session management.
- Room-Based Collaboration: Users can create or join rooms to collaborate with others.
- Real-Time Drawing: A shared canvas where multiple users can draw simultaneously.
- Real-Time Data Exchange: The backend is equipped to handle real-time data, including chat messages, with persistence handled by a message queue.
- Scalable Architecture: The decoupled backend ensures that the application can handle a growing number of users.
- Frontend: Next.js, React, Tailwind CSS
- HTTP Backend: Express.js, TypeScript
- WebSocket Backend: ws, TypeScript
- Database: PostgreSQL, Prisma
- Message Queue: Redis, BullMQ
- Monorepo Management: pnpm, Turborepo
- Validation: Zod
To get the project up and running on your local machine, follow these steps.
-
Clone the repository:
git clone https://github.com/your-username/drawing-app.git cd drawing-app -
Install dependencies:
pnpm install
-
Set up the database and Redis:
- Start PostgreSQL and Redis instances using Docker:
docker run --name drawing-app-db -e POSTGRES_PASSWORD=mysecretpassword -p 5432:5432 -d postgres docker run --name drawing-app-redis -p 6379:6379 -d redis
- Create a
.envfile inpackages/dbby copying the example:cp packages/db/.env.example packages/db/.env
- Update the
DATABASE_URLinpackages/db/.envwith your database credentials.
- Start PostgreSQL and Redis instances using Docker:
-
Set up the backends:
- Create
.envfiles for the HTTP and WebSocket backends:cp apps/http-backend/.env.example apps/http-backend/.env cp apps/ws-backend/.env.example apps/ws-backend/.env
- Update the environment variables in the
.envfiles. EnsureREDIS_URLinapps/ws-backend/.envis set (e.g.,redis://localhost:6379).
- Create
-
Run database migrations:
pnpm db:migrate
-
Start the development servers:
pnpm dev
This will start the client, HTTP backend, and WebSocket backend in development mode. The application will be accessible at http://localhost:3000.
The project is a monorepo managed with pnpm and Turborepo.
apps:client: The Next.js frontend.http-backend: The Express.js backend for API requests.ws-backend: The WebSocket backend for real-time communication.
packages:backend-common: Shared utilities for the backends.common: Shared types and interfaces.db: The Prisma schema and database client.eslint-config: Shared ESLint configurations.typescript-config: Shared TypeScript configurations.worker: A worker service for processing jobs from the message queue (e.g., saving chat messages).
The HTTP backend provides the following endpoints:
POST /auth/signup: Register a new user.POST /auth/login: Log in a user and create a session.POST /room/create: Create a new collaboration room.GET /room/:roomId: Get the details of a specific room.GET /room/join/:roomId: Join a specific room.
All endpoints under /room require authentication.
The WebSocket backend handles the following real-time events:
join-room: Sent when a user joins a room.leave-room: Sent when a user leaves a room.send-data: A generic event for sending data to other users in a room. Themessagepayload contains the specific data type (e.g.,drawing,cursor, or chat messages). Non-drawing data is queued for persistence.
Refer to the .env.example files in each application's directory for a complete list of variables.
apps/http-backend:DATABASE_URL: Connection string for the PostgreSQL database.JWT_SECRET: Secret key for signing JWTs.PORT: Server port.
apps/ws-backend:PORT: WebSocket server port.REDIS_URL: Connection URL for the Redis instance.
packages/db:DATABASE_URL: Connection string for the PostgreSQL database.
Contributions are welcome! If you have any ideas, suggestions, or bug reports, please open an issue or submit a pull request.