GitHub - kwy404/doodleduo: Draw together on one endless whiteboard, peer to peer in the browser, with chat and calls. · GitHub
Skip to content
kwy404Public

About

Draw together on one endless whiteboard, peer to peer in the browser, with chat and calls.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

doodleduo: Mabel and Otto draw glowing chalk lines on a night slate while friends join with live cursors

doodleduo

An infinite whiteboard you draw on together with friends at the same time, peer to peer in the browser.
Website · Open the app · Leia em português

Press Invite friends and send six words, a QR code or a link (all three carry the same words), then draw on the same endless slate while you talk: chat with replies and reactions, a voice call with strong noise suppression, camera bubbles that float next to each cursor, and screen sharing. Up to 5 people, no account, and no server of ours in the middle. Boards are saved in your browser.

Mabel and Otto draw on the same slate at once, each with a live cursor

Smooth, pressure aware pen
Plus a highlighter, an eraser, shapes, arrows and text.

Sticky notes and pictures
Paste or drop a picture: it is compressed and sent to everyone.

Live cursors
Each person has a color and a name on every screen.

Select, move, resize, duplicate
Undo and redo per person.

Edits that merge
A CRDT keeps every copy of the board identical.

Boards you keep
Saved in IndexedDB. Export PNG, SVG or a board file.

Pan and pinch zoom
Two fingers on phones, big touch targets.

Installable
A PWA that opens offline.

English and Portuguese
Picked from your browser, switchable in settings.

Chat
Replies and reactions, saved with the board.

Voice with noise suppression
Browser filters plus our own DSP worklet, with a mic test.

Camera bubbles and screens
Small cameras float by each cursor; share a screen.

A right click, a long press or the Menu key (Shift+F10 too) opens one keyboard friendly menu: copy, paste, duplicate, delete, front and back, color, group and lock on shapes and strokes; paste, a sticky note, text and zoom to fit on the empty board; reply and react on chat messages; mute for me and go to their cursor on the people in the call.

Talk while you draw

Mabel and Otto talk while they draw: camera bubbles by each cursor, a chat with a reply and a reaction, and a call with noise suppression

Everyone on the board can join the call. Mute, turn the camera off, share a screen, and pick the microphone, camera and speaker in the settings (the change applies during the call). Strong noise suppression runs the browser filters plus our own DSP AudioWorklet; the mic test lets you hear yourself after it.

How pairing works

Six words, a QR code or an invite link connect two people, and six more words confirm it
  1. The inviter gets six words (66 random bits from the BIP39 English list), a QR code and an invite link with a Copy button. All three carry the same words and work once, for ten minutes. The link looks like .../app/#join=word-word-word-word-word-word: the words sit in the hash, which the browser never sends to any server. Opening it drops the friend straight into the join, and the app clears the words from the address bar. Pasting the whole phrase (or the link) into any word box spreads it one word per box.
  2. Both devices derive a topic and an AES-GCM key from the words (PBKDF2, then HKDF) and meet on several public MQTT brokers at once. The brokers only see a random topic and ciphertext. The WebRTC offer and answer travel sealed with that key.
  3. Once connected, the friend's screen shows six confirmation words made from the DTLS fingerprints of the connection. The inviter types them back. If someone sat in the middle, the words would not match, and three wrong tries close the connection.

Anyone already on a board can invite the next person. The mesh introduces newcomers to everyone, and forwards through a relay member when two people cannot reach each other directly.

Why everyone sees the same board

Someone who joins late receives the whole board from the people already drawing

Each element is a map of fields, and each field is a last writer wins register stamped with a Lamport time and the replica id. Deleting is a field too, so undo is just a newer write. Pen strokes are ordered point lists that only their author appends to, so chunks can arrive late or twice and still line up. A late joiner merges the full state in small parts and asks for the pictures it lacks; pictures are named by their SHA-256 and checked on arrival. The unit tests run thousands of random concurrent edits across three replicas over a lossy, reordering network and require identical results.

Honest limits

  • Drawing together needs at least one person who has the board to keep it open. There is no server that stores boards.
  • Pairing depends on public MQTT brokers that are not ours. If none answers, pairing fails with a clear message.
  • Some networks block direct connections. The app tests at start whether the public STUN servers answer. No TURN server is built in; you can add your own in the settings.
  • Boards live in your browser's storage. Clearing site data deletes them, so export a board file to keep a copy.
  • Pen pressure needs a pen that reports it. With a mouse or a finger, the width follows your speed.
  • The eraser removes whole strokes and shapes. Pictures are scaled to 1600 pixels; animated GIFs keep their first frame.
  • Reloading the page ends the live session. Invite each other again and the boards merge back.
  • Calls are a full mesh: with five people each device sends its voice and camera four times, which needs a decent upload. Screen sharing needs a browser that supports it, so most phones cannot share.

Meet Mabel and Otto

Mabel and Otto, two ducks drawing on a night slate

Mabel is the bold one, chalk up and already drawing. Otto is the calm one, crayon close, happy to watch first. See the character sheet.

Development

npm install
npm test          # unit tests: CRDT convergence, smoothing, board file, pairing, mesh, QR
npm run lint      # ESLint
npm run rules     # house rules: no emoji, no long dashes, no product names
npm run e2e       # two browser profiles join by link, words and QR code, then draw, chat and call
npm run serve     # http://127.0.0.1:8080/doodleduo/

The site is plain static files in docs/ with relative paths, served the same way as GitHub Pages. Chat, calls, the mesh and the noise suppression are adapted from howlden. Shared modules live in src/ and are copied to docs/app/core/ with npm run core. Styles use Monsoon and the interface is declared with Voodoo.js.

License

MIT, made by Alexandre Kohler.

About

Draw together on one endless whiteboard, peer to peer in the browser, with chat and calls.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages