feat(design): Mermaid diagrams open as whiteboards - #156
Merged
Conversation
filipeforattini
force-pushed
the
feat/design-whiteboard
branch
from
September 6, 2026 06:50
dc65b33 to
156c521
Compare
Every rendered diagram gets an Excalidraw whiteboard beside it, and a Fullscreen action that opens the same one over the page: converted from the Mermaid source, drawn on and rearranged, autosaved beside the review's own state, and queued as one ordinary note carrying a summary of what changed plus the edited scene and a PNG on disk. The agent edits the Mermaid source in response; nothing is converted back. A scene saved for an older diagram is never merged silently. The frames run sandboxed with no origin and no server access; the review page does every read and write, only for a frame that proved a channel token minted for this prototype and its descent from the prototype frame. The bundle is not in the binary: a release ships it as a tarball the server fetches on first use; a checkout builds it with bun run build:whiteboard. lavish-axi's whiteboard core and frame are vendored (MIT); the sources, store, channel and routes are ours. Claude-Session: https://claude.ai/code/session_013JrKXL4pdgTu2EtCjgiYyq
filipeforattini
force-pushed
the
feat/design-whiteboard
branch
from
September 6, 2026 06:52
156c521 to
4303d80
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tranche D of the lavish-axi parity plan, the last one: the whiteboard.
In the prototype — the SDK joins every rendered diagram in a
.mermaid(ordata-redcode-mermaid/data-lavish-mermaid) container with a sibling frame (sandbox="allow-scripts allow-popups",data-redcode-ui) hosting the Excalidraw whiteboard; the container is hidden, not replaced, so a theme re-render stays harmless and the file keeps its Mermaid. Diagram identity is the container's index in document order. The prototype's policy gainsframe-src <origin>/design/:id/whiteboardonly while the bundle is on the machine.The frame — lavish's
whiteboard-frame.js+ css, vendored with the redcode prefix on its messages, token global and data attributes: boots locked in view mode behind a click-catcher, converts the source (label line-break repair, duplicate-id fallback, fonts loaded before the second materialisation), restores a saved scene when the source hash matches, offers Re-convert / Keep editing when the hash moved and the scene has real edits (style-only and sub-2px jitter do not count), autosaves 800 ms after a change, confirms external links in a dialog (http/https/mailto only), and on Queue feedback exports a PNG and posts the summary. Fullscreen asks the shell to reopen the diagram in an overlay; the inline frame parks onabout:blankmeanwhile so two editors never autosave one scene.The shell — hosts the overlay frame (same sandbox), and is the only party with server access: it authenticates each frame's channel token, requires descent (
source.parent === frame.contentWindow) for inline frames, fetches the Mermaid sources and the saved scene, mediates saves (chained per diagram), flushes open whiteboards for up to 1.5 s before a reload, tells an open overlay when its source changed underneath, and queues the note astag: "whiteboard"with the summary, note, and the scene/PNG paths, replacing an unsent note for the same diagram (queueKey).The server (
design/whiteboard.ts) — HMAC channel tokens bound to one prototype, 5-minute TTL,timingSafeEqual; Mermaid sources extracted fromindex.htmlwith htmlparser2 in document order (comments, raw text,templateandnoscriptignored,<br>kept as a label break), hashed; scenes and the agent's.excalidraw/.pngunder<root>/.review/whiteboards/, written atomically through a per-diagram queue; the frame page with its own CSP; bundle assets resolved by real path and served withaccess-control-allow-origin: *, an ETag andno-cache. Routes:GET /whiteboard(frame),GET /mermaid-sources,GET|PUT /whiteboard/:index(20 MB),POST /whiteboard-channel,POST /whiteboard/:index/feedback-files,GET /design/vendor/whiteboard/*.feedback.tsaccepts theexcalidraw-scenetarget (lavish's normaliser, bounded), rendered aswhiteboard: diagram N.The bundle —
bun run build:whiteboard(Bun.build: Excalidraw 0.18.1, mermaid-to-excalidraw 2.2.2 with mermaid pinned at 11.12.1, React) producesdist/whiteboard/(7 MB script, css with fonts inlined, Excalidraw's font families). Not in the binary:script/build.tsaddsredcode-whiteboard-<version>.tar.gzto the release assets, and the server fetches it intoGlobal.Path.data/designs/whiteboard/<version>/the first time a review asks (REDCODE_DISABLE_WHITEBOARD_DOWNLOAD=1never fetches;REDCODE_WHITEBOARD_DIRpoints at a build; a checkout uses its owndist/whiteboard). Until it is there, the shell and SDK are toldwhiteboard: falseand diagrams stay plain.Prompt — the mode explains the
whiteboard: diagram Nnote, the summary and the files, and that the answer is a Mermaid edit, never the scene written back.Tests: lavish's 31 whiteboard-core tests vendored;
whiteboard.test.ts(channel, sources, scenes, frame, assets, download refusal for a source build); route scenarios (sources and scene round trip, files, foreign origin refused, frame token bound to one prototype, bundle CORS/304/traversal, CSP and SDK config flip when the bundle is present); shell, SDK and feedback tests. 427 design tests and 1514 across session/tool/server/cli pass; core, app and tui typecheck.Dependencies: none added to the workspace.
script/whiteboard-bundle.tsinstalls its exact pins (Excalidraw 0.18.1, mermaid-to-excalidraw 2.2.2, mermaid 11.12.1, React 18.2.0) in its own project undernode_modules/.cache/redcode-whiteboard-build/and builds there, so the terminal UI's React and the lockfile are untouched.https://claude.ai/code/session_013JrKXL4pdgTu2EtCjgiYyq
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.