I Replaced Image AI for Technical Diagrams with an 8-Tool Code-First Matrix A developer replaced image-generation AI for technical diagrams with an 8-tool code-first matrix, including Mermaid, PlantUML, Markmap, Graphviz, matplotlib, Pillow, D3.js, and Blender. The approach prioritizes deterministic, scriptable outputs over prompt-based generation, reducing editing time and recurring overhead for visuals. I needed faster edits for technical diagrams, and a lower recurring overhead for recurring visuals. I stopped asking for new images for everything. That change started the moment I replaced "generate now, tweak later" with a fixed 8-tool matrix. TL;DR: I moved recurring illustration work into seven scriptable stacks + one 3D stack and kept image-generation AI only as a fallback. When I edited an article recently, I was spending too much time redoing the same visual shape in slightly different versions. The same chart logic should not need prompt guessing each time. I asked myself: If the answer was mostly "text/code + deterministic output," I did not open an image-generation model first. I also kept one practical boundary: this was not an academic tool roundup. This is a log of what I actually used and in what context. The number I now defend is exactly 8 . Instead of inventing synthetic savings, I evaluate every new illustration request against this matrix. | Tool | Best fit | Why I pick it | |---|---|---| | Mermaid | flow, sequence, architecture notes | fastest in markdown-native writing | | PlantUML | UML-heavy docs | strict structure when Mermaid gets too loose | | Markmap | map-style summaries | converts headings directly | | Graphviz | dependency and direction graphs | compact graph semantics | | matplotlib | numeric visualizations | source-of-truth from data tables | | Pillow | labels, badges, annotations | deterministic pixel edits in Python | | D3.js | node/link or hierarchy interactions | data-driven relationship rendering | | Blender | 3D explanatory graphics | stronger structural clarity for complex scenes | This is the exact set I now reach for before any image-generation request. I am including small runnable snippets I can reuse. php flowchart LR A "User" -- B "App" B -- C "API" C -- D "Storage" C -- E "Cache" npm i -D @mermaid-js/mermaid-cli I use this for quick reviews because it is fast to read, fast to version-control, and fast to regenerate. php @startuml actor User participant API participant DB User - API: Request API - DB: Query DB -- API: Result API -- User: Response @enduml java -jar plantuml.jar -tpng architecture.puml When a diagram should model lifecycle, protocol, or strict roles, this is my second branch after Mermaid. Release Plan Week 1 Audit Diagram targets Week 2 Implementation Regression checks Week 3 Publish preparation npm i -D markmap-cli This removes a whole "I have to learn a separate visual DSL" step for internal notes. php digraph G { rankdir=LR; "API" - "Auth"; "API" - "Search"; "Auth" - "DB"; "Search" - "SearchIndex"; } dot -Tsvg graph.dot -o graph.svg I use this when relationship direction is the only thing I need to make obvious. python import matplotlib.pyplot as plt stages = "Flow", "Auth", "Search", "Storage", "Cache" latency = 1.2, 0.7, 2.1, 0.9, 0.4 plt.figure figsize= 7, 3.5 plt.plot stages, latency, marker="o" plt.title "Pipeline Latency by Stage" plt.ylabel "Seconds" plt.tight layout plt.savefig "pipeline-latency.svg" uv add matplotlib For this kind of visual, AI image generation is the wrong tool. Data should be generated from data. python from PIL import Image, ImageDraw, ImageFont canvas = Image.new "RGB", 640, 200 , " 1f2d3d" draw = ImageDraw.Draw canvas draw.rectangle 20, 40, 620, 160 , outline=" f4d03f", width=3 draw.text 40, 80 , "Deployment Checklist", fill=" ffffff" canvas.save "badge-note.png" uv add Pillow I use this for simple, repeatable badges and annotations where consistency matters more than illustration style. python import { JSDOM } from "jsdom"; import as d3 from "d3"; import fs from "node:fs"; const width = 540; const height = 360; const nodes = {id: "A"}, {id: "B"}, {id: "C"} ; const links = {source: "A", target: "B"}, {source: "B", target: "C"} ; const dom = new JSDOM "< doctype html