Essays — AI-Generated Blog Diagrams
Overview I used to make diagrams with Mermaid: drop a code block into Markdown and a figure appears. That works fine, and AI is good at Mermaid. But Mermaid only goes so far. For richer figures you need a drawing tool, and hand-drawing is expensive. This post explores how to produce blog diagrams w

Posted on Nov 1 • Originally published at cnblogs.com
I used to make diagrams with Mermaid: drop a code block into Markdown and a figure appears. That works fine, and AI is good at Mermaid.
But Mermaid only goes so far. For richer figures you need a drawing tool, and hand-drawing is expensive.
This post explores how to produce blog diagrams with AI.
Idea. Rough.js is a hand-drawn style canvas library. With a handwritten font, rectangles and lines pick up jitter and look like a sketch.
// x / w for each box is hand-computed box(doc, 30, 60, 150, 130, 'gray', 'Power on', ['kernel + init']); box(doc, 227, 60, 195, 130, 'gray', 'Boot script', ['/etc/init.d/codesyscontrol']); box(doc, 469, 60, 225, 130, 'blue', 'Runtime', ['codesyscontrol.bin']); // two more boxes omitted arrow(doc, 181, 125, 221, 125); Enter fullscreen mode Exit fullscreen mode Result:
Pros. Full control of layout; not limited by a layout engine.
The figures in this post use this method.
Idea. Same drawing path, but coordinates are not hard-coded: measure text width, size the box, center the row.
// content only — no positions or widths flowRow(doc, [ { tone: 'gray', title: 'Power on', sub: ['kernel + init'] }, { tone: 'gray', title: 'Boot script', sub: ['/etc/init.d/codesyscontrol'] }, { tone: 'blue', title: 'Runtime', sub: ['codesyscontrol.bin'] }, { tone: 'orange', title: 'Read boot app dir', sub: ['.app +.crc'] }, { tone: 'green', title: 'Verify & load', sub: ['enter cyclic tasks'] }, ]); Enter fullscreen mode Exit fullscreen mode Result:
Pros. Edit copy without re-placing boxes. Overflow fails loudly instead of relying on eyeballing the PNG.
Idea. D2 is a diagram DSL. Nodes and edges go in text; the layout engine places them; --sketch adds hand-drawn jitter. Export SVG → PNG. Fonts and Chinese line-height are the usual pitfalls.
direction: right power: "Power on\nkernel + init" { shape: rectangle } script: "Boot script\n/etc/init.d/\ncodesyscontrol" { shape: rectangle } rt: "Runtime\ncodesyscontrol.bin" { shape: rectangle } // two more nodes omitted power -> script -> rt -> read -> load Enter fullscreen mode Exit fullscreen mode Result:
Pros. Best auto-layout of the five — a few lines of DSL and the structure is placed for you.
Idea. Boxes as HTML, layout via CSS flex, then headless browser (Playwright) to PNG. Cost: you install a browser.
<div class= "flow" > <div class= "node" style= "border-color:#495057;background:#f1f3f5" > <div class= "t" > Power on </div> <div class= "s" > kernel + init </div> </div> <svg class= "arrow" > … </svg> <div class= "node" > … </div> </div>.flow { display: flex; align-items: center; gap: 6px; } Enter fullscreen mode Exit fullscreen mode Result:
Pros. Web layout powers: wrapping, spacing, radii. Tweak styles in the browser.
Idea. Mermaid’s built-in hand-drawn theme ( look: handDrawn ). Long Chinese labels often break the layout and need tuning.
flowchart LR power["Power on<br/>kernel + init"]:::tgray script["Boot script<br/>/etc/init.d/<br/>codesyscontrol"]:::tgray rt["Runtime<br/>codesyscontrol.bin"]:::tblue power --> script --> rt classDef tgray fill:#f1f3f5,stroke:#495057 classDef tblue fill:#e7f5ff,stroke:#1971c2 Result:
Pros. Lowest friction — no install; a code block in Markdown is enough. AI knows it well.
The five differ mainly in who computes coordinates and how much style you can control. All are code-generated figures.
Figure - Content: full write→figure pipeline, 5 steps - Layout: five boxes in a row, arrows between them - Emphasis: the only human step — human review; width 1200px Enter fullscreen mode Exit fullscreen mode
While writing this section I literally typed the brief like this:
Mermaid would struggle with figures like these. Dragging boxes in an online tool burns your fingers. Calling a large image model burns tokens and often “surprises” you on edits.
With a local pipeline the artifact is a file on disk: fix it by hand (re-render) or say what to change — the next run stays stable.
Treat figure generation as a skill, or fold it into Agents.md — whatever matches how you want the loop to run.
I only just started on this path — better ideas welcome.