cd /news/developer-tools/i-replaced-image-ai-for-technical-di… · home topics developer-tools article
[ARTICLE · art-44449] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=↑ positive

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.

read4 min views1 publishedJun 30, 2026

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.

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.

@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.

## 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.

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.

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.

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.

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><body></body>");
const body = d3.select(dom.window.document.body);
const svg = body.append("svg").attr("viewBox", `0 0 ${width} ${height}`);

const simulation = d3.forceSimulation(nodes)
  .force("link", d3.forceLink(links).id(d => d.id).distance(110))
  .force("charge", d3.forceManyBody().strength(-220))
  .force("center", d3.forceCenter(width / 2, height / 2));

simulation.tick(80);

svg.selectAll("line")
  .data(links)
  .join("line")
  .attr("x1", d => d.source.x)
  .attr("y1", d => d.source.y)
  .attr("x2", d => d.target.x)
  .attr("y2", d => d.target.y);

svg.selectAll("circle")
  .data(nodes)
  .join("circle")
  .attr("cx", d => d.x)
  .attr("cy", d => d.y)
  .attr("r", 18);

fs.writeFileSync("network.svg", body.html());
npm i d3 jsdom

When relationship density grows, D3 gives me the control that static diagram tools sometimes hide.

import bpy

bpy.ops.wm.read_factory_settings(use_empty=True)
camera = bpy.data.objects["Camera"]
camera.location = (4, -6, 3)
camera.data.lens = 40
cube = bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))
sphere = bpy.ops.mesh.primitive_uv_sphere_add(radius=0.6, location=(2, 0, 0.6))

bpy.ops.render.render(write_still=True, filepath="infra-overview.png")
blender --background --python render_scene.py

Blender is the last tool I keep for cases where shape and spatial composition are part of the explanation.

I call it the "draw from intent, not from prompt" rule:

If the figure has structure, use text/code and regenerate it from source. Use image-generation AI only for final polish or style-first deliverables.

This removed most of the recurring "I know the idea but cannot get the same output again" pain.

If I had to do one thing now, I would first swap one recurring illustration with Mermaid or matplotlib and leave the rest unchanged until the matrix habit becomes automatic.

I can ship fast when visuals are generated like code.

── more in #developer-tools 4 stories · sorted by recency
── more on @mermaid 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-replaced-image-ai-…] indexed:0 read:4min 2026-06-30 ·