A modern, real-time collaborative drawing application built with React, TypeScript, Node.js, and Socket.IO. Draw.Wine allows multiple users to collaborate on digital canvases in real-time with a rich set of drawing tools and features.
- Selection Tool: Select, move, and resize elements
- Basic Shapes: Rectangle, Diamond, Circle, Arrow, Line
- Free Drawing: Pencil tool for hand-drawn sketches
- Text Tool: Add text elements with customizable fonts
- Image Tool: Insert and manipulate images
- Eraser: Remove elements with precision
- Laser Pointer: Temporary laser trail for presentations
- Real-time Synchronization: All drawing operations sync instantly across users
- Live Cursors: See other users' cursors moving in real-time
- User Awareness: View active collaborators with colored indicators
- Room-based Sessions: Join specific rooms for focused collaboration
- User Identification: Custom names and colors for each collaborator
- Rough.js Integration: Hand-drawn, sketchy appearance for shapes
- Customizable Styling: Stroke colors, widths, and roughness levels
- Element Management: Layer-based element handling
- Viewport Controls: Pan and zoom functionality
- Auto-save: Automatic local storage of drawing progress
- Export Capabilities: Save drawings locally
- WebSocket Communication: Real-time bidirectional communication
- Responsive Design: Works on desktop and mobile devices
- Performance Optimized: Efficient rendering and state management
- Type Safety: Full TypeScript implementation
- Modern UI: Radix UI components with Tailwind CSS styling
- Node.js (v16 or higher)
- npm or yarn package manager
-
Clone the repository
git clone https://github.com/pandarudra/draw.wine.git cd draw.wine -
Install backend dependencies
cd be npm install -
Install frontend dependencies
cd ../fe npm install -
Set up environment variables
Create a
.envfile in thebedirectory:PORT=3001 NODE_ENV=development FE_URL_PROD=https://your-frontend-domain.com
-
Start the development servers
Backend (from
bedirectory):npm run dev
Frontend (from
fedirectory):npm run dev
-
Access the application
- Frontend: http://localhost:5173
- Backend API: http://localhost:3001
be/
โโโ src/
โ โโโ index.ts # Express server setup
โ โโโ controllers/ # Route controllers
โ โโโ events/
โ โ โโโ socket.event.ts # Socket.IO event handlers
โ โโโ services/
โ โ โโโ socket.service.ts # WebSocket service
โ โโโ routes/
โ โ โโโ rooms.routes.ts # API routes
โ โโโ types/
โ โ โโโ index.ts # TypeScript interfaces
โ โโโ utils/ # Utility functions
โ โโโ env/
โ โโโ e.ts # Environment configuration
โโโ package.json
Key Technologies:
- Express.js: Web application framework
- Socket.IO: Real-time WebSocket communication
- TypeScript: Type-safe JavaScript development
- Helmet: Security middleware
- CORS: Cross-origin resource sharing
- Rate Limiting: API protection
fe/
โโโ src/
โ โโโ components/
โ โ โโโ custom/ # Application-specific components
โ โ โ โโโ CanvasBoard.tsx
โ โ โ โโโ Toolbar.tsx
โ โ โ โโโ CollabRoom.tsx
โ โ โ โโโ modals/
โ โ โโโ ui/ # Reusable UI components
โ โโโ contexts/
โ โ โโโ DrawingContext.tsx # Drawing state management
โ โ โโโ CollabContext.tsx # Collaboration state
โ โโโ pages/
โ โ โโโ Landing.tsx # Entry point
โ โ โโโ PlayGround.tsx # Main drawing interface
โ โ โโโ CollabRoom.tsx # Collaboration room
โ โโโ utils/ # Utility functions
โ โโโ constants/ # Application constants
โ โโโ types/ # TypeScript definitions
โโโ package.json
Key Technologies:
- React 19: UI library with latest features
- TypeScript: Type safety and better development experience
- Vite: Fast build tool and development server
- Tailwind CSS: Utility-first CSS framework
- Radix UI: Accessible component primitives
- Socket.IO Client: Real-time communication
- Rough.js: Hand-drawn style graphics
- React Router: Client-side routing
| Event | Payload | Description |
|---|---|---|
join_room |
{ roomId: string, user: UserInfo } |
Join a collaboration room |
drawing_operation |
{ roomId: string, operation: DrawingOperation } |
Send drawing changes |
cursor_update |
{ roomId: string, position: Position } |
Update cursor position |
laser_point |
{ roomId: string, point: Position, userId: string, timestamp: number } |
Laser pointer trail |
laser_clear |
{ roomId: string, userId: string } |
Clear laser trail |
leave_room |
{ roomId: string } |
Leave collaboration room |
| Event | Payload | Description |
|---|---|---|
room_joined |
{ roomId: string, elements: Element[], collaborators: User[] } |
Confirmation of room join |
operation_applied |
DrawingOperation |
Broadcast drawing changes |
collaborators_updated |
User[] |
Updated list of active users |
cursor_moved |
{ userId: string, position: Position } |
Other user's cursor movement |
laser_point |
{ userId: string, point: Position, timestamp: number } |
Other user's laser point |
laser_clear |
{ userId: string } |
Clear other user's laser |
| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Server health check and connection stats |
GET |
/api/rooms/* |
Room management endpoints (extensible) |
- Solo Drawing: Navigate to
/board/[id]for individual drawing - Collaborative Drawing: Go to
/collab?room=[roomId]&name=[username]
- Select Tool: Click to select and manipulate existing elements
- Shape Tools: Click and drag to create rectangles, circles, diamonds
- Line/Arrow: Click start point, then end point
- Pencil: Click and drag for freehand drawing
- Text: Click to place text, then type
- Image: Click to upload and place images
- Eraser: Click elements to delete them
- Laser: Temporary pointer for presentations
- Join Room: Enter room ID and username to collaborate
- See Collaborators: View active users in the top-right panel
- Live Cursors: See where others are working
- Real-time Sync: All changes appear instantly for everyone
Backend:
npm run dev # Start development server with hot reload
npm run build # Build TypeScript to JavaScript
npm run start # Start production serverFrontend:
npm run dev # Start Vite development server
npm run build # Build for production
npm run preview # Preview production build
npm run lint # Run ESLint// User representation
interface User {
id: string;
name: string;
color: string;
cursor?: Position;
socketId: string;
isDrawing?: boolean;
currentElementId?: string;
joinedAt: number;
}
// Drawing element
interface Element {
id: string;
type: string;
x: number;
y: number;
width?: number;
height?: number;
strokeColor: string;
strokeWidth: number;
roughness?: number;
points?: Position[];
text?: string;
// ... other properties
}
// Room state
interface Room {
id: string;
users: Map<string, User>;
elements: Element[];
lastActivity: number;
createdAt: number;
}- CanvasBoard: Main drawing canvas with all rendering logic
- Toolbar: Tool selection and drawing options
- CollabRoom: Collaboration room management
- DrawingContext: State management for drawing operations
- CollabContext: Real-time collaboration state
-
New Drawing Tool:
- Add tool to
TOOLBAR_ITEMSinconstants/toolbar.ts - Implement tool logic in
CanvasBoard.tsx - Add corresponding event handlers
- Add tool to
-
New Socket Event:
- Define event in backend
socket.event.ts - Add client-side handler in
CollabContext.tsx - Update TypeScript interfaces
- Define event in backend
Backend (.env):
PORT=3001 # Server port
NODE_ENV=development # Environment mode
FE_URL_PROD=https://your-domain.com # Production frontend URL- Vite Config: Frontend build settings in
vite.config.ts - TypeScript: Configurations in
tsconfig.jsonfiles - Tailwind: Styling configuration in
tailwind.config.js
-
Build the application:
npm run build
-
Set production environment variables
-
Start the server:
npm start
-
Build for production:
npm run build
-
Deploy the
distfolder to your hosting service
Create Dockerfile for containerized deployment:
# Backend Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
EXPOSE 3001
CMD ["npm", "start"]- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes
- Commit:
git commit -m 'Add amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request
- Follow TypeScript best practices
- Maintain consistent code formatting
- Write meaningful commit messages
- Test new features thoroughly
- Update documentation as needed
This project is licensed under the ISC License.
- Rough.js for hand-drawn style graphics
- Socket.IO for real-time communication
- Radix UI for accessible components
- Tailwind CSS for styling utilities
- React and TypeScript for the development foundation
For support, questions, or feature requests, please open an issue on GitHub.
Built with โค๏ธ by the Draw.Wine team