4.4 KiB
How to draw a box diagram (architecture, components, data flow) that byre's app renders in the transcript, with zoom and highlighting.
Box diagrams
A fenced block with the language diagram draws boxes in rows with arrows between them. The app lays it out itself, so you never place coordinates. Clicking it opens a full-size view: pinch or scroll to zoom and pan; clicking a box highlights it, its arrows and its neighbors; each highlight line becomes a button there. It is the only diagram format byre draws; a ```mermaid block shows as plain code.
row
app "Byre.app" "REST + SSE · WebSockets"
row
server "internal/server" "REST · SSE · WebSockets" blue
aside store "internal/store" "byre.db, SQLite WAL" green
row
manager "agents.Manager" amber
coord "coordinator" "level-triggered"
live "live sessions" "turn end: commit, snapshot"
app -> server
server -> manager "start · message"
manager -> store "writes"
store ..> server "events → SSE"
store ..> coord "poke"
highlight "Event loop" store server coord
rowstarts a row; rows stack top to bottom. The boxes indented under it sit side by side, stretched to a common width.- A box is
id "Title" "detail line" ..., then optionally a color:blue,green,amber,redorplain(the default). The id is letters, digits,_and-, unique in the diagram. Without a title the id is shown. - A box indented under another box is its child; children sit side by side inside their parent, and nest to any depth.
asidebefore a top-level box puts it in a column to the right of the rows, level with its row. Use it for shared state (a database, git) that many rows touch.a -> b "label"draws a solid arrow anda ..> b "label"a dashed one; the label is optional. Arrows route around boxes, and may end on a child or a parent.highlight "Name" id id ...names a set of boxes to light up together, with the arrows between them.- Lines starting with
#are comments. A mistake shows the source with the reason it wasn't drawn.
Nested diagrams
When a box hides a whole diagram of its own, give it an inside section instead of children. A top-level line inside <id> starts that box's diagram; the rows, arrows and highlights after it belong to it, up to the next inside. The box gets a mark, and in the full-size view selecting it shows an Open button; a breadcrumb leads back up.
row
app "Byre.app"
row
server "internal/server" blue
aside store "internal/store" green
row
manager "agents.Manager" amber
app -> server
server -> manager "start · message"
store ..> coord "poke"
workers -> store "snapshots"
inside manager
row
coord "coordinator" "level-triggered"
live "live sessions"
row
workers "workers" "push · snapshot"
coord -> workers "start"
live -> workers "turn end"
- Ids are unique across the whole block, so an arrow or highlight anywhere can name a box at any level. Write each arrow once, between the boxes it really joins.
- Each level draws an arrow at the deepest boxes it can show: at the top,
store ..> coordends onmanager; insidemanager,storeshows as a dashed ghost outside the frame, on the side where it sits above, and the arrow crosses the frame tocoord. Clicking a ghost goes back up to it. Arrows that end up with the same ends merge into one. - An
insidecan name a box from anotherinside, to any depth. - A box can have both indented children and an
inside: the children show inline as a preview, and when it's opened they form its diagram's first row, above theinsiderows.
Keep each box to a title and one or two short detail lines, and draw only the arrows the reader needs; a picture with every dependency in it reads worse than prose. When a level grows past that, move a cluster into an inside.
Check a diagram before you send it: render_diagram takes the block's body and returns a PNG of what the app draws, every level stacked under its breadcrumb, or the reason it can't. Look for crossing or overlapping arrows and labels sitting on top of each other, and adjust the rows, aside or arrows until it reads cleanly.
To hand a diagram over as a file, export_diagram writes it as one self-contained HTML page with the app's exact layout and its full-size view's interactivity (click to highlight, highlight buttons, opening nested diagrams, zoom and pan, light and dark mode); show it with show_page. The full-size view in the app has the same export as its Export HTML button.