Public: anyone can read this; the crew can change it.
Build canvas #2
Check · Review · Land · Live done — Landed and live in production.
canvas is now a real whiteboard: an infinite sheet with freehand ink, rectangles, ellipses, lines, arrows, text and sticky notes, pan and zoom (wheel, pinch, two fingers), live cursors and presence over server-sent events, per-person undo, SVG and PNG export, and boards that are shared by URL with an optional edit password. The starter's notes table is gone; boards and shapes replace it.
shipped production is serving it for issue #1 deploy 89346db
Sign in to join this conversation.
canvas is now a real whiteboard: an infinite sheet with freehand ink, rectangles, ellipses, lines, arrows, text and sticky notes, pan and zoom (wheel, pinch, two fingers), live cursors and presence over server-sent events, per-person undo, SVG and PNG export, and boards that are shared by URL with an optional edit password. The starter's notes table is gone; boards and shapes replace it.
The design worth looking at is
src/shape.ts: one vocabulary imported by both halves, so the boundary validation, the server's SVG and the browser's DOM nodes are the same code and cannot drift — colours are indexes into a palette, so no colour string from the network can ever reach an attribute.src/db.tsgives each board a revision counter and stamps every shape it touches, with deletes as tombstones, soGET /b/<id>/eventscan hand a reconnecting stream exactly what it missed viaLast-Event-ID. Cursors and shape changes travel together in one throttledPOST /b/<id>/sync, and presence is coalesced and flushed at 15 Hz per board so the fan-out stays bounded.src/watch.tsis the one piece of polling: once a second, and only for boards someone is actually watching, it notices a change made in the terminal and streams it on.In the preview: make a board on
/, open it in two windows and draw in one — the stroke grows live in the other, and the cursors carry names. TrySVGandPNGin the bar, then make a board with a password and open it in a private window: the board is readable, the tools are gone, and the banner trades the password for an HttpOnly cookie scoped to that one board. OverFORGE_APP_SSH(printed on the front page), pressnfor a board,ato stick a note on it, and watch it land on the open web page within a second.What I chose not to do: undo is per person and per tab — the browser sends the inverse of what it did, and a reload empties the stack; there is no server-side history, because a shared undo that reverses a colleague's stroke is worse than none. There is no selection rectangle, no resize handles, no z-order controls and no image paste — select moves one shape at a time. The board is rendered twice into the first response (as SVG for the no-JavaScript first paint, as JSON for the client's model), which roughly doubles the HTML for a very busy board; I kept it because a board that is readable before any script runs is worth the bytes.
bun testis 26 tests, all passing, covering validation, escaping, the export, locks, cross-site posts, the stream's catch-up and the terminal bridge.Closes #1