Canvas

The infinite canvas is a board without edges for planning, mapping and drawing together: sticky notes, shapes, text, images, frames and connectors that follow what they join. Pan and zoom with a mouse, a trackpad, a finger or the keyboard; drag, resize, turn, line things up, type straight onto the board, draw with a pen or a highlighter, vote on ideas, start from a template, undo anything.

It stays fast however big the board grows. Everything is indexed by where it sits and only what is in view is built; zoomed far out, the board is painted instead, so ten thousand items pan and zoom as smoothly as ten.

It is built for multiplayer. The drawing is kept apart from the data: every change comes out as a few lines of JSON for your server, socket or peer connection to pass on, and the other copies apply it and agree, whatever order the changes arrive in. Other people's cursors and selections are drawn for you. There is no server of ours in the loop, and nothing leaves the page unless you send it.

A planning board

A product launch laid out in three frames, with the flow of the work drawn between them. Drag a note, or a frame by its title to carry everything in it. Double-click the board for a new note, or pick a tool on the left. Hover over a note and drag from one of its dots to another item to connect them — or to empty space, for a new note joined to the first. Select something to recolour it, change a shape, restack, lock or vote on it, or turn it by the round handle above it (or with the full stop and comma keys); select several to group them or line them up. The pen draws by hand, the laser points without leaving a mark, and the templates button starts a retrospective, a kanban board, a SWOT analysis, a flowchart or a mind map. Drop a picture from your computer onto the board.

Show everything Snap to grid Lined grid Download SVG Download PNG Start again
Keyboard: Tab moves through the items in reading order and Alt+arrow to the nearest one that way; the arrow keys move what is selected (Shift for a grid step) or pan when nothing is. Enter edits, Esc finishes, Delete removes, Ctrl+Z undoes, Ctrl+D duplicates, ] and [ restack, . and , turn by 15° (Shift for a quarter turn). + and - zoom, Shift+1 shows everything. N, S, T, C and F pick the note, shape, text, connector and frame tools, P, M and E the pen, highlighter and eraser, L the laser; hold Space to pan. Ctrl+G groups, Ctrl+F finds.

One tag, data in and events out. Give the board its items as nodes and edges — plain objects, or JSON in the markup — and read it back with await board.getSnapshot(). Notes, shapes, text, images, frames and connectors are all the same shape of object: an id, a type, a box, and what to write in it.

Two people, one board

Two canvases on this page, joined through a pretend network that delays every message and delivers them out of order. Move, type or delete on either side and watch it reach the other; point at the board and a named cursor follows on the other side, with a coloured outline round what you have selected. Pick the laser (L) and press to point something out. Turn on the slow network to see both copies still end up the same, and let Bob follow Alice to see his view go wherever hers does.

Slow network Bob follows Alice

Wiring it to your own server. Send what bmxCanvasStateChange gives you and hand what arrives to applyRemote(): board.addEventListener('bmxCanvasStateChange', e => socket.send(JSON.stringify(e.detail.ops))) and socket.onmessage = m => board.applyRemote(JSON.parse(m.data)). Every change carries a clock and the id of the copy that made it, and each field keeps the latest; so two people moving the same note see it land in the same place, and one recolouring it while the other types in it keeps both. bmxNodeMove streams a drag while it happens, bmxCursorMove the pointer, and getSyncState() brings someone who joins late up to date.

Open this page in a second tab

This board is shared with every other tab or window of this page in your browser, through nothing but the browser: one attribute, channel. Open the page again beside this one and work on both. Each tab sees the others' changes, cursors, selections and laser, a tab opened later catches up with what is already there, and you can follow another tab's view.

Across machines, a relay is enough. board.joinRoom(transport) takes anything with send(text) and subscribe(listener) — a WebSocket to a relay that passes each message to everyone else in the room is a few lines of server code that knows nothing about boards and keeps nothing. The canvas does the rest: changes, drags, cursors, selections, views, and bringing a late joiner up to date.

Your own HTML on the board

A node of type html shows whatever element of the page carries its slot name — a chart, a form, a video, a component from any framework — and it moves and zooms with the board. Its buttons and fields work as they would anywhere else; drag it by any part that is not a control.

Weekly orders 48 today, up from 12
Rate the launch plan

Ten thousand items

Press the button to fill a board with ten thousand notes and shapes and nearly as many connectors, then take the tour: a zoom from a single note out to the whole board and back, with the frame rate counted as it goes. Close in, the notes in view are real, sharp and editable; far out, the board is painted, and the paint is reused while it pans.

Place ten thousand items Take the tour