{"slug": "i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix", "title": "I Replaced Image AI for Technical Diagrams with an 8-Tool Code-First Matrix", "summary": "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.", "body_md": "I needed faster edits for technical diagrams, and a lower recurring overhead for recurring visuals.\n\nI stopped asking for new images for everything.\n\nThat change started the moment I replaced \"generate now, tweak later\" with a fixed 8-tool matrix.\n\n**TL;DR:**\n\nI moved recurring illustration work into seven scriptable stacks + one 3D stack and kept image-generation AI only as a fallback.\n\nWhen I edited an article recently, I was spending too much time redoing the same visual shape in slightly different versions.\n\nThe same chart logic should not need prompt guessing each time.\n\nI asked myself:\n\nIf the answer was mostly \"text/code + deterministic output,\" I did not open an image-generation model first.\n\nI also kept one practical boundary: this was not an academic tool roundup.\n\nThis is a log of what I actually used and in what context.\n\nThe number I now defend is exactly **8**.\n\nInstead of inventing synthetic savings, I evaluate every new illustration request against this matrix.\n\n| Tool | Best fit | Why I pick it |\n|---|---|---|\n| Mermaid | flow, sequence, architecture notes | fastest in markdown-native writing |\n| PlantUML | UML-heavy docs | strict structure when Mermaid gets too loose |\n| Markmap | map-style summaries | converts headings directly |\n| Graphviz | dependency and direction graphs | compact graph semantics |\n| matplotlib | numeric visualizations | source-of-truth from data tables |\n| Pillow | labels, badges, annotations | deterministic pixel edits in Python |\n| D3.js | node/link or hierarchy interactions | data-driven relationship rendering |\n| Blender | 3D explanatory graphics | stronger structural clarity for complex scenes |\n\nThis is the exact set I now reach for before any image-generation request.\n\nI am including small runnable snippets I can reuse.\n\n``` php\nflowchart LR\n  A[\"User\"] --> B[\"App\"]\n  B --> C[\"API\"]\n  C --> D[\"Storage\"]\n  C --> E[\"Cache\"]\nnpm i -D @mermaid-js/mermaid-cli\n```\n\nI use this for quick reviews because it is fast to read, fast to version-control, and fast to regenerate.\n\n``` php\n@startuml\nactor User\nparticipant API\nparticipant DB\nUser -> API: Request\nAPI -> DB: Query\nDB --> API: Result\nAPI --> User: Response\n@enduml\njava -jar plantuml.jar -tpng architecture.puml\n```\n\nWhen a diagram should model lifecycle, protocol, or strict roles, this is my second branch after Mermaid.\n\n```\n# Release Plan\n## Week 1\n### Audit\n### Diagram targets\n## Week 2\n### Implementation\n### Regression checks\n## Week 3\n### Publish preparation\nnpm i -D markmap-cli\n```\n\nThis removes a whole \"I have to learn a separate visual DSL\" step for internal notes.\n\n``` php\ndigraph G {\n  rankdir=LR;\n  \"API\" -> \"Auth\";\n  \"API\" -> \"Search\";\n  \"Auth\" -> \"DB\";\n  \"Search\" -> \"SearchIndex\";\n}\ndot -Tsvg graph.dot -o graph.svg\n```\n\nI use this when relationship direction is the only thing I need to make obvious.\n\n``` python\nimport matplotlib.pyplot as plt\n\nstages = [\"Flow\", \"Auth\", \"Search\", \"Storage\", \"Cache\"]\nlatency = [1.2, 0.7, 2.1, 0.9, 0.4]\n\nplt.figure(figsize=(7, 3.5))\nplt.plot(stages, latency, marker=\"o\")\nplt.title(\"Pipeline Latency by Stage\")\nplt.ylabel(\"Seconds\")\nplt.tight_layout()\nplt.savefig(\"pipeline-latency.svg\")\nuv add matplotlib\n```\n\nFor this kind of visual, AI image generation is the wrong tool.\n\nData should be generated from data.\n\n``` python\nfrom PIL import Image, ImageDraw, ImageFont\n\ncanvas = Image.new(\"RGB\", (640, 200), \"#1f2d3d\")\ndraw = ImageDraw.Draw(canvas)\ndraw.rectangle((20, 40, 620, 160), outline=\"#f4d03f\", width=3)\ndraw.text((40, 80), \"Deployment Checklist\", fill=\"#ffffff\")\ncanvas.save(\"badge-note.png\")\nuv add Pillow\n```\n\nI use this for simple, repeatable badges and annotations where consistency matters more than illustration style.\n\n``` python\nimport { JSDOM } from \"jsdom\";\nimport * as d3 from \"d3\";\nimport fs from \"node:fs\";\n\nconst width = 540;\nconst height = 360;\nconst nodes = [{id: \"A\"}, {id: \"B\"}, {id: \"C\"}];\nconst links = [{source: \"A\", target: \"B\"}, {source: \"B\", target: \"C\"}];\n\nconst dom = new JSDOM(\"<!doctype html><body></body>\");\nconst body = d3.select(dom.window.document.body);\nconst svg = body.append(\"svg\").attr(\"viewBox\", `0 0 ${width} ${height}`);\n\nconst simulation = d3.forceSimulation(nodes)\n  .force(\"link\", d3.forceLink(links).id(d => d.id).distance(110))\n  .force(\"charge\", d3.forceManyBody().strength(-220))\n  .force(\"center\", d3.forceCenter(width / 2, height / 2));\n\nsimulation.tick(80);\n\nsvg.selectAll(\"line\")\n  .data(links)\n  .join(\"line\")\n  .attr(\"x1\", d => d.source.x)\n  .attr(\"y1\", d => d.source.y)\n  .attr(\"x2\", d => d.target.x)\n  .attr(\"y2\", d => d.target.y);\n\nsvg.selectAll(\"circle\")\n  .data(nodes)\n  .join(\"circle\")\n  .attr(\"cx\", d => d.x)\n  .attr(\"cy\", d => d.y)\n  .attr(\"r\", 18);\n\nfs.writeFileSync(\"network.svg\", body.html());\nnpm i d3 jsdom\n```\n\nWhen relationship density grows, D3 gives me the control that static diagram tools sometimes hide.\n\n``` python\nimport bpy\n\nbpy.ops.wm.read_factory_settings(use_empty=True)\ncamera = bpy.data.objects[\"Camera\"]\ncamera.location = (4, -6, 3)\ncamera.data.lens = 40\ncube = bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 1))\nsphere = bpy.ops.mesh.primitive_uv_sphere_add(radius=0.6, location=(2, 0, 0.6))\n\nbpy.ops.render.render(write_still=True, filepath=\"infra-overview.png\")\nblender --background --python render_scene.py\n```\n\nBlender is the last tool I keep for cases where shape and spatial composition are part of the explanation.\n\nI call it the **\"draw from intent, not from prompt\"** rule:\n\nIf the figure has structure, use text/code and regenerate it from source. Use image-generation AI only for final polish or style-first deliverables.\n\nThis removed most of the recurring \"I know the idea but cannot get the same output again\" pain.\n\nIf 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.\n\n*I can ship fast when visuals are generated like code.*", "url": "https://wpnews.pro/news/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix", "canonical_source": "https://dev.to/nomurasan/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix-3f9n", "published_at": "2026-06-30 06:45:34+00:00", "updated_at": "2026-06-30 06:48:42.019603+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "generative-ai"], "entities": ["Mermaid", "PlantUML", "Markmap", "Graphviz", "matplotlib", "Pillow", "D3.js", "Blender"], "alternates": {"html": "https://wpnews.pro/news/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix", "markdown": "https://wpnews.pro/news/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix.md", "text": "https://wpnews.pro/news/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix.txt", "jsonld": "https://wpnews.pro/news/i-replaced-image-ai-for-technical-diagrams-with-an-8-tool-code-first-matrix.jsonld"}}