An anonymous, real-time collaborative platform to share anything.
Public Canvas is a high-performance, anonymous drawing tool designed for seamless sharing. It features an infinite workspace, multiple public boards, and a premium, minimal aesthetic powered by the Roboto font.
- Infinite Workspace: Pan and zoom across an effectively unlimited drawing area.
- Real-Time Collaboration: See strokes and fills from other users instantly.
- Multiple Public Boards: Create and join different canvases anonymously.
- Snapshot Loading: Boards load their entire history at once for a smooth initial experience.
- Minimal UI: A clean, distraction-free interface with a focus on typography and white space.
- Essential Tools: Pencil, Eraser, Hand (Panning), and a curated Color Palette.
- Responsive Design: Works across different screen sizes and high-DPI displays.
- Backend: Ruby on Rails 8.1
- Real-Time: ActionCable (WebSockets)
- Frontend: Hotwire (Stimulus + Turbo)
- Styling: TailwindCSS
- Database: SQLite3
- Ruby 3.4.8 (managed via
miseorrvm) - Rails 8.1
- SQLite3
-
Clone the repository:
git clone <repository-url> cd s
-
Install dependencies:
bundle install
-
Setup the database:
rails db:migrate rails db:seed
-
Start the development server:
./bin/dev
The application will be available at
http://localhost:3000.
If you prefer to use Docker, you can spin up the entire environment with a single command:
-
Ensure you have a Master Key: Create
config/master.keyor set theRAILS_MASTER_KEYenvironment variable. -
Build and Start:
docker-compose up --build
The app will be available at
http://localhost:3000. The SQLite database is persisted in the./storagedirectory on your host.
The real-time magic of Public Canvas is powered by the integration of ActionCable and Stimulus.
When a user joins a board, they subscribe to a specific WhiteboardChannel identified by the board's unique slug. This creates a persistent WebSocket connection between the client and the server.
- Broadcasting: When a user draws a stroke or performs an action, the data is sent to the server, persisted in the database, and then broadcasted to all other users subscribed to that specific board's channel.
- Snapshots: To prevent "ghost drawing" (where lines appear one by one on load), the server sends a single
snapshotmessage containing the entire board history immediately upon subscription.
The whiteboard_controller.js manages the local canvas state and coordinates with ActionCable.
- Local Rendering: Strokes are rendered locally for the drawing user immediately for zero-latency feedback.
- Remote Rendering: When the controller receives a
drawevent from the WebSocket, it translates those coordinates into the user's current view (accounting for their specific pan/zoom level) and renders them on the fly. - Coordinate Mapping: The system uses a World Coordinate System. Screen coordinates are mapped to world coordinates before being sent to the server, ensuring that users at different zoom levels or on different screen sizes see the drawings in the same relative positions.
This project is open-source and available under the MIT License.