A text-to-diagram engine designed from day one with AI agents as the primary author, not humans. Compact DSL, deterministic SVG output, repairable errors, and a public playground that runs entirely client-side.
At a glance
- First-shot LLM render success: 94% on a held-out prompt set of architecture / sequence / state diagrams
- Median tokens per diagram: 180 — roughly 2–3× more compact than Mermaid for the same shape
- Playground p50 render: 120 ms (parse → layout → SVG → DOM), client-side only
- Deterministic layout — same input produces identical output byte-for-byte; no floating-point drift, no theme override
- One-shot repairable errors — every validator message names the offending token, the expected shape, and includes a working example
- 37 layout rules (R1–R37) across 11 build phases — the hard problem wasn’t parsing, it was producing good auto-layout on the first try
- Custom SVG icon support — drop an inline
<svg>block and reference it as a node shape, no asset pipeline required - 4-section docs — syntax / examples / layout rules / API — written in the order an LLM would consume them
- Single render path — text → AST → layout → SVG; no plugins, no dialects, no server-side rendering
- Zero backend — playground is a static site; parser and renderer run in the browser
Stack
TypeScript (parser + layout + SVG renderer) · Astro (playground + docs site) · Cloudflare Pages (static deploy) · Cloudflare Tunnel (preview deploys on custom subdomain) · custom DSL grammar, hand-written recursive-descent parser · no runtime dependencies in the rendered output
Documentation
| Doc | Read this for |
|---|---|
| PRD | What & why — JTBD, design constraints, scope, success metrics, what we cut |
| Architecture | Render pipeline, parser/layout/renderer split, error model, deploy topology |
| Implementation | DSL grammar, layout rule catalog, token budgeting, perf numbers, repro steps |
| Notes | Chronological decision log across the 11 build phases, gotchas, hours |
Quickstart
Use it inline from a Claude conversation:
“Render the following Diagram-Engine source:”
web -> api -> postgres api -> cache
Open the public playground, paste, see SVG. No login, no install.
Embed in your own page (M2, deferred):
<script type="module" src="https://diagram-engine.example/embed.js"></script>
<diagram-engine>
web -> api -> postgres
api -> cache
</diagram-engine>
Project status
| Phase | Milestone |
|---|---|
| P1 | Grammar lock + recursive-descent parser + AST shape |
| P2 | Layout engine v0 — left-to-right flow only |
| P3 | SVG renderer + 12 base shapes |
| P4 | Validator + error catalog (named-token errors) |
| P5 | Sequence diagrams (lifelines, async messages) |
| P6 | State machines + self-loops |
| P7 | Auto-clustering (R7) + lane inheritance (R12) |
| P8 | Edge routing + label-overlap avoidance (R19) |
| P9 | Visual style rules R31–R37 (corner radius, stroke, padding, icon spacing) |
| P10 | Custom inline SVG icon support |
| P11 | Public playground site + 4-section docs + CF Pages deploy |
Total build time: 11 phases over ~6 weeks part-time. M2 work (npm publish, embed.js, inline-in-chat plugin) is deferred until there is a real downstream consumer asking for it.
Why this exists
Mermaid, PlantUML, Graphviz, and D2 are all human-first DSLs. They’re technically usable by LLMs, but their failure modes are LLM-hostile: whitespace-sensitive syntax, ambiguous error messages, multiple dialects for similar shapes, layout that drifts across versions. When an LLM emits invalid syntax, the human-friendly error message rarely helps it iterate.
Diagram-Engine flips the constraint: the LLM is the primary author. The syntax is short, the errors are mechanical, the layout is deterministic, and the validator is designed to be read by another model and acted on in one shot. The full PM rationale is in the blog post.