C4 drawio
Generate readable, auto-laid-out C4 / software-architecture diagrams as native, editable draw.io (.drawio) files. Use when the user wants an architecture diagram, C4 model (system context / container / component), service or system diagram rendered in draw.io's visual style but WITHOUT hand-placing boxes — i.e. "draw the architecture as draw.io", "C4 container diagram in draw.io", "a clean/readable .drawio diagram with auto-layout", "nicer draw.io architecture diagram", or combining C4/Structurizr-style auto-layout with the draw.io look. Produces .drawio + optional PNG/SVG/PDF, fully local.From its SKILL.md
npx -y skills add MakhimKitov/claude-drawio-skills --skill c4-drawioAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.8 KB, as published. Nobody here has run it
C4 → draw.io (auto-layout + draw.io style)
Hand-placing boxes in draw.io always overlaps. This skill lays the model out on a
layered grid — columns by dependency rank (internals left, external systems right of
the boundary, persons standing next to what they use), rows aligned to neighbours — and
emits a native draw.io file that looks hand-drawn with draw.io's own C4 shape
library: every element is a C4 <object> carrying c4Name/c4Type/c4Technology/
c4Description placeholders (editable via the Format panel / Edit Data), with the
palette's typography — 16px bold name, bracketed [Type: Technology] line, 11px muted
description — and the palette's sizes as minimums (boxes/cylinders 240×120, persons
200×180; descriptions always render in full, the shape grows if the text needs it).
Boxes are colour-coded by abstraction level (system / container / component), cylinders
for datastores, person2 silhouettes for people, grey-purple externals, a dashed system
boundary. Edges are grey blockThin orthogonal arrows with crossing jumps; every
edge on a shared side gets its own connection point, ordered by destination, so
lines fan out of a shape without overlapping or crossing each other. Adjacent columns
connect with a clean elbow through the gutter (one staggered vertical per edge); longer
edges travel
node-free corridors — down the gutter, across a lane above/below the diagram, up the
target's gutter — never through other shapes. Labels ride on the edge (bold
description + [technology], wrapped at 240px, collision-separated) and move with it
when re-routed. Pure Node — no Graphviz, no Docker.
You can feed it two ways: a small model JSON (Steps 1–3), or an existing Structurizr
workspace.dsl in one command (see "From a Structurizr DSL" below).
Workflow
Step 1 — Build the model as JSON
Translate the user's architecture (from their description, their code, or an existing
Structurizr workspace.dsl) into a model JSON file. Schema:
{
"title": "System Name — Software System",
"rankdir": "LR",
"nodes": [
{ "id": "web", "type": "container", "name": "Web App", "tech": "React", "desc": "Short responsibility" },
{ "id": "db", "type": "database", "name": "Database", "tech": "PostgreSQL", "desc": "What it stores" },
{ "id": "user", "type": "person", "name": "User", "desc": "Who they are" },
{ "id": "stripe","type": "external", "name": "Stripe", "desc": "Payment processing (no tech line — external systems never carry one)" }
],
"edges": [
{ "from": "user", "to": "web", "label": "Uses [HTTPS]" },
{ "from": "web", "to": "db", "label": "Reads/writes [SQL]" },
{ "from": "web", "to": "stripe", "label": "Charges [REST]", "dashed": true }
]
}
typemaps to draw.io's native C4 styling (defaultcontainer):person(navy silhouette) ·externalPerson(grey-purple silhouette) ·system(Software System,#1061B0) ·container(#23A2D9) ·component(#63BEF2) ·database(cylinder) ·queue(horizontal cylinder) ·external(External Software System, grey-purple).techis ONLY a technology — language/framework for an app ("Python","Go · gRPC"), the product name for a datastore ("PostgreSQL","Redis"). Role or deployment notes belong indesc, not here.system/externalnodes take notechat all — a software system is many technologies — and the generator drops it if present. An edge label like"Charges [REST]"splits intoc4Description+c4Technology.descis REQUIRED on every node: one short, informative sentence. It always renders in full — never truncated — and the shape grows in height past the 240×120 minimum when the text needs more lines, so keep it tight.- Arrows point in the control direction — who initiates the action — never the data flow. Edges to datastores are the exception: read/write data flow reads naturally there.
- Arrow text is a short verb phrase — keep the description part under ~60 chars (the generator warns above that); detail belongs in the node descriptions, not on lines.
titledraws a dashed C4 system boundary around the internal containers/datastores/queues;personandexternalnodes are placed outside it. Omittitlefor no boundary. Addboundaryfor a short boundary label (e.g. the system name) whentitleis a long diagram caption.rankdir:LR(left→right, default) orTB(top→bottom).dashed: trueon an edge for dashed lines (handy for external/async calls).- Use any string
ids you like — they're remapped internally, so reserved names likepushornameare safe. - For full details and tips see
references/model-schema.md; a complete worked example isexamples/messenger.json.
Write the model to a file, e.g. architecture.json.
Step 2 — Generate the .drawio
node <skill-dir>/scripts/c4-to-drawio.js architecture.json architecture.drawio
Self-contained — layout is computed by the script itself, no Graphviz or Docker needed.
Step 3 — Render (optional)
The .drawio is the deliverable — it opens and exports perfectly in the draw.io GUI.
To also produce an image locally:
bash <skill-dir>/scripts/render.sh architecture.drawio png 2 # -> architecture.drawio.png
(svg/pdf also work; the last arg is scale.)
Then show the user the .drawio (editable) and the rendered image.
From a Structurizr DSL (one command, all views)
If the architecture is (or should be) a Structurizr workspace.dsl, skip the hand-written
JSON: this generates a native draw.io diagram per view (context / container / component)
from that single model.
bash <skill-dir>/scripts/dsl-to-drawio.sh workspace.dsl [out-dir] [png|svg|pdf|none]
It exports the DSL to JSON via the Structurizr CLI (Docker), maps each view to a model JSON
(struct-to-model.js), then runs the same generator + renderer as above — emitting
<viewKey>.drawio (+ image) per view. Element tags drive the styling (External →
grey-purple, Database → cylinder, people → silhouettes); tag a relationship Async for a
dashed edge. Mapping, DSL gotchas, and the per-element tech property override are in
references/structurizr-input.md. Prefer this when one model should drive several consistent
views; prefer the JSON path for a quick one-off.
Prerequisites
- Node.js (for the generator — layout included, nothing else needed).
- Rendering only: draw.io Desktop. The CLI must run headless with
--no-sandbox(handled byrender.sh); otherwise it launches the GUI and hangs. - Structurizr DSL path only: Docker running with the
structurizr/structurizrimage (docker pull structurizr/structurizr), used to export the DSL to JSON.
Notes
- Already have a Structurizr
workspace.dsl?dsl-to-drawio.shturns that same model into editable draw.io with the native C4 palette — no need to re-describe the architecture. - Tune spacing in
scripts/c4-to-drawio.jsviaRGAP(gutter between columns) /CGAP(gap within a column) if a dense diagram needs more breathing room.