drawing-architecture-diagrams
Skill2 starsChanged 2 months agoMITView on GitHub
Use when building, editing, restyling or fixing an architecture diagram — cloud, on-prem or mixed — in Google Cloud visual style, a .drawio / draw.io diagram, or when connectors in an existing diagram cross boxes, strike through labels, or look messy
1 other project uses a version of this.
Adopted by
Most recently taken up by
- WhiteMuush/Your-Claude-DevOpstheir own version, first seen Nov 1, 2026
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- WhiteMuush/Your-Claude-DevOps★ 2same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository5 other files it gives its agents.
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 4 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈4
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 33
Use the folder the user names.
- Very specific: line 40
Never leave a build script, a .drawio or a preview in the project root, and never write outside the project you were pointed at.
- Very specific: line 61
Do not patch styles in the old XML.
- Distinctive: line 167
Waypoints: Every route leaves and arrives straight, along the normal of the face it uses.
- Distinctive: line 227
Don't know the name? Search:
- Distinctive: line 261
Read the picture for what a checker cannot see: a panel with one lonely card, a flow that reads backwards, six lines in a corridor that two …
- Distinctive: line 277
Use it when someone hands you a diagram whose look you are meant to match.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Drawing architecture diagrams
A .drawio architecture diagram in Google Cloud visual style: tinted panels,
white cards with the product icon, Google's palette on the connectors, and
every connector on a route you chose rather than one draw.io guessed.
The style is Google's; the systems need not be. About 2,400 product icons are available — GitHub, Jenkins, Terraform, Redis, Nginx, Kafka, Postgres and the rest of the on-prem world alongside GCP, AWS, Azure and Kubernetes — so an on-prem or multi-cloud system drawn this way still reads as one of these diagrams.
Build it with arch_drawio.py (this directory). Check it with
check_routing.py. Look at it with preview.py.
Where the files go
Everything this skill produces lives in one folder, never loose in the project root:
docs/diagrams/
payments-platform.py # the script that builds it
payments-platform.drawio # the diagram
payments-platform.preview.svg # what you looked atUse the folder the user names. Otherwise put it under docs/diagrams/ when the
project has a docs/ directory, and diagrams/ at the project root when it
does not — the build script, the .drawio, and any preview or PNG together.
write() creates the folder if it is missing, so
f.write("docs/diagrams/payments-platform.drawio") is all it takes, and preview.py
writes the SVG beside its input.
Never leave a build script, a .drawio or a preview in the project root, and
never write outside the project you were pointed at. One folder, named files —
a diagram whose script sits next to it can be regenerated; one scattered across
a repository root cannot be found again.
The output contract
Whatever you were asked for — a new diagram, an edit, a restyle, "just change the colours" — the file you hand back has all four of these:
- Every connector routed. A pinned exit side, a pinned entry side, and a
corridor.
arch_drawio.edge()will not build one without them. check_routing.pyreporting 0 FAIL on the file you are handing over.- A legend, one row per connector colour, saying what travels it.
- A label on every connector — what actually moves, not "uses".
Restyling or editing an existing diagram
Rebuild it through the emitter. Read the old file for its nodes, its edges and
its labels, then construct those same nodes and edges with arch_drawio.py.
Do not patch styles in the old XML. A diagram exported from a generator has no
routing in it — its edges carry a source and a target and nothing else — so
a styling pass leaves every one of them for draw.io to route, through whatever
boxes now sit in the way. That is what "restyled it and the lines are still a
mess" is, every time. Moving a column or resizing a card makes it worse,
because the router re-picks paths you never saw.
Plan the corridors before you place the columns
Count the connectors that have to cross each gutter. A gutter holds
(COL_PITCH - PANEL_W - LANE_INSET) / LANE_PITCH corridors — nine at stock
constants. A hub column feeding two neighbours will want more than that, and
you find out mid-build, after the layout is committed, unless you count first.
Widening costs nothing but page width:
import arch_drawio as G
G.COL_PITCH = 760 # before you create any panelThe constants are a starting point, not a law.
| card | 250 × 58, stride 70 — 98 between two cards with an arrow between them |
| panel | card + 14 padding, 34 on top for its label |
| column pitch | 600 (panel 278, gutter 322, 9 corridors) |
| row pitch | 620 |
| corridor pitch | 30, first at +40 |
d.lane(after=N) hands out the next free vertical corridor in the gutter right
of column N. d.band(below_row=N) does the same horizontally, and must be
called after that row's panels have their cards, since where the row ends
depends on how tall its tallest panel grew. One corridor per connector. Adding
a flow is then adding a lane, not re-arranging the flows already drawn.
Two connectors may share a corridor (share=True) when they are the same
journey — a request and its reply. Not otherwise.
Where a connector can leave a card
L(t) R(t) T(t) B(t) — side, and where along it.
Only the first and last card of a panel can leave vertically. Cards are stacked 12px apart, so a card in the middle has no way out through its top or bottom; the connector would start inside its neighbour. Everyone else goes sideways into a gutter. This is the constraint that decides your card ordering — put the card with the most connectors at the end of its panel — and the emitter enforces it.
Spread the anchors on a card that takes several connectors: L(0.25),
L(0.5), L(0.75). Three arrows into one point is three arrowheads on top of
each other. If check_routing.py reports two connectors stacked on a line and
they already have separate corridors, this is what it means.
direct=True skips the corridor. It is for two cards in the same panel, one
directly above the other, with nothing in between — not for adjacent columns,
which are further apart than it allows.
panel.port() makes a panel itself an endpoint, for the flows that belong to a
whole zone rather than one card in it: every service logging, a deploy landing
on all of them.
points=[(x, y), ...] is the escape hatch for a route no single corridor can
express — out, along a gutter, across a band, up into a panel. Every hop must
be horizontal or vertical. Reach for it when lane= and band= cannot say
what you mean; a diagram of any size needs it two or three times.
The card
The label lives on the icon cell, not the card. Its colours and sizes are inline HTML rather than style keys — that is how draw.io's own GCP shapes carry a two-tone label, and it is the only way the title and the subtitle can differ:
<b style="color:#202124;font-size:13px">Firestore</b><br>
<font style="color:#5F6368">products · clauses · graph_events</font>The icon sits at x=12, y=12 inside the 250×58 card, 34×34, and its style ends
with rounded=1. card(title, subtitle, icon) assembles all of that; the
numbers are here so you recognise them when reading someone else's file.
An arrow inside a panel opens the stack
Cards in a panel sit 12px apart, which is the right distance for a list of things and the wrong distance for an arrow: the arrowhead and its label do not fit, and the label ends up over a card. So a pair with a vertical arrow between them — and only that pair — gets 40px instead. A stack with no arrow in it stays tight.
This happens as the edge is drawn, so lane() and band() called afterwards
measure the panel at its real height. Take a band before drawing the arrows
inside that row's panels and you get a RoutingError naming both, because the
band was measured against a panel that has since grown.
What is settled at write time
Three things are worked out when the file is written, not when each connector was added, because each depends on every other connector — and half of those did not exist yet at the time:
- Anchors. Two connectors that both leave the middle of a face leave the
same pixel and run on top of each other. Anchors left at the middle are
spread; a fraction you pinned yourself is never moved, and the spread avoids
it. (Ask for
R(0.2)and nothing else lands within about 8px of it.) - Waypoints. Every route leaves and arrives straight, along the normal of the face it uses. Without that the last hop can run along a box's edge and the arrowhead points sideways into a corner — the defect reads as a bend at the tip. Corners that are not corners are dropped.
- Label positions. Each label is placed clear of other connectors, of crossings, of boxes and of the other labels, as near the middle of its own line as those allow — then pinned into the file, so draw.io and the preview show the same picture.
Corridors and bands start beyond the approach line, so a lane never runs alongside the straight bit of a connector leaving a face: two lines 4px apart read as one thick line with the labels floating between them.
A vertical lane() reached from a top or bottom face is refused: it costs two
corners more than the band() that case wants, every time. A band between two
side faces is fine — that is the ordinary long return path.
Where two connectors meet
Two edges that both leave the middle of a card's face leave the same pixel, and
their runs lie on top of each other out to the corridor. The first edge on a
face keeps the middle and the rest are spread along it, automatically; a
fraction you pass yourself is never moved, and direct=True is exempt so a
straight neighbour hop stays straight.
Where one connector crosses another, the horizontal one hops over it —
jumpStyle=arc in the file, an arc in the preview. Without the hop a crossing
and a junction are the same picture.
A connector's label sits in a break in its own line, on an opaque plate, drawn after every path — so it names the line it is about, and nothing is drawn over it. When that spot is taken the label slides along the line, and steps aside by one plate width — no further, or it stops belonging to anything — when staying on would cover a card, cover another label, or swallow the hop itself: two stacked cards are 12px apart, and a plate centred there hides the arrowhead.
Colour means kind, not service
SYNC blue, EVENT green, DLQ red, DATA yellow, MODEL purple, AGENT
cyan, PLUMBING grey. One colour per kind of connection: synchronous calls,
the async backbone, the failure path, store access, model calls, in-process
calls, and CI/CD-secrets-logs. Dashed for supporting paths. If you want an
eighth colour you probably have two kinds that are really one.
Icons
Pass a name and let the resolver find it:
p.card("Source control", "github.com/acme/api", icon="github")
p.card("Cache", "session store", icon="redis")
p.card("Provisioning", "terraform apply", icon="terraform")
p.card("API", "FastAPI · public", icon="gcp/compute/run.png") # or a pathA bare name must match exactly one icon, or exactly one inside the family you
name — icon("redis", "aws"). Names that exist in several clouds raise rather
than resolve, because quietly drawing the wrong vendor's logo is worse than
saying so. The error lists the candidates.
Don't know the name? Search:
python3 ~/.claude/skills/drawing-architecture-diagrams/arch_drawio.py kafkaFamilies, in the order the resolver prefers them: onprem (CI, VCS, queues,
databases, monitoring, IaC), generic, programming, saas, k8s,
elastic, then gcp, firebase, aws, azure, ibm, oci,
alibabacloud, digitalocean, openstack, outscale, gis.
The set is from 2020 and misses newer products — no Artifact Registry, no
Vertex Pipelines. Use the nearest sibling (devtools/container-registry.png)
rather than hunting.
Icons embed as data URIs so the file stands alone. draw.io writes those as
data:image/png,<b64> with no ;base64 marker — keep that form, it is what
draw.io reads. preview.py puts the marker back before rendering, because
nothing else accepts draw.io's version.
Before handing it over
S=~/.claude/skills/drawing-gcp-architecture-diagrams
python3 "$S/check_routing.py" docs/diagrams/out.drawio # must report 0 FAIL
python3 "$S/preview.py" docs/diagrams/out.drawio # writes docs/diagrams/out.preview.svg
rsvg-convert -w 1600 -o docs/diagrams/out.png docs/diagrams/out.preview.svg # now you can actually lookpreview.py is not draw.io. It draws unrouted connectors faded and straight
through, so an unrouted diagram looks obviously wrong. Its edge labels sit at
the midpoint of the path, which is close to but not exactly where draw.io puts
them — near enough to judge crowding, not to judge a single collision.
Read the picture for what a checker cannot see: a panel with one lonely card, a flow that reads backwards, six lines in a corridor that two closer panels would have made one.
Checking the style against a reference
ab.py diffs two .drawio files style key by style key, bucketed by role —
page, banner, panel, card, icon, edge, edge label, text. It matches roles by
cell id rather than guessing from the style, because a guessed bucket compared
against a guessed bucket produces a clean report that means nothing.
S=~/.claude/skills/drawing-architecture-diagrams
python3 "$S/ab.py" theirs.drawio mine.drawioUse it when someone hands you a diagram whose look you are meant to match. It tells you which keys differ, rather than leaving you to compare screenshots.
Common mistakes
| Patching styles in an existing file | Rebuild through the emitter. Styles are not the routing. |
| Moving a card after routing | Its corridors are now stale. Re-run the checker. |
| Placing columns before counting corridors | You find out at RoutingError, with the layout already committed. |
| Vertical exit from a middle card | Only the ends of a panel can leave up or down. |
Every connector out of R(0.5) | Spread automatically now, but four arrows on one face still means the card is doing four jobs. |
| A colour per service | Colour is the kind of connection. Services get icons. |
| Reporting done without the checker | This failure is invisible until it renders. |
preview.py writes a plain SVG — open it in any browser if you have no rsvg-convert. The PNG step is for pasting into a document, not for looking at it.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

