A real-time collaborative whiteboard application built with FastAPI, Vue.js, and Valkey. Draw, collaborate, and share ideas in real-time with multiple users.
- Real-time collaborative drawing
- Multiple users can draw simultaneously
- WebSocket-based synchronization
- Persistent storage with Valkey
- Responsive web interface
Choose one of the following methods to run the application:
- Docker (v20.10+)
- Docker Compose (v2.0+)
This is the easiest way to get started. Docker will handle all dependencies and setup automatically.
-
Clone the repository
git clone <repository-url> cd demo
-
Start the application
docker-compose up -d
Or use the shortcut:
make run
This will start:
- Valkey server on port 6379
- Whiteboard backend on port 8000
-
Access the application
Open your browser and navigate to:
http://localhost:8000 -
View logs (optional)
docker-compose logs -f whiteboard-backend
-
Stop the application
docker-compose down
To remove volumes as well:
docker-compose down -v
For local development without Docker, use uv for faster dependency installation.
-
Clone the repository
git clone <repository-url> cd demo
-
Install uv (if not already installed)
# On macOS and Linux curl -LsSf https://astral.sh/uv/install.sh | sh # On Windows powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
-
Install Valkey
On macOS:
brew install valkey brew services start valkey
On Ubuntu/Debian:
sudo apt-get install valkey-server sudo systemctl start valkey-server
On Windows:
- Use Valkey Docker image [https://valkey.io/download/]
-
Create a virtual environment and install dependencies
uv venv source .venv/bin/activate # On Windows: .venv\Scripts\activate uv pip install -r requirements.txt
-
Configure environment variables (optional)
Copy
.env.exampleto.envin the root directory:cp .env.example .env
Then adjust values if needed:
VALKEY_HOST=localhost VALKEY_PORT=6379 VALKEY_DB=0 MAX_STROKES_PER_ROOM=10000 ADMIN_INSIGHTS_TOKEN=change-me
-
Run the application
cd backend uvicorn main:app --host 0.0.0.0 --port 8000 --reload -
Access the application
Open your browser and navigate to:
http://localhost:8000
demo/
├── backend/
│ ├── __init__.py
│ ├── main.py # FastAPI application entry point
│ ├── api.py # API routes and WebSocket handlers
│ ├── database.py # Valkey connection and operations
│ ├── models.py # Data models
│ └── connections.py # WebSocket connection management
├── frontend/
│ ├── index.html # Main HTML file
│ └── assets/ # Static assets (CSS, JS)
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Docker image configuration
├── requirements.txt # Python dependencies
└── README.md # This file
When running with Docker, the application automatically reloads when you make changes to the code (hot reload enabled).
For local development with uv, the --reload flag enables hot reloading.
GET /- Serve the frontend applicationGET /health- Basic healthcheck endpointGET /assets/*- Serve static assetsPOST /api/feedback- Capture product feedback from usersPOST /api/telemetry- Capture product funnel eventsGET /api/admin/insights- Token-protected 24h aggregate of telemetry + feedback
WS /ws/{room_id}- Real-time collaboration WebSocket connection for a room
- WebSocket messages use
protocol_version=1 - New clients bootstrap with recent history (up to 1500 strokes) for faster loads
stroke_countreturns total room strokes, whilehistorymay be truncated for performance- Stroke streams are capped using
MAX_STROKES_PER_ROOMto keep memory bounded
- Set
ADMIN_INSIGHTS_TOKENin.env - Send it as header
x-admin-tokenwhen callingGET /api/admin/insights - Response includes last 24h event counts, feedback rating mix, negative feedback rate, active unique rooms, and recent feedback samples
- Optional UI dashboard: open
http://localhost:8000/admin/insights, enter the token, and load metrics
- Open a specific room by URL query param:
http://localhost:8000/?room=my-team-room - Use the Copy Share Link button in the toolbar to invite collaborators to the same room
- Room IDs support letters, numbers,
_, and-(max 64 chars)
- A feedback widget is shown in the app so users can send thumbs up/down and optional notes
- Feedback is stored in Valkey stream key
whiteboard:feedback
- Backend: FastAPI, Python 3.11
- Database: Valkey
- Frontend: Vue.js, HTML5 Canvas
- Real-time: WebSocket (Socket.IO)
- Containerization: Docker, Docker Compose
Run a quick backend/API contract check:
export ADMIN_INSIGHTS_TOKEN=change-me
python scripts/smoke_test.pyOptional base URL override:
SMOKE_BASE_URL=http://localhost:8000 python scripts/smoke_test.pyShortcut:
ADMIN_INSIGHTS_TOKEN=change-me make smokeBenchmark shortcut:
make benchmark
CLIENTS=50 DURATION=30 make benchmarkPort already in use:
# Check what's using the port
netstat -ano | findstr :8000 # Windows
lsof -i :8000 # macOS/Linux
# Change the port in docker-compose.yml
ports:
- "8001:8000" # Use 8001 insteadContainer won't start:
# Check logs
docker-compose logs whiteboard-backend
# Rebuild containers
docker-compose up --buildModule not found:
# Reinstall dependencies
uv pip install -r requirements.txtPort 8000 already in use:
# Run on a different port
uvicorn main:app --host 0.0.0.0 --port 8001- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source and available under the MIT License.
For issues, questions, or contributions, please open an issue on the repository.
Talk planning content lives in docs/talk-idea.md.