InkSync is a modern, real-time collaborative whiteboard platform built with a scalable pnpm monorepo, TypeScript, and Docker - designed for production from day one.
This repository contains the frontend, backend service and shared packages, fully containerized and deployed using Render.
- ✏️ Drawing Tools: Pen, rectangles, circles, and text annotations
- 🗑️ Eraser Tool: Click to delete individual strokes with improved detection
- ↶↷ Undo/Redo: Full history tracking with keyboard shortcuts (Ctrl+Z/Y)
- 🔍 Zoom & Pan: Mouse wheel zoom and middle-click pan navigation
- 🎨 Color Picker: Customizable stroke colors
- 👥 Real-time Collaboration: See other users' drawings instantly
- ⚡ No Login Required: Create and join boards instantly
- 🔗 Easy Sharing: Share board link with anyone
- 🧹 Auto Cleanup: Boards automatically destroyed after 30 minutes of inactivity
- 🗑️ Smart Cleanup: Empty boards cleaned up after 5 minutes
- 🏗️ Monorepo architecture using
pnpm workspaces - ⚡ TypeScript-first codebase
- 📦 Shared packages (
shared-types) for type safety - 🐳 Production‑ready Docker setup (multi‑stage build)
- 🚀 Deployed on Render with zero-config Docker runtime
- 🔒 Environment‑based configuration
- ♻️ Reproducible builds using
pnpm-lock.yaml - 🧹 Memory-efficient: Automatic board cleanup and lifecycle management
InkSync/
├─ apps/
│ └─ frontend/ # Frontend
│ ├─ src/
│ ├─ tsconfig.json
│ └─ package.json
│ └─ backend/ # Backend
│ ├─ src/
│ ├─ tsconfig.json
│ └─ package.json
│
├─ packages/
│ └─ shared-types/ # Shared TypeScript types
│ ├─ src/
│ ├─ tsconfig.json
│ └─ package.json
│
├─ Dockerfile # Production Docker build
├─ pnpm-lock.yaml # Dependency lockfile
├─ pnpm-workspace.yaml # Workspace configuration
├─ package.json # Root config
└─ README.md
- Framework: React 19
- Styling: Tailwind CSS (Vite integration)
- Canvas Rendering: Konva + React Konva
- Routing: React Router v7
- Realtime: Socket.IO Client
- UI Utilities: React Modal
- QR Sharing: qrcode.react
- Runtime: Node.js 20
- Framework: Express 5
- Realtime: Socket.IO
- Type Safety:
@whiteboard/shared-types(workspace package)
- Runtime: Node.js 20
- Language: TypeScript
- Package Manager: pnpm (workspaces)
- Containerization: Docker (multi-stage)
- Deployment: Render
- Package Manager: pnpm (workspaces)
- Containerization: Docker (multi-stage)
- Deployment: Render
- Node.js
>= 20 - pnpm
>= 9 - Docker (optional, for container testing)
Enable pnpm via Corepack:
corepack enableFrom the repository root:
pnpm installpnpm --filter @whiteboard/shared-types build
pnpm --filter @whiteboard/backend build
pnpm --filter @whiteboard/frontend buildpnpm --filter @whiteboard/backend devBackend will start on:
http://localhost:4000
docker build -t ink-sync .docker run -p 4000:4000 ink-syncThis project is deployed using Render Web Service (Docker runtime).
- Dockerfile is located at repo root
Root Directoryin Render is empty- Port is injected automatically by Render
- App listens on
process.env.PORT
No custom build or start commands are required.
Example .env:
NODE_ENV=production
PORT=4000.env files to version control.
A simple health endpoint is recommended:
GET /healthResponse:
{ "status": "ok" }pnpm install # Install all dependencies
pnpm build # Build all packages
pnpm dev # Start dev mode
pnpm lint # Run linter- Single source of truth for dependencies
- Shared types across services
- Fast installs with pnpm
- Docker‑first mindset
- ✅ Lockfile‑based installs
- ✅ Multi‑stage Docker builds
- ✅ Environment‑based config
- ✅ Graceful shutdown support
- ✅ Zero‑config CI/CD via Render
MIT © InkSync
Built with ❤️ By Nemish Gorasiya using pnpm, TypeScript and Docker.