# Arch Map

> Use when you need a visual architecture map of a codebase and no finished source document exists (an existing subsystem, a refactor in flight, or a proposed design) rendered as a self-contained HTML page. NOT for rendering a report that already exists, on disk or as findings reached in the conversation; that is html-report.

- Skill: `giostriquer/arch-map` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add giostriquer/arch-map`
- Raw SKILL.md: https://api.skillmd.com/api/skills/giostriquer/arch-map/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: giostriquer (https://skillmd.com/u/giostriquer)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/giostriquer/arch-map

---


# Arch Map

## Purpose

Derive an architectural representation (from the repo, a diff, or a plan)
and render a **self-contained HTML architecture map** optimized for
orientation: a graphical mental model first, then the inventory that backs it.

Sibling boundary: the line is *who authors the content*, not whether a file
exists: `html-report` renders findings that already exist (as a document or
as work done in the conversation) and may never invent content; `arch-map`
**authors the representation** by reading code, and must trace every element
to something real (file, symbol, or diff hunk).

## When to use

Three input shapes, grounded in the repository, diff, or proposed plan:

1. **Existing subsystem**: how a part of the codebase is structured today.
2. **Refactor in flight**: branch/diff (or planned): what moves, what stays.
3. **Proposed design**: plan or conversation; target state before commit.

Not for: rendering a report that already exists, whether on disk or as
findings reached in this session (use `html-report`); freeform diagrams
disconnected from this repo's code, diff, or plan.

## Skill package layout

Everything an adopting project needs ships **next to this file**:

| Path | Role |
|---|---|
| `references/subsystem-specimen.html` | Worked subsystem page (SVG mental model + layers + rules) |
| `references/refactor-specimen.html` | Worked refactor page (Today\|Target graph + stages) |

Resolve these relative to the skill directory the host loaded (plugin cache
or repo checkout). Do **not** look for workshop-local `tmp/` specimens;
they are not part of this package. The CSS tokens, markup scraps, and fit
rules in this file are the complete contract; following them is enough.

## Step 0: house style

1. Glob the **output project's** scope/artifact directories and `docs/` for a hand-authored
   standalone `.html` architecture page (inline styles; exclude
   `node_modules/`, `dist/`, etc.). **Genre test:** structural graphics
   dominate (system map, layers, legend, before/after flow), unlike a
   `html-report` report. If a sibling exists, match its tokens and component
   shapes.
2. Otherwise use the **deep-dark glass** defaults below, copying structure
   and tokens from the shipped specimens:
   - Subsystem → `references/subsystem-specimen.html`
   - Refactor → `references/refactor-specimen.html`

When analyzed repo ≠ output repo, glob both; **output repo sibling wins**.

## Pipeline

### 1: Derive

Mine boxes (modules, layers, components) and edges (calls, imports, data
flow).

- **Subsystem:** entry points → modules → edges. Prefer architecture /
  dependency-rule tests first (`architecture.test`, boundary lint): enforced
  rules beat guessed imports. Fan out explore subagents on large surfaces.
- **Refactor:** classify diff into add / remove / move / rename; state **the
  invariant** (what does *not* change).
- **Proposed design:** extract from plan; verify real references; mark the
  rest proposed (dashed).

**Traceability (load-bearing).** Observed boxes and edges trace to a real file, symbol, or diff hunk
(path in caption/`title`). Proposed elements trace to the plan or conversation
and use dashed styling; never silently mix them with observed structure.

### 2: Choose views

At most **3 views** (plus the mandatory mental-model diagram). Each view
opens with the question it answers.

| Piece | Question | Form |
|---|---|---|
| **Mental model** (required) | "How do I hold this in my head?" | SVG layered system map, *or* for refactors a Today\|Target flow graph (chips + connectors) |
| Containment / layers | "How is it organized?" | Stacked glass bands + module cards |
| Flow | "How does data / control move?" | HTML connector steps |
| Before / after | "What does this change?" | Linked compare panes (large refactors) |
| Delta | "What does this change?" | One canvas, good/bad/dim chips (small refactors) |

Deriving more than you show is fine. Name unchosen views in the intro. Do
not draw a fourth diagram.

### 3: Render

Produce an offline, self-contained HTML file: inline CSS, JavaScript, SVG, and
any necessary assets; use system fonts. No CDN, remote font, or external script
requests. Render diagrams as inline SVG or bundle required renderer code locally.
The reference specimens illustrate style; do not copy their network imports.
Use the repo's scope folder, otherwise `.workbench/<scope>/`. Promote to a durable
location only when requested or conventional, after rechecking provenance. Match
requested language; otherwise use the conversation's language for chrome and copy.

## Visual language: deep-dark glass (rigid defaults)

### Deep dark + glass

Near-black canvas with a subtle sky neon at the top; panels are translucent
glass, not flat `#181818` chrome.

```css
:root{
  --bg-gradient:radial-gradient(circle at 50% 0%,rgba(56,189,248,.08),transparent 35rem),
                linear-gradient(180deg,#020408 0%,#050811 100%);
  --bg:#020408;
  --surface:rgba(10,15,26,.85);
  --raised:rgba(0,0,0,.45);
  --ink:#f1f5f9; --soft:#cbd5e1; --muted:#94a3b8;
  --line:rgba(255,255,255,.07); --line-strong:rgba(255,255,255,.12);
  --accent:#38bdf8; --accent-wash:rgba(14,165,233,.16);
  --ok:#34d399; --ok-wash:rgba(6,78,59,.4);
  --no:#fb7185; --no-wash:rgba(136,19,55,.4);
  --sans:"Inter",system-ui,sans-serif;
  --mono:"JetBrains Mono",ui-monospace,Consolas,monospace;
  --radius:16px; --wire:#94a3b8;
}
body{margin:0;background:var(--bg-gradient);color:var(--ink);font:16px/1.55 var(--sans);min-height:100vh}
.glass-card{
  background:rgba(10,15,26,.75);
  border:1px solid rgba(255,255,255,.07);
  box-shadow:0 20px 50px rgba(0,0,0,.7);
  backdrop-filter:blur(20px);
}
code{
  font-family:var(--mono);font-size:.86em;
  background:rgba(10,15,26,.9);border:1px solid var(--line-strong);
  border-radius:6px;padding:.08em .4em;color:#7dd3fc;
  overflow-wrap:anywhere;word-break:break-word;
}
```

Fonts: system sans-serif for UI and system monospace for paths/chips. Inline
licensed font data only if an explicit visual requirement warrants it.
Use inline SVG icons. If a diagram renderer is needed, bundle it locally so
opening the page makes no remote requests.

**Body text is `--ink` / `--soft`.** Use `--muted` for captions/paths only,
never for mid-grey paragraphs on black.

### Color scarcity

- Sky accent (`#38bdf8` / `#7dd3fc`) for chrome, protocol tags, emphasis wires,
  section numbers, sticky-nav brand.
- Emerald eyebrow pill + green/red **only** for ✓/✕, refactor good/bad,
  Today/Target panel chrome.
- **No role rainbow** (do not paint modules entry/domain/infra/ext).

### Page skeleton

**Subsystem pages**

1. Sticky glass pill TOC (optional on short pages)
2. Glass hero: emerald eyebrow + large Inter title + lede + fact tiles
3. **§ Mental model**: SVG system map in a glass stage (+ optional Mermaid)
4. Supporting inventory (stack, layers, rules, flows, …)
5. Provenance footer

**Refactor pages**

1. Glass hero (eyebrow + title + lede + fact tiles)
2. **Today | Target** compare panes (the graph): load-bearing
3. Rule card + migration stages (or other supporting views)
4. Provenance footer

A page that skips the graphical mental model / compare graph fails the
skill.

### Mental-model SVG (subsystem)

Layered bands (`.band`), boxes (`.box` / `.box-emph` process owners /
`.box-ext` dashed external), wires + markers, lane labels. ★ for spawn
owners. Match `references/subsystem-specimen.html`.

```css
.arch-svg .band{fill:rgba(0,0,0,.45);stroke:rgba(255,255,255,.07)}
.arch-svg .box{fill:#050811;stroke:rgba(255,255,255,.2);stroke-width:1.25}
.arch-svg .box-emph{fill:rgba(14,165,233,.22);stroke:#38bdf8;stroke-width:1.75}
.arch-svg .box-ext{fill:rgba(0,0,0,.55);stroke:#94a3b8;stroke-dasharray:5 4}
.arch-svg .title{fill:#f1f5f9;font-weight:700}
.arch-svg .sub,.arch-svg .lane-label{fill:#94a3b8;font-family:var(--mono)}
.arch-svg .wire{stroke:#94a3b8;stroke-width:1.75;fill:none}
.arch-svg .wire-accent{stroke:#38bdf8;stroke-width:2.25}
.arch-svg .wire-label{fill:#cbd5e1;font-family:var(--mono);font-weight:600}
```

**SVG text must fit its box: SVG never wraps or clips.** This is the #1
mechanical defect. Rules:

- **Short labels only.** Box titles are one noun; `.sub` is a short path or
  tag (`src/web · :5173`), never an enumeration. Push detailed lists into
  the HTML layer cards below, not into SVG text.
- **Size the box to its text**, not the reverse. Rough budget at 12px mono:
  ≈ 7.2 user-units per character. A 330u box holds ~40 chars with padding;
  leave ≥ 5u slack each side.
- **Center with `text-anchor="middle"`** at the box's mid-x so growth is
  symmetric and overflow is obvious.
- **Last resort for an unavoidably long label:** add
  `textLength="<box-width-minus-pad>" lengthAdjust="spacingAndGlyphs"` to
  compress-fit, or split into two `<tspan>` lines. Do not let it bleed.
- **Wrap the diagram, don't break the page.** The stage gets
  `overflow-x:auto`; give a dense `.arch-svg` a `min-width` so it scrolls
  *inside the stage* at narrow widths instead of forcing a horizontal page
  scroll.

### Refactor chrome (Today | Target)

Glass panes with rose/emerald borders (not a 2px top bar alone). Chips +
HTML connectors carry the graph. State the **invariant** above or in the
lede. Match `references/refactor-specimen.html`.

```css
.panel{background:var(--surface);border:1px solid var(--line);border-radius:18px;
  padding:22px 20px;box-shadow:0 20px 50px rgba(0,0,0,.55);backdrop-filter:blur(20px)}
.panel-today{border-color:rgba(244,63,94,.28)}
.panel-target{border-color:rgba(52,211,153,.28)}
.chip{font:500 11px/1.3 var(--mono);padding:3px 8px;border-radius:9999px;
  white-space:normal;overflow-wrap:anywhere;max-width:100%;
  border:1px solid var(--line-strong);background:var(--raised);color:var(--soft)}
.chip-good{border-color:rgba(52,211,153,.35);background:var(--ok-wash);color:#a7f3d0}
.chip-bad{border-color:rgba(244,63,94,.35);background:var(--no-wash);color:#fecdd3}
.chip-dim{opacity:.45;color:var(--muted)}
.protocol-tag{font:600 11px var(--mono);padding:2px 8px;border-radius:9999px;
  border:1px solid rgba(56,189,248,.3);background:rgba(56,189,248,.1);color:#7dd3fc}
```

### Flows

Prefer vertical HTML connectors (line + pill label + arrow). Use Mermaid for
dense import/dependency graphs only.

## Process rules

- **Traceability**: no invented boxes/edges; proposed dashed.
- **Provenance**: every view footed with derived-from + commit; hashes via
  live `git rev-parse` at generation time (analyzed repo when cross-repo).
- **View economy**: mental model + ≤3 supporting views.
- **Zoom**: ~30 visible boxes per view; group beyond that.
- **Invariant**: required on refactor pages.
- **Language**: match the user's requested language or the conversation language.
- **Fit**: SVG text stays inside its box; long paths/tokens (`code`,
  `.mod .path`, `.chip`) wrap via `overflow-wrap:anywhere`; the page never
  scrolls horizontally at common widths. Enforce by construction (short
  labels, box sized to text, wrap CSS above): spot-check three boxes and
  a phone-width resize before finishing.
- **One pass; direction change = clean rewrite; one knob at a time.**

## Pre-finish checklist

1. Parse-check HTML / inline JS (`new Function` on script bodies).
2. Mental-model graphic present (SVG map *or* Today|Target flow graph).
3. Legend covers every shape/stroke style used on diagrams.
4. Contrast: body text is `--ink` or `--soft`, not `--muted`.
5. No role-rainbow paints on modules.
6. Every edge endpoint resolves to a rendered id (or deliberate caption /
   band adjacency).
7. Provenance present; hashes live-read.
8. Spot-check 3 box paths against the repo.
9. Views within cap; refactor pages state the invariant.
10. Sticky TOC (if present) works; stacks at phone width; print stylesheet
    present when the page is long.
11. Requested language is consistent; the page renders with networking disabled.
12. **Fit holds**: every SVG `.title`/`.sub` sits inside its box (≥ 5u slack);
    `code` / `.mod .path` / `.chip` use `overflow-wrap:anywhere`; no horizontal
    page scroll when the viewport is narrowed to phone width. Spot-check at
    least three boxes against their rects.

## Reference markup (load-bearing scraps)

Offline document head:

```html
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
  :root { --sans: system-ui, sans-serif; --mono: ui-monospace, monospace; }
</style>
<!-- Inline the diagram SVG, styles, and interaction code below. -->
```

Glass hero + fact tiles:

```html
<header class="hero glass-card">
  <p class="eyebrow"><span aria-hidden="true">◇</span> Target architecture</p>
  <h1>One door to the stack</h1>
  <p class="lede">Short orientation. <strong>Key nouns</strong> emphasized.
    Paths as <code>engine.getStackConfig()</code>.</p>
  <dl class="facts">
    <div class="fact"><dt>Door</dt><dd><code>getStackConfig()</code></dd></div>
    <div class="fact"><dt>Verified</dt><dd><code>abc1234</code></dd></div>
  </dl>
</header>
```

```css
.hero{padding:28px;border-radius:24px}
.eyebrow{display:inline-flex;align-items:center;gap:8px;font:600 12px/1 var(--mono);
  letter-spacing:.08em;text-transform:uppercase;color:#34d399;padding:6px 12px;
  border-radius:999px;background:rgba(52,211,153,.1);border:1px solid rgba(52,211,153,.3)}
.hero h1{font:800 40px/1.1 var(--sans);letter-spacing:-.03em;margin:12px 0;color:#f8fafc}
.fact{background:rgba(0,0,0,.55);border:1px solid var(--line);border-radius:14px;padding:12px 14px}
.fact dt{font:700 11px/1 var(--mono);letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
```

Module card + layer band (neutral):

```html
<div class="layer">
  <div class="layer-head"><h3>Browser · src/web/</h3><span class="hint">contracts only</span></div>
  <div class="mods">
    <div class="mod" id="spa" title="src/web/App.tsx">
      <h4>App shell</h4><div class="path">App.tsx · main.tsx</div>
      <p class="cap">Three always-mounted tabs.</p>
    </div>
  </div>
</div>
```

```css
.layer{background:var(--surface);border:1px solid var(--line);padding:16px 18px}
.layer-head h3{font:700 12px/1 var(--mono);letter-spacing:.08em;text-transform:uppercase;color:#e2e8f0;margin:0}
.mod{background:var(--raised);border:1px solid var(--line);border-radius:12px;padding:10px 12px}
.mod h4{font:700 14.5px/1.25 var(--sans);margin:0 0 3px;color:var(--ink)}
.mod .path{font:500 12px/1.3 var(--mono);color:var(--muted);overflow-wrap:anywhere;word-break:break-word}
.mod .cap{margin:7px 0 0;font-size:13px;color:var(--soft);overflow-wrap:anywhere}
```

Rule verdicts:

```html
<div class="rule ok"><span class="mark">✓</span><div class="body">
  <strong><code>src/web/</code> → <code>contracts.ts</code> only</strong>
  <p>No database, filesystem, or capability imports in the browser.</p>
</div></div>
```

```css
.rule{display:flex;gap:12px;background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:12px 14px}
.rule.ok{border-left:3px solid var(--ok);background:var(--ok-wash);border-color:rgba(52,211,153,.28)}
.rule.no{border-left:3px solid var(--no);background:var(--no-wash);border-color:rgba(244,63,94,.28)}
.rule .mark{font:700 14px/1 var(--mono)}
.rule.ok .mark{color:var(--ok)} .rule.no .mark{color:var(--no)}
```

HTML flow connector:

```html
<div class="conn"><div class="conn-line"></div>
  <div class="conn-label">POST /api/resource/action</div>
  <div class="conn-line"></div><div class="conn-arrow"></div></div>
```

```css
.conn{display:flex;flex-direction:column;align-items:center;padding:.35rem 0}
.conn-line{width:2px;min-height:8px;background:var(--line-strong)}
.conn-label{font:600 11px/1.3 var(--mono);color:#7dd3fc;background:rgba(10,15,26,.95);
  border:1px solid rgba(56,189,248,.3);border-radius:9999px;padding:2px 12px;margin:3px 0}
.conn-arrow{border-left:5px solid transparent;border-right:5px solid transparent;border-top:6px solid var(--muted)}
.conn-good .conn-line{background:rgba(52,211,153,.55)}
.conn-good .conn-arrow{border-top-color:var(--ok)}
.conn-bad .conn-line{background:rgba(244,63,94,.55)}
.conn-bad .conn-arrow{border-top-color:var(--no)}
```

## Suggested invocation

- Map how the plugin system is structured. → subsystem: derive, mental
  model SVG, layers, project scope-folder page
- Show what this refactor branch actually moves. → diff, invariant,
  Today|Target panes
- Draw the target architecture we just discussed. → proposed (dashed) +
  verified real pieces
- Make this page shareable. → promote
- This diagram is too crowded. → zoom: group boxes, not smaller fonts

