agentleFS
aliefauzanaliefauzan/Orthogram/skills/drawing-architecture-diagrams/SKILL.md

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

  • Other versions1 project uses a version of this.

    Word for word · 0

    None found.

    Edited · 0

    None found.

    Wrote their own version · 1

    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
  1. Very specific:

    Use the folder the user names.

    line 33
  2. Very specific:

    Never leave a build script, a .drawio or a preview in the project root, and never write outside the project you were pointed at.

    line 40
  3. Very specific:

    Do not patch styles in the old XML.

    line 61
  4. Distinctive:

    Waypoints: Every route leaves and arrives straight, along the normal of the face it uses.

    line 167
  5. Distinctive:

    Don't know the name? Search:

    line 227
  6. Distinctive:

    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 …

    line 261
  7. Distinctive:

    Use it when someone hands you a diagram whose look you are meant to match.

    line 277

≈ “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.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

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 at

Use 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:

  1. Every connector routed. A pinned exit side, a pinned entry side, and a corridor. arch_drawio.edge() will not build one without them.
  2. check_routing.py reporting 0 FAIL on the file you are handing over.
  3. A legend, one row per connector colour, saying what travels it.
  4. 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 panel

The constants are a starting point, not a law.

card250 × 58, stride 70 — 98 between two cards with an arrow between them
panelcard + 14 padding, 34 on top for its label
column pitch600 (panel 278, gutter 322, 9 corridors)
row pitch620
corridor pitch30, 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 path

A 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 kafka

Families, 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 look

preview.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.drawio

Use 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 fileRebuild through the emitter. Styles are not the routing.
Moving a card after routingIts corridors are now stale. Re-run the checker.
Placing columns before counting corridorsYou find out at RoutingError, with the layout already committed.
Vertical exit from a middle cardOnly 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 serviceColour is the kind of connection. Services get icons.
Reporting done without the checkerThis 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.

Download now (ZIP)

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
What did you use it for? e.g. Reviewing pull requests in a Rails app

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.