<< All versions

Skill v1.5.0

currentAutomated scan98/100
konraddzbik/architecture-diagram-skill/architecture-diagram

+12 new

──Details
PublishedNovember 1, 2026 at 02:33 AM
Content Hashsha256:c65fb18ca208fcac...
Git SHAe0e43282dd9c
Bump Typepatch
Compare with v1.0.0
──Files
Files (1 file, 23.7 KB)
SKILL.md23.7 KBactive
SKILL.md · 315 lines · 23.7 KB

name: architecture-diagram version: 1.5.0 description: "Build interactive, click-through architecture diagrams for software systems — a self-contained single HTML file with animated step-by-step flows, mode toggles (dev/prod, offline/online, v1/v2), dark/light theme, and a side panel with payload details, plus a companion markdown description. Use when the user wants to visualize or design a system: architecture diagram, service map, data flow, RAG/agentic flow, microservices topology, integration diagram, CI/CD or data/ETL pipeline, multi-agent system, or onboarding diagram — or to design a new service's flows before building. Natural-language triggers: 'I'm building X, what should the flow look like', 'pokaż jak działa system', 'diagram architektury', 'wizualizacja systemu', 'klikany diagram'. Do NOT use for static diagrams that belong inline (Mermaid/PlantUML), slide decks, or printable/PDF handouts — this produces interactive HTML for browser consumption." license: MIT


Interactive Architecture Diagrams

Build single-file, drop-in HTML pages that let workshop attendees, clients, or new team members click through how a system works — step by step, with animated data packets flowing between nodes, payload details on a side panel, and toggleable modes (offline/online, dev/prod, v1/v2). The aesthetic is dark and didactic-first: bounded nodes, gentle quadratic wires, packets that glow only on the active step — no rainbow gradients. Rebrand via the CSS tokens in assets/css-tokens.css.


When to reach for this skill

SituationUse this skill?
"Show me how the auth flow works" (interactive, for a workshop)Yes
"Design the RAG pipeline before we build it" (planning new service)Yes
"Map our microservices and how they communicate"Yes
"Visualize the CI/CD pipeline for onboarding docs"Yes
"Show the data flow through our ETL pipeline"Yes
"Draw an agentic multi-agent system with tool calls"Yes
"Build me an architecture mockup we can iterate on with the team"Yes
"Draw a sequence diagram for the PR" (static, goes in markdown)No — a Mermaid sequence diagram inline is simpler
"Add a diagram to a slide deck or PDF" (static, not interactive)No — this produces interactive HTML, not images or slides
"I just need a static boxes-and-arrows topology" (no flows/steps)No — a Mermaid flowchart is enough

The differentiator is interactivity + sequenced data flow: if the value is "click through it and watch what happens", use this skill; if you need a static image, a slide, or an inline diagram, use Mermaid instead.


The mental model

Every diagram has four things:

  1. Nodes — services, datastores, users, queues, external systems. Each has a role (color) and metadata (tech stack, port, deployment target).
  2. Flows — named scenarios the user can pick (e.g. RAG Query, Direct Query, Ingest, Auth). Each flow is an ordered list of steps.
  3. Steps — {from, to, color, title, route, payload, desc, chips}. Each step lights up one wire and one target node. (color and title are required — color must be a CSS variable name like --c-orch, anything else falls back to the brand accent; a missing title shows "—". Color it by the non-orchestrator endpoint: flow-design-patterns.md → "Wire color logic".) A step with from === to renders as a loop on that node — above it, or below for a top-row node (internal work such as "CI → CI: build").
  4. Modes — orthogonal toggle (offline/online, dev/prod, v1/v2). Modes can:
  • hide/show entire nodes (e.g. Seed only exists offline)
  • rename a node (Qdrant → BigQuery)
  • swap payload bodies, ports, auth headers, latency chips

Modes are NOT alternative flows. Flows describe scenarios ("user asks a question"); modes describe deployment shape ("on Docker" vs "on Cloud Run").


Workflow when invoked

Step 1 — Capture intent

If the user has uploaded a SOLUTION.md, README, OpenAPI spec, or any architecture description — or described the system in their message — read it first. Extract:

  • Service names + tech stack + ports
  • Deployment modes (if any)
  • Named endpoints/operations and what they do (these become flows)
  • For each operation, the chain of internal service calls (these become steps)

Then ask ONLY the gaps that can't be reasonably defaulted. If the system, its main flows and its modes (or lack of them) are known — or the user said not to ask — proceed, and list your assumptions in architecture.md. Defaults: audience = engineers, language = the request's.

Only for a vague request ("diagram our backend") ask briefly: what system, which main flows, any mode toggles (offline/online, dev/prod, v1/v2), who the audience is.

Step 2 — Plan the topology on paper first

Before writing code, sketch on paper (literally in your head or a scratch file) WHICH services exist, WHERE they sit relative to each other, and WHICH flows connect WHICH nodes. Avoid wire crossings — this is the single biggest readability win. See references/flow-design-patterns.md for layout heuristics.

Quick rules:

  • Orchestrator/API gateway in the middle, dependencies fanning out
  • User on the far left (entry point), datastores on the right (exit), services in between
  • Read-only services above, write-heavy services below (intuitive: data flows down into them)
  • Optional/one-shot services (seed jobs, cron) tucked in a corner

Step 3 — Build from the template

Copy assets/template.html to the working directory. It's a fully working drop-in: dark theme, side panel, player controls (play/pause/step), keyboard shortcuts, animated SVG packets, mode toggle. Edit only these regions (the template's top EDIT THESE THINGS comment is the authoritative list):

  1. `<title>` + `<h1>` — replace {{SYSTEM_NAME}} and the header text. For a Polish (or other non-English) diagram also set <html lang="pl">.
  2. `.modepick` buttons — mode toggle labels (or remove the whole .modepick if single-mode; the panel badge and O key adapt). Three or more modes are fine — O cycles through them.
  3. `.flowtabs` — one .flowtab per scenario; data-flow must match a flows key. Tab order = keyboard digits 1–9; nothing else to keep in sync.
  4. `.node` divs in .stage — one per service: data-id, data-role, style="left/top", label, tech, port. Place them on the grid in references/flow-design-patterns.md (left 2/26/52/78%, top 8/38/70%, ≥ 24% apart in a row) — fixed 150px tiles overlap or clip otherwise.
  5. The `flows` object in JS — one entry per scenario, each with an ordered steps[] array. Set state.mode / state.flow to the keys you want shown first (an unknown key falls back to the first button and logs a warning).

Always edit the .legend: one item per role you use, labelled with what that color means in your system (e.g. compute → "Worker"); delete the rest. Recolor :root CSS variables only for a restyle. After editing, search the file for {{[A-Z] (regex) — a correctly filled file has zero matches.

Don't reinvent the CSS, the player, the SVG wire renderer, or the side panel — they all work.

Step 4 — Validate before showing the user

After generating, do this self-check:

  • [ ] Open the file mentally: does every flow's step sequence make narrative sense? (Step 1 sets up, last step delivers a result to the user.)
  • [ ] Do wires cross unnecessarily? If yes, reposition nodes (try moving the late-arriving dependency away from the early ones).
  • [ ] Are there flows where a single node is the to of two consecutive steps? That's fine if it's a loop, but check the description explains why.
  • [ ] Mode swap: pick the most different node between modes (usually the database) and verify ALL its mode-dependent fields are filled in (label, tech, port, payload, chips).
  • [ ] Did you generate the companion architecture.md? (Required — see Step 5.)

Then run every check in references/validation.md the environment allows: the static check (needs only node); then, with puppeteer-core + Chrome, node <skill-dir>/references/screenshot.js architecture.html /tmp/arch-preview from the user's project (<skill-dir> = this SKILL.md's folder; exit 1 = page error, 2 = lint warnings — non-zero means fix the HTML) and read the canvas PNGs for overlapping or cut-off tiles; without either, window.archValidate() in the browser console ([] = clean).

Step 5 — Output the files

Always two files:

  • architecture.html — the interactive diagram
  • architecture.md — text description (components, flows step-by-step, mode differences, scenarios for the workshop)

Save to the current working directory. Platform-specific overrides:

  • Claude.ai — use /mnt/user-data/outputs/ instead
  • Claude Code / Gemini CLI / OpenCode / Copilot CLI — save to the current working directory (default)

Both should be self-sufficient — someone can read the markdown without opening the HTML, and vice versa.

Step 6 — Present the output

Tell the user where the files were saved and how to open them (open architecture.html on macOS, xdg-open architecture.html on Linux, or just open in browser). If present_files is available (Claude.ai), call it to display the HTML first, then the markdown.


File reference

FileWhen to read
assets/template.htmlAlways. This is the starting point you copy and modify.
assets/css-tokens.cssIf user asks to restyle (e.g. light theme, different brand colors). Standalone tokens you can splice into existing CSS.
references/flow-design-patterns.mdWhen planning a new system from scratch. Heuristics for node placement, naming flows, sequencing steps, choosing modes.
references/component-library.mdWhen building the nodes list. Copy-paste node snippets for User/API/Service/DB/Queue/Cache/LLM/Cron/External/etc. with proper roles and icons.
references/validation.mdStep 4. Static check (node only), how to run references/screenshot.js (headless-Chrome previews + lint) and its exit codes, browser-console fallback.
examples/rag-eskadra-bielik.jsonReference example: a real RAG system with 5 flows and offline/online modes. Read for topology layout, offline/online mode design (per-node tech/port swapping), and flow decomposition via step_outline. Payload/chip conventions are in the sections below, not the examples.
examples/auth-oauth2.jsonReference example: an OAuth2 + session flow with dev/prod modes. Shows redirect flows and external IdP nodes.
examples/event-driven.jsonReference example: event-driven microservices with Kafka, showing async fan-out flows.
examples/cicd-pipeline.jsonReference example: CI/CD pipeline with GitHub Actions, staging/prod modes, rollback flow.
examples/agentic-tool-calling.jsonReference example: agentic AI system with tool calling, single-agent vs multi-agent modes.

The `examples/*.json` files are planning specs, not drop-in code — JSON outlines you translate into the template's HTML nodes + inline JS flows object. See references/flow-design-patterns.md → "Example JSON → template mapping" for the field-by-field translation.


Quick reference — node roles and colors

Hardcoded in CSS variables in template.html. Pick one per node:

RoleColorUse for
usermint #46f9b8Browser, mobile client, end user, CLI user
orchsky #6aa9ffAPI / Service: gateway, orchestrator, BFF, ordinary internal services
computemagenta #ff6b8aLLM, ML model, worker, expensive compute
embedamber #ffc14dEmbedding service, transformer, preprocessor
vectorviolet #b388ffDatabase (any), vector store, cache, queue, blob storage
seedorange #ff9457Cron, one-shot job, migration, seed, scheduled task
extslate #94a3b8External: 3rd-party / SaaS (Stripe, Twilio, Confluence, hosted IdP)

Roles are color groups, not literal meanings; the legend labels say what each color means in your diagram. Don't invent more (Postgres + Redis are both vector, told apart by icon and label) — past seven the legend becomes a colorblind nightmare. An 8th role needs a --c-<role> in the dark :root and body.light blocks, a .node[data-role] rule, an ahMap entry + <marker>, and a legend item.


Visual states — what the viewer sees on each step

This is the most important didactic mechanic in the diagram. Understand it before modifying the JS or CSS, or you'll break the "click a flow tab, see the whole path" intuition.

When a user picks a flow tab and lands on step N, every node and wire is classified into one of these states:

ElementStateLooks likeWhen
NodeactiveFull ring + glow + step-number badgeTarget of current step (e.g. LLM when step says "Orch → LLM")
Nodeactive-fromSoft ring, no badgeSource of current step
NodeparticipantNear-full opacity, slightly desaturatedAppears anywhere else in this flow, just not in this step
Nodedimmed25% opacity, washed outNot in this flow at all (e.g. seed during a login flow)
NodehiddenInvisibleMode-excluded entirely (e.g. seed node in online mode)
WireactiveBright role color, glow, packet animatingThe wire of the current step
WirepreviewRole color at 50% opacity, dashedBelongs to this flow but not the active step — shows the full path ahead
Wiremuted~8% opacityDoesn't belong to this flow

Why `participant` matters (and the JS/CSS implementation gotchas) is detailed in references/flow-design-patterns.md → "The participant state". Short version: it lets a viewer see the whole path on the first click, instead of stepping through to discover which nodes a flow uses — that's the entire point of the diagram. If you add node states, keep applyStep and the CSS (.node.participant, .wire.preview) consistent.


Interaction model

The diagram supports five ways to interact, in increasing order of viewer expertise:

InteractionWhat happensWho uses it
Click flow tabJump to the first playable step of that flow, side panel updatesEveryone
Click Next/Prev (or →/←, Space)Advance/rewind one step; Play at the end restarts the flowWorkshop attendees walking through
Click a nodeJump to the first step where this node appearsCurious viewers exploring
Drag a node (mouse/pen) or Shift+Arrows on a focused nodeReposition the node on the canvas; wires redraw live; layout saved per browserLayout tweakers / presenters
Fullscreen (F)Canvas fills the screen with the controls bar on top, flow tabs at the bottom, and the side panel as an overlay; Escape or the same button exitsWorkshop presenters

Node click vs drag. A 5px movement threshold distinguishes a click (jump to step) from a drag (reposition). On touch screens nodes are tap-to-jump only, so swiping over a node still scrolls the page.

Node click is the easiest to miss when modifying the skill. Three things must be in place:

  1. cursor: pointer on .node (visual affordance — "this is clickable")
  2. :hover state that reveals the role color (confirms interactivity)
  3. The JS handler that does findIndex on the current flow's steps and jumps there

If a node isn't part of the current flow (.dimmed state), clicking it shakes the node instead of doing nothing. Silent ignore is bad UX — the viewer thinks the page is broken.

Keyboard accessibility: nodes have tabIndex=0, Enter/Space triggers the same action as click, Shift+Arrows moves the node one grid cell. Step changes are announced through a live region. Single-key shortcuts can be switched off via the "shortcuts on" link under the tabs (WCAG 2.1.4).

Don't break this when adding features. It's the only way for a viewer to think "wait, where is the LLM used?" and find out instantly. Without it, they'd have to step through all 8 steps just to discover one node's role.


Quick reference — payload format

Payloads in the side panel are monospace + minimal syntax highlight. Keep them realistic but trimmed — show the shape, omit boring fields:

js
{
payloadOffline:
`POST /ask
{
"query": "Ile kosztuje parking?",
"limit": 3,
"temperature": 0.7
}`
// avoid: full HTTP headers, User-Agent, 50-line bodies — show only the shape
}

Use 4-space indent, no tabs. Use // comments for inline annotations.

If a step is the same in both modes, use payload (single key). If they differ, use payloadOffline + payloadOnline (or whatever the mode names are: payload + capitalized mode key, so mode prod → payloadProd). The mode-specific key wins when both are present — handy for "generic payload, one mode overrides it". Same rule for chips / chipsOffline. An object instead of a string is pretty-printed as JSON.

desc accepts inline HTML only: <em>, <strong>, <code>, <kbd>, <br>, <a href="https://…">. Everything else is stripped at render time (block tags unwrap, scripts/iframes are dropped) — keep descriptions to a sentence or three.


Quick reference — chips (metadata badges)

Chips below the payload are short metadata labels. Two semantic types auto-style themselves:

  • Latency (matches /\d+\s*(?:ms|s|min)\b/) — gets a stopwatch icon, e.g. "~150ms", "5-30s", "timeout 120s"
  • Size/count (matches /dim|×|loaded|rules|count/) — gets a database icon, e.g. "768 dim", "38 loaded", "×N"
  • Other — neutral, e.g. "COSINE", "baseline", "idempotent", "UUID5"

Maximum 3 chips per step. They're hints, not specifications.


Naming conventions

ThingConventionExample
Flow key in JSsnake_caseask, ask_direct, ingest_text
Flow display name"Title Case (METHOD /route)""RAG Query (POST /ask)"
Node data-idsnake_case, shortorch, vector, embed
Mode keysnake_case, descriptiveoffline/online, dev/prod, v1/v2
Step titlePolish or English, depending on workshop language. Consistent within one file."Pytanie z UI" or "Question from UI"

Common pitfalls

Three strings kill the whole diagram. Everything in flows lives inside one <script> block, so in any desc, title, payload or chip:

  • </script> closes the block early — write <\/script> (&lt;/script&gt; works only in desc; elsewhere it shows literally).
  • <!-- with a <script anywhere after it keeps the real </script> from closing the block — write <\!--.
  • ${…} in a backtick payload runs as JavaScript (crash, or silently wrong text). Write \${ (e.g. \${{ secrets.TOKEN }}) and ` \ `` for a backtick.

The page lints itself (browser console, window.archValidate(), or screenshot.js): unknown node ids, tab/flow mismatches, unknown onlyMode / data-modes values, missing title/color, leftover placeholders. A clean console is part of "done".

Content Security Policy. The template ships a CSP <meta> that allows only inline script/style and Google Fonts. If a user asks for an external image, script, or font, extend the matching directive (or they'll see a blocked request in the console).

Source node looks dead. If a step's source node renders dimmed instead of active-from, you regressed the participant logic — see "Visual states".

Wire crossings. Caused by node placement, not code — swap node positions to fix. (Wires bend to the right of their direction of travel, so a request and its response sit on opposite sides; repeats between one pair get wider lanes. That helps but won't fix a bad layout.)

Too many flows. More than 6 flows clutters the tab bar. If you have 8+, group them: one diagram per group (e.g. "read flows" vs "write flows" as two separate HTML files).

Modes that aren't really modes. If the toggle changes the entire topology (different services, different protocols), it's not a mode — it's a second system. Build two HTML files.

Static screenshots beat live diagrams sometimes. If the diagram will end up in a PDF report, a slide deck, or a printed handout, this skill is the wrong choice — produce a static diagram instead. This skill is for interactive consumption in a browser.

Forgetting the .md. The HTML is the showpiece, but the .md is what people read on GitHub, paste into Slack, and grep for endpoint names. Always generate both.

Polish vs English. Match the workshop language. Bilingual settings typically use Polish for internal workshops and English for client deliverables. Default to the language of the request; ask only if it's genuinely ambiguous.


Extending the template

If a user asks for something the template doesn't support, here's the difficulty ranking:

RequestDifficultyWhere to edit
New nodetrivialAdd .node div, position via left/top %
New flowtrivialAdd entry to flows object
Different brand colorssmallEdit CSS variables in :root (see assets/css-tokens.css)
Light themebuilt-inClick the moon/sun button or press T. To make light the default, add class="light" to <body>.
Drag-and-drop nodesbuilt-inAlready supported — drag any node (mouse/pen) or Shift+Arrow a focused one; positions snap to a 48px lattice; only moved nodes are saved in localStorage (keyed by page title + node-id set — give each diagram a unique title).
Fullscreen modebuilt-inPress F or click the expand icon. Controls bar and flow tabs stay reachable, the side panel too above ~1140px (narrower: a one-line step summary); Escape or the button exits.
Self-step (internal work)built-inA step with from === to draws a loop on the node (above it; below it on the top row).
Three or more modessmallAdd a button to .modepick; add payload<Mode> / chips<Mode> / data-*-<mode> fields. O cycles through all modes automatically. Mode colors follow button order, not keys: 1st blue, 2nd violet, 3rd+ accent.
Layout resetbuilt-inPress R or click the ↻ button (appears after any drag).
Progress barbuilt-inThin bar below player shows step position in current flow.
Flow note linebuilt-inSet note on a flow (and onlineNote on an onlyMode flow); it renders under the player.
Reduced motionbuilt-inHonors prefers-reduced-motion: the flying packet is hidden and transitions collapse.
Parallel steps (two simultaneous wires)mediumGroup steps as {parallel: [step, step]}; player advances both
Branching flows (if-then-else)hardCurrently linear. Either fork into separate flows or add a branch field with UI for picking the branch.
Saving state in URLsmallHash-based: #mode=online&flow=ask&step=3 — parse in boot, update on changes

Don't promise features the template doesn't support without flagging the work involved.


Iteration tips

When the user gives feedback like "the diagram is too cramped" or "step 5 is confusing":

  • "Too cramped" → use the whole grid (Step 3) and shorten tech/port text; never below 24% between nodes in a row. More than ~12 nodes → split the diagram.
  • "Confusing step" → the step description is doing too much. Split into two steps OR rewrite to focus on ONE handoff (X sends Y to Z, that's it).
  • "It doesn't match how it really works" → ask for the actual code path. Don't guess; the diagram has zero value if it lies about reality.
  • "Make it pop more" → resist. Didactic clarity > visual punch. Maybe one accent element (a glow on the result node when flow completes) but stop there.
  • "Add a legend" → already there. If they want it bigger, increase the .legend font-size and gap.
← v1.0.0All versions