What does arch-diagram do?
Two methods, usable individually or chained (natural language → Mermaid → HTML).
- nl2mmd: natural language → Mermaid dialect
- mmd2html: Mermaid dialect → interactive HTML (template: this skill's
assets/template.html)
Common Convention: Mermaid Dialect
Structure (three layers, corresponding to the HTML server→service→sub-service):
- Top-level
subgraph= server, withdirection TBinside - Second-level
subgraph= service (only create a subgraph when there are sub-services; services without sub-services are written directly as nodes) - Nodes inside a service subgraph = sub-services
- All titles use quoted text:
subgraph X["Title"],N["Title"]
Metadata (meta): use | inside the title to separate name from metadata. After generating HTML, the metadata appears as light small text next to the name (server specs, ports, workload, parameters, etc.). Omit | if no metadata:
subgraph WEB["Web Edge | Active-Active · LAN"]→ server name "Web Edge", metadata "Active-Active · LAN"WEB_GW["API Gateway | QPS 3k"]→ service name + metadata- Parsing rule: take the last
|, left side is name, right side is metadata
Edge types are expressed by line style, fixed:
| Type | Line Style | Semantics |
|---|---|---|
| sync | ==> | data sync / write-back |
| call | --> | API / RPC / WS |
| job | -.-> | cron / scheduled task / push |
| data | -.- | read-only query |
- Edge labels:
==>|"type · time or frequency"|, e.g.,==>|"sync · 07:10 4×/day"|;-->|call|can omit the description - Node IDs use uppercase snake_case:
<server>_<service>_<sub-service>, e.g.,NAS_SCHED_FLAT - Edges can anchor to subgraphs (service-level or server-level), indicating that edge is at that granularity
- Starts with
flowchart LR; internal edges within the same host are written normally (when generating HTML, these become right-out right-in looping lines)
Method 1: nl2mmd (Natural Language → Mermaid)
- Extract entities: machines/hosts/environments → servers; software installed or running on them → services; components/features/tasks/libraries within software → sub-services.
- Extract relationships: verb mapping—sync/write-back/mirror → sync; call/request/send-receive → call; daily/scheduled/cron/xx:xx/push → job; read/query/white-box → data. Write time and frequency into edge labels.
- When uncertain about the level, place at the service level; do not invent sub-services.
- Put numbers and spec information (ports, specs, workload, IP ranges, etc.) into node metadata:
["Name | Metadata"]; put time and frequency into edge labels. Do not lose information. - Output a complete
flowchart LRcode block, no explanation needed.
Method 2: mmd2html (Mermaid → Interactive HTML)
Steps
- Read the full
assets/template.html(about 38KB, self-contained single file, default data is the content ofexamples/sample.mmd). - Parse the Mermaid (following the dialect above), build a
mermaid id → hierarchy pathmapping: paths are dot-connectedserver.service.sub-service(truncated by nesting depth). When an edge anchors to a subgraph, the path stops at that level. - Replace the entire block between
/*==DATA==*/and/*==DATA-END==*/in the template with the new data block, leave the rest of the code unchanged:
/*==DATA==*/
var ARCH_TITLE='Diagram Title (terminal title bar and standalone <title>)';
var ARCH_LSKEY='arch-<slug>'; // localStorage key, unique per diagram
var TYPE={sync:{c:'#3ecf8e',dash:'10 4',dur:'1.5s',label:'Sync'},
call:{c:'#58a6ff',dash:'6 5',dur:'1.1s',label:'Call'},
job :{c:'#f0a942',dash:'2 4',dur:'0.85s',label:'Job'},
data:{c:'#b18cff',dash:'14 5',dur:'1.9s',label:'Data'}};
var COLS=[['srvA','srvB'],['srvC']]; // default column layout: each array entry = a group of server IDs
var SERVERS=[
{id:'srvA',short:'A',name:'A · Display Name',meta:'Metadata',ac:'#b18cff',svc:[
{id:'svc1',short:'svc1',name:'Service 1',meta:'',subs:[
{id:'sub1',short:'sub1',name:'Sub-service 1',meta:''}]},
{id:'svc2',short:'svc2',name:'Service 2'}]},
];
var EDGES=[
{from:'srvA.svc1.sub1',to:'srvC.svc2',type:'sync',sched:'07:10 4×/day'},
];
/*==DATA-END==*/
Field rules:
iduses ASCII (dot-path is built from this);namecan be Chinese;shortis the short name used in connections/logsmetacomes from the part after the last|in a node/subgraph title; omit if absentaccycles through the palette:#b18cff #3ecf8e #39d0c4 #58a6ff #f0a942type∈sync|call|job|data(corresponding to Mermaid line styles);schedcomes from the part of the edge label after the type, writereal-timeif absentCOLS: roughly arrange by edge flow direction (sources on left, sinks on right); single-server column generator automatically centers vertically
- Write the output to the target path (fragment version). When double-click usage is needed, wrap it:
<!doctype html><html lang="en"><head><meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{ARCH_TITLE}</title>
<style>html,body{margin:0;padding:0;background:#080b12}#svcarch{min-height:100vh}</style></head><body>
{fragment}</body></html>
QA
- Mandatory: extract the
<script>and runnode --check; verify data—server/service/sub-service counts match Mermaid, edge count = Mermaid edge count, default view connection count = deduplicated (from,to,type) groups. - When browser is available: when serving locally, must include charset header (
python3 -m http.serverdoes not include charset, causing Chinese garbled characters; use a custom handler to addContent-Type: text/html; charset=utf-8for.html), open and check title, counts,▾ serversgranularity switching, and click to collapse. - Only modify the DATA block in the template; do not re-implement the rest of the code (drag, collapse, persistence).
Examples
examples/sample.mmd— complete dialect example (4 servers, 9 edges, covering all 4 line styles and same-host edges)examples/sample.html— finished product generated from template (double-click to use)
Built-in Capabilities of the Generated HTML (do not re-implement outside the template)
Drag to move (bar handle on top, hold Alt to show all handles), resize right edge, collapse/float up, three granularity presets (servers/services/leaves), edge log / inspector, layout and collapse state stored in localStorage (key = ARCH_LSKEY). Interface text is in English.
- Canvas zoom and pan: Ctrl+scroll wheel to zoom centered on cursor (0.4–2.5×), hold Ctrl to switch mouse to hand shape, drag to pan canvas; percentage chip in bottom-right corner click resets. Zoom/pan persisted via localStorage.
- Built-in editing: Hold Alt and click any node header (all three levels) to edit name/metadata/server border color, add children, delete (two-step confirmation, cascading subtree and edges); Alt+click on an edge to change type/timestamp or delete it; while Alt is held, a ⇱ export button appears in the top-right corner, showing a modal with the latest Mermaid (syntax highlighted + copy button), containing ⟲ relayout and ↺ restore default data buttons. Editing results persist via localStorage.