Sketchboard is a collaborative drawing application featuring a real-time canvas, multiplayer synchronization.
Sketchboard is a modern monorepo application built for real-time collaborative drawing experiences. It combines a blazing-fast Next.js frontend, WebSocket-powered collaboration, BullMQ-based persistence, and shared packages for scalable full-stack development.
- π¨ Real-time collaborative canvas
- β‘ WebSocket-powered live synchronization
- π Authentication system with JWT
- π§ Persistent room history using BullMQ workers (comming soon)
- π¦ Turborepo monorepo architecture
- ποΈ Prisma ORM + PostgreSQL
- π― Shared UI & TypeScript packages
- π¨ TailwindCSS shared configuration
- π§© Fully modular backend architecture
This project, Sketchboard, is a full-stack monorepo designed for a collaborative drawing application. It uses pnpm workspaces for package management and Turborepo for build orchestration.
The project is split into Applications (runnable services) and Packages (shared libraries).
π± Applications (apps/)
- web: A Next.js frontend application using the App Router.
- Styling: Tailwind CSS and Vanilla CSS.
- Canvas Logic: Located in app/draw/ and app/canvas/, handling the core drawing functionality.
- Features: Includes Sign-in/Sign-up flows, a dashboard, and collaborative drawing rooms ([roomId]).
- http-backend: A Node.js service (likely Express) handling RESTful operations.
- Modules: Auth, Room management, and Middleware.
- ws-backend: A dedicated WebSocket server.
- Handles real-time collaboration, allowing multiple users to draw on the same canvas simultaneously.
- Includes a queue-worker for processing messages.
π¦ Shared Packages (packages/)
- db: Centralized database logic using Prisma ORM. It defines the schema.prisma used by both backends.
- common: Shared TypeScript types and constants used by both the frontend and backends to ensure type safety across the stack.
- be-common: Shared logic specifically for the backend services.
- ui: A shared React component library (includes a Button.tsx and uses Tailwind).
- eslint-config & typescript-config: Standardized linting and TypeScript configurations used across all sub-projects.
π οΈ Key Technologies
- Frontend: Next.js, React, Tailwind CSS, Lucide React (implied by icons).
- Backend: Node.js, TypeScript, WebSockets.
- Database: Prisma (PostgreSQL/MySQL based on typical Prisma usage).
- Monorepo Tools: pnpm, Turborepo.
This structure allows for high code reuse (especially types and database schemas) and keeps the real-time drawing logic (ws-backend) separate from the standard API logic (http-backend).
Sketchboard/
β
βββ apps/
β βββ web/ # Next.js frontend
β βββ http-backend/ # Express REST API
β βββ ws-backend/ # WebSocket server + BullMQ workers
β
βββ packages/
β βββ db/ # Prisma client wrapper
β βββ common/ # Shared types & zod schemas
β βββ ui/ # Shared Tailwind/UI config
β
βββ prisma/ # Prisma schema & migrations
βββ turbo.json- Next.js (App Router)
- React
- TypeScript
- TailwindCSS
- WebGL / Shader-based visuals
- Express.js
- WebSocket Server
- BullMQ
- Redis
- Prisma ORM
- PostgreSQL
- Redis
- Turborepo
- pnpm
| File | Description |
|---|---|
apps/web/components/Canvas.tsx |
Main collaborative canvas wrapper |
apps/web/app/draw/* |
Drawing engine & shape handling |
apps/web/components/AuthPage.tsx |
Authentication UI |
apps/web/components/LaserFlowBoxExample.tsx |
Demo shader wrapper |
| File | Description |
|---|---|
apps/http-backend/src/index.ts |
Express server bootstrap |
auth.service.ts |
Authentication logic |
room.ts |
Room history endpoints |
apps/ws-backend/src/index.ts |
WebSocket server |
messages.worker.ts |
BullMQ persistence worker |
Before starting the project, make sure you have:
- Node.js
18+ pnpm- PostgreSQL database
- Redis server
Create a .env file in the apps/http-backend and apps/web and apps/ws-backend and packages/db directories.
The following environment variables are required: http-backend
FRONTEND_URL=localhost:3000
PORT=3002
JWT_SECRET=your_jwt_secret_keyweb
BACKEND_URL=localhost:3002ws-backend
PORT=8080
REDIS_URL=redis://localhost:6379
JWT_SECRET=your_jwt_secret_keydb
DATABASE_URL="postgresql://postgres:mypassword@localhost:5432/postgres"git clone https://github.com/samarkun23/Excellidraw.git
cd Excellidrawpnpm installCreate a .env file and add the required variables.
pnpm turbo devpnpm turbo dev --filter=webcd apps/web
pnpm devcd apps/http-backend
pnpm devcd apps/ws-backend
pnpm devpnpm turbo buildClient β WebSocket Server β BullMQ Queue β Worker β Database
- The client connects to the WebSocket server.
- Drawing events are emitted in real time.
- Messages are queued using BullMQ.
- Workers persist data into PostgreSQL.
- Room history is fetched through the HTTP backend.
Shared Tailwind presets are located in:
packages/uiMake sure your frontend imports the shared preset correctly.
Run migrations before starting the backend:
cd packages/db
npx prisma migrate dev
npx prisma generateIf you encounter hydration mismatches in Next.js:
- Use
"use client"for browser-only components - Avoid
Date.now()orMath.random()during SSR - Keep server/client-rendered values deterministic
Ensure:
position: fixed;
inset: 0;
height: 100vh;Also resize the canvas using devicePixelRatio for crisp rendering.
- Verify
WS_URL - Ensure the WebSocket server is running
- Confirm ports match frontend config
- Check if Redis is running
- Verify
REDIS_URL - Ensure workers are started
Contributions are welcome!
- Fork the repository
- Create a feature branch
- Commit your changes
- Open a pull request
Please keep frontend and backend changes separated whenever possible.
- Multiplayer cursors
- Undo / Redo synchronization
- File export support
- Presence indicators
- End-to-end encryption
- AI-assisted drawing tools
- More drawing tools
- Chat support
If you like this project:
- Give it a β on GitHub
- Share it with developers
- Contribute new features
Built with passion using modern web technologies.


