Quickdraw
The MIT-licensed infinite-canvas whiteboard SDK. Drop a complete, polished drawing surface into your React, React Native, or plain-JS app — free for any use, including commercial products, forever. An open-source alternative to tldraw with no license fee.
Website · Try the app · npm · Docs · Contributing · Changelog
The hosted app at app.tryquickdraw.com — the same board createQuickdraw() drops into your page.
Quickdraw exists because embedding a whiteboard shouldn't cost thousands of
dollars a year. Quickdraw is MIT: no license key, no fees, no strings. A small
"Made with Quickdraw" badge sits in the board's corner by default; keeping it
helps people find the project, and turning it off is free, legal, and one line
— watermark: false, no license key, no signup, no phone-home. We just
appreciate the credit.
What you get
A simple, joyful drawing experience:
- Pressure ink — a freehand pen whose width breathes with stylus pressure,
- Highlighter that soaks into the paper (and glows on dark boards)
- Shapes — rectangle, ellipse, triangle, diamond, hexagon, star, cloud — with a
- Arrows with draggable bend, lines, text, sticky notes
- Images — paste, drag-drop, or pick; auto-downscaled and stored in-document
- Laser pointer for presenting (ephemeral, never saved)
- Selection — click, shift-click, marquee; move, resize, rotate, duplicate,
- Infinite canvas — pan, wheel zoom, two-finger pinch, zoom-to-fit
- Palm rejection — once a stylus is seen, fingers steer the camera and the
- Undo/redo — one entry per gesture, however many events it took
- Light & dark themes, twelve named colors that resolve per theme, and a
- Grid backdrops — plain, ruled lines, notebook rules, dots, crosses
lines; spacing adapts to the zoom
and fades in rather than popping
- PNG export — whole board or selection, on paper or transparent
- A responsive floating toolbar that sheds tools gracefully as the frame
- Real-time sync built into the data model — every change emits a
Zero runtime dependencies. The core is plain ESM that runs in any modern browser without a build step.
Packages
| Package | For | |
| --- | --- | --- |
| @quickdrawjs/core | Any web page or framework | framework-free engine + toolbar |
| @quickdrawjs/react | React apps | component + hooks |
| @quickdrawjs/react-native | React Native / Expo apps | WebView component + typed bridge |
Quick start — React
npm install @quickdrawjs/react
import { Quickdraw } from '@quickdrawjs/react'
import '@quickdrawjs/core/quickdraw.css'
export default function App() {
return (
<div style={{ position: 'fixed', inset: 0 }}>
<Quickdraw theme="light" grid="lines" watermark={false} />
{/* the "Made with Quickdraw" badge is on by default;
watermark={false} removes it — free, no strings */}
</div>
)
}
Persistence, imperative control, custom chrome:
const ref = useRef(null)
<Quickdraw
ref={ref}
snapshot={saved} // load a serialized document
autoFit // fit content on mount/resize
onChange={(diff, source, editor) => // every document change
save(editor.store.getSnapshot())}
onSave={(blob) => upload(blob)} // intercept toolbar PNG export
/>
ref.current.editor.setTool('draw')
ref.current.editor.store.undo()
Quick start — plain JS
npm install @quickdrawjs/core
import { createQuickdraw } from '@quickdrawjs/core'
import '@quickdrawjs/core/quickdraw.css'
const board = createQuickdraw({ container: document.getElementById('board') })
board.editor.store.listen((diff) => console.log('changed', diff))
Quick start — React Native
npm install @quickdrawjs/react-native react-native-webview
import { Quickdraw } from '@quickdrawjs/react-native'
<Quickdraw
ref={board}
theme="dark"
onChange={(diff) => sync(diff)}
style={{ flex: 1 }}
/>
// const snapshot = await board.current.getSnapshot()
// const png = await board.current.exportPng({ scale: 2 })
The engine ships inside the package as a single self-contained HTML string — no network, works offline, Apple Pencil pressure and palm rejection included.
The data model
The document is a flat map of immutable records. Every mutation happens in a transaction and emits a diff:
{ added: { [id]: record }, removed: { [id]: record }, updated: { [id]: [from, to] } }
That one shape powers everything:
- Persistence —
store.getSnapshot()/store.loadSnapshot(snap)are
- Sync — ship user diffs to peers,
store.applyDiff(diff, 'remote')on
- History — undo entries are diffs, composed per gesture;
invertDiffand
composeDiff are exported
- Audit / recording — log the diff stream and you can replay a drawing
// a complete sync client
store.listen((diff) => socket.send(JSON.stringify(diff)), { source: 'user' })
socket.onmessage = (e) => store.applyDiff(JSON.parse(e.data), 'remote')
Keyboard shortcuts
| | |
| --- | --- |
| V / 1 | Select |
| H | Hand (or hold Space) |
| D / P / B | Draw |
| I | Highlight |
| E | Eraser |
| K | Laser |
| A / L | Arrow / Line |
| G, R, O | Shape / rectangle / ellipse |
| T / N | Text / sticky note |
| ⌘Z / ⇧⌘Z | Undo / redo |
| ⌘A ⌘C ⌘X ⌘V ⌘D | Select all, copy, cut, paste, duplicate |
| ] / | Bring to front / send to back |
| Arrows (+Shift) | Nudge selection |
| ⇧1 / ⇧0 | Zoom to fit / reset zoom |
| ⌘+ / ⌘− | Zoom in / out |
| ⌫ / ⇧⌘⌫ | Delete selection / clear the board (undoable) |
| Enter / Esc | Edit text / done |
| ? | Show this list on the board |
Repository
packages/core @quickdrawjs/core — the engine (plain ESM, zero deps)
packages/react @quickdrawjs/react
packages/react-native @quickdrawjs/react-native
examples/vanilla no-build-step example (open via any static server)
examples/react-demo vite playground (npm run dev)
Development:
npm install # workspace install
npm test # vitest — engine, React bindings, RN bridge
npm run dev # react demo at localhost:5173
npm run build # bundle the RN WebView page
npm run typecheck # validate the published type declarations
Roadmap — and what's honestly missing today
Quickdraw is young. What it doesn't have yet: a first-party multiplayer server (the diff-based store is sync-ready — you bring the transport), layers, frames, or rich text. The full roadmap lives in [issue #1 — comment there if the missing feature that sent you back to a paid SDK is on it (or isn't).
Made with Quickdraw
Projects and products built on Quickdraw. Shipped something? Add it here — edit this table and open a PR (one row, alphabetical, ≤ 15-word description; see the showcase guidelines).
| Project | Description | | --- | --- | | tryquickdraw.com/app | The official free whiteboard app — no account, autosaves locally. | | _Your project here_ | Add yours → |
Sponsors
Quickdraw is MIT-licensed with no paid tier — sponsors are what keep it that way. Sponsors get their logo on the website and here:
tldraw |
Star history
Quickdraw is free forever — no license fees, no upsell. If it saves you one, a star is how other developers find it.
Regenerated every night by a scheduled workflow — same data as the chart on the website.
Contributing
Quickdraw is open to contributions from everyone — bug reports, features,
docs, examples. Start with CONTRIBUTING.md, browse
good first issue,
or open a discussion
if you're not sure where a change belongs. We follow the
Contributor Covenant.
License
MIT. Use it, ship it, sell what you build with it.