CoDNA Request access
Contents

Docs Decisions

0019 · Diagrams are Mermaid text, drawn by the web UI

Status: Accepted · 2026-10-20.

Context

A knowledge base explains systems, and systems are explained with diagrams: how the parts connect, who calls whom, what state a thing moves through. CoDNA's own architecture was drawn outside CoDNA, because CoDNA could not show it. Pages are markdown and nothing drew a diagram.

A picture of one could have been pasted in as an image (0015), but images do not suit diagrams here. Agents write much of what is in CoDNA, and an agent cannot add an image: page files are uploaded by people, and the MCP tools can look at an image but not make one. An image cannot be read back as what it says, so an agent cannot change one either. A diagram that nobody can edit falls behind the system it describes. SVG, the one image format that is text, is refused because it can carry script.

Decision

A diagram is a fenced code block marked mermaid, and the web UI draws it, as GitHub does. The page stores the text and nothing else (0006: text is never re-serialised). An agent writes and changes a diagram as it does any other text, every change is in the page's history as a diff, and an export holds the block as written. GitHub, Obsidian and most other markdown tools draw it too.

  • Where it is drawn. In reading, in a past version, and in the editor while the cursor is outside the block. With the cursor in it the text shows, with the drawing under it, drawn again as it is written. A block Mermaid cannot read shows its text, with one line on what was wrong.
  • How it looks. In CoDNA's light and dark tokens, read from the page, and drawn again when the theme changes. A diagram wider than the text is shrunk to fit it, whole, and opens over the page as large as the window allows, with zoom and dragging to move around. The text column is kept to its reading measure, beside the table of contents, so a diagram does not widen it.
  • What it costs. Mermaid is pinned to one version and loaded only by a page that has a diagram, as chunks of its own. A page without one loads about 2 KB more than before, and nothing of Mermaid.
  • What it may do. Mermaid draws with securityLevel: 'strict' and no HTML labels, and a diagram cannot change either, or its stylesheet, with an %%{init}%% line. Its SVG is sanitised again with DOMPurify, and its stylesheet keeps only rules scoped to the diagram itself, so no diagram can restyle the page around it. Links a click line makes are drawn but lead nowhere: one would take the reader out of the app, and a page's relative links would not resolve inside a diagram. The web UI's Content-Security-Policy allows inline styles for the stylesheet inside the SVG, and scripts only from the instance (SECURITY.md, "What a page can do in the browser"); files served on their own keep stricter ones (files.md).
  • Elsewhere. An excerpt, a search result and a list row say [Diagram] where a diagram is, never its code. get_document and export return the text, unchanged. The MCP server's instructions tell agents to write diagrams this way.

Consequences

  • Diagrams can be kept up to date by whoever keeps the page up to date, person or agent.
  • Drawing happens in the browser, so the server has nothing to render, store or cache. It also means nothing outside the web UI draws one: an excerpt says [Diagram], and a notification would show the text.
  • The words inside a diagram are not searched, as code is not. What matters belongs in the text around it as well.
  • A diagram is laid out by the reader's browser, with the reader's fonts, so it can differ slightly from one machine to another. Upgrading Mermaid can change layouts too, which is why it is pinned.
  • Mermaid is several megabytes across its chunks. The first page with a diagram waits for it once; after that it is cached like the rest of the app.
  • A large diagram's words are small in the column; it is read in the full view. Drawn first at its own size, scrolling sideways in the column, a wide one showed a third of itself at a time, which was harder to read than the whole of it small and one click from full size.

Alternatives rejected

  • Images. Agents cannot add them or change them, and a picture of a diagram cannot be diffed, searched or reviewed.
  • Drawing on the server. Mermaid lays out with a browser's text measurement. Running it in the Go binary would take a headless browser or a JavaScript engine with a DOM, against 0003, for a picture the reader's browser can draw.
  • Other diagram languages. PlantUML needs a Java server; Graphviz and D2 are less often written by people and agents, and fewer markdown tools draw them. Mermaid is what GitHub and Obsidian draw, and what agents already write.
  • Drawing inside a sandboxed iframe. It would isolate the SVG fully, at the cost of sizing, theming and scrolling an iframe per diagram. Strict mode, sanitising and scoping the stylesheet close what an iframe would.