From Accessibility Audit
Generates a fully self-contained interactive HTML architecture diagram for a software project. Use this skill whenever the user asks to "visualize the architecture", "create a diagram of the project", "make an interactive map of the codebase", "diagram the system", "show how the pieces fit together", or any request to produce an explorable/interactive visualization of a project's components, services, agents, APIs, or data flows. Also triggers on "zoom into the architecture", "interactive diagram", "clickable diagram", "architecture overview with details", "show me the tech stack visually", or "I want to explore the codebase structure". Always use this skill when the user wants something richer than a static diagram — especially if they mention zoom, click-through, detail panels, or multiple layers of information.
How this skill is triggered — by the user, by Claude, or both
Slash command
/accessibility-audit:interactive-diagramThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill produces a fully self-contained, interactive HTML file that lets users explore a software project's architecture through pan/zoom navigation, color-coded zones, and clickable nodes with rich detail panels.
This skill produces a fully self-contained, interactive HTML file that lets users explore a software project's architecture through pan/zoom navigation, color-coded zones, and clickable nodes with rich detail panels.
Before reading any files or building the diagram, ask the user these three questions in a single message. Use the AskUserQuestion tool with multiple choice options where applicable.
Start with the key files that describe the project's architecture. Always read:
CLAUDE.md or README.md at the repo root — these are gold; they often describe every module, environment variable, and pattern.env.example or documented environment variablesUse Glob to discover files if you're unsure of the structure:
CLAUDE.md, README.md, backend/src/**/*.controller.ts, frontend/src/App.tsx,
frontend/src/pages/*.tsx, backend/src/**/*.module.ts
Read selectively — you need enough to understand the system's shape, not every line of every file.
After reading, mentally map the project into 3–6 logical zones. Common patterns:
Within each zone, identify nodes: discrete components, endpoints, agents, or services. A node is anything a developer or architect would want to understand individually. Aim for 20–60 nodes depending on scope.
For each node capture:
component, service, agent, endpoint, store, externalactive, wip, disabled, or missingImportant: flag incomplete configurations. When reading project files, watch for features that are referenced in one place but not wired up in another — for example, an agent card in the frontend UI that has no corresponding entry in the backend type union or workflow ID map. Mark these with status: "missing" and include a ⚠ indicator in the diagram. This surfaces real gaps to the team and is one of the highest-value things the diagram can communicate.
Map the connections between nodes. For each edge:
solid for primary flows, dashed for optional/async/disabled flowstrue for edges that cross zones in a way that would visually tangle (route them as arcs above the canvas)Use the template below as the structural foundation. Fill in the ZONES, NODES, EDGES, NODE_DETAILS, and AGENT_DETAILS data structures.
Key implementation details:
Zones are rendered as labeled background rectangles. Lay them out left-to-right or in a logical spatial arrangement (client → frontend → backend → external). Calculate zone widths proportional to node count.
const ZONES = [
{ id: 'frontend', label: 'Frontend', color: '#3B82F6', x: 20, y: 60, w: 300, h: 520 },
{ id: 'backend', label: 'Backend', color: '#10B981', x: 340, y: 60, w: 300, h: 520 },
// ...
];
Use a NODE_STYLES map keyed by type to assign fill, stroke, and text colors. In dark mode these are set via D3 .attr() as presentation attributes; in light mode they're overridden by CSS class rules (.ntype-{type} .node-bg { fill: ...; stroke: ...; }). This lets CSS handle theme switching without a full re-render.
const NODE_STYLES = {
component: { fill: '#1e3a5f', stroke: '#3B82F6', textColor: '#93c5fd' },
agent: { fill: '#2d1b69', stroke: '#8B5CF6', textColor: '#c4b5fd' },
endpoint: { fill: '#1a3a2a', stroke: '#10B981', textColor: '#6ee7b7' },
store: { fill: '#2d1f00', stroke: '#F59E0B', textColor: '#fcd34d' },
external: { fill: '#1e1a2e', stroke: '#6366F1', textColor: '#a5b4fc' },
service: { fill: '#1a2a1a', stroke: '#22C55E', textColor: '#86efac' },
};
The theme is controlled by data-theme on <html>. CSS custom properties handle backgrounds, text, and panel colors. SVG presentation attributes (set by D3) are overridden by CSS class selectors for node fills and zone fills in light mode.
Arrow marker colors require special handling — CSS can't easily target SVG <defs>. Store D3 selection references to each marker's <path> and update fill in JavaScript when the theme changes:
const markerPaths = {};
function updateMarkerColors() {
const LIGHT_EDGE_COLORS = { '#3B82F6': '#2563eb', '#10B981': '#059669', ... };
Object.entries(markerPaths).forEach(([origColor, sel]) => {
const col = currentTheme === 'light' ? (LIGHT_EDGE_COLORS[origColor] || origColor) : origColor;
sel.attr('fill', col);
});
}
.node-group .node-bg { transition: filter 0.12s, stroke-width 0.12s; }
.node-group:hover .node-bg { filter: brightness(1.18); stroke-width: 2.5px; }
The right-side panel renders NODE_DETAILS on click. Structure it with sections: Overview, Responsibilities (if present), Code Snippet (collapsible <pre> block), Examples, Tags. For agents specifically, render AGENT_DETAILS with example prompts and workflow status.
Agent detail panels must include example prompts — 2–4 concrete example questions a user would type to that agent. This is the most useful thing the panel can show for AI agents.
Status indicators: use colored dots — green for active, yellow for wip, red for disabled, orange/⚠ for missing.
const zoom = d3.zoom()
.scaleExtent([0.25, 3])
.on('zoom', (event) => { mainGroup.attr('transform', event.transform); });
svg.call(zoom);
// Reset on double-click
svg.on('dblclick.zoom', () => {
svg.transition().duration(500).call(zoom.transform, d3.zoomIdentity);
});
Before saving, run a quick internal consistency check:
details propertySave the file to the workspace folder:
/sessions/{session-id}/mnt/{workspace-name}/{project-name}-architecture.html
Provide a computer:// link so the user can open it directly. The file should be entirely self-contained — no separate CSS/JS files needed.
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="UTF-8">
<title>{Project Name} Architecture</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js"></script>
<style>
/* CSS custom properties for theming */
:root[data-theme="dark"] { --bg: #080d1a; --panel-bg: #0f172a; --text: #e2e8f0; ... }
:root[data-theme="light"] { --bg: #eef2f7; --panel-bg: #ffffff; --text: #1e293b; ... }
/* Light mode SVG overrides (higher specificity than D3 .attr() presentation attributes) */
[data-theme="light"] .ntype-component .node-bg { fill: #eff6ff; stroke: #2563eb; }
[data-theme="light"] .zone-frontend .zone-bg { fill: rgba(59,130,246,0.07); stroke: rgba(59,130,246,0.35); }
/* Hover effects (CSS only) */
.node-group .node-bg { transition: filter 0.12s, stroke-width 0.12s; }
.node-group:hover .node-bg { filter: brightness(1.18); stroke-width: 2.5px; }
</style>
</head>
<body>
<div id="header">...</div>
<div id="main">
<div id="canvas-wrapper">
<svg id="main-svg">
<defs><!-- arrow markers --></defs>
<g id="main-group"><!-- zones, edges, nodes rendered by D3 --></g>
</svg>
<div id="toolbar"><!-- zoom/reset/theme buttons --></div>
</div>
<div id="detail-panel"><!-- node details rendered on click --></div>
</div>
<script>
// Data: ZONES, NODES, EDGES, NODE_DETAILS, AGENT_DETAILS
// Theme: init from localStorage / prefers-color-scheme
// D3: render zones → edges → nodes
// Interactions: click nodes, zoom/pan, theme toggle
</script>
</body>
</html>
status: "missing" with ⚠Over-top edges: When an edge would draw directly through an intermediate zone (e.g., frontend → external AI API, crossing the backend zone visually), route it with a cubic Bezier that arcs above the canvas top. Use a flag like overTop: true and compute the path as M${sx},${sy} C${sx},-35 ${dx},-35 ${dx},${dy}.
SVG defs and CSS: Arrow marker fills can't be styled purely with CSS. Store D3 path element references and imperatively update them in your updateMarkerColors() function when the theme changes.
Node label truncation: For long node names, either wrap text or truncate with ellipsis. SVG text elements don't word-wrap natively — use tspan elements or truncate to ~20 chars with a tooltip showing the full name.
Zone sizing: Don't hardcode pixel positions for zones if possible. Calculate them based on the number of nodes in each zone, with a minimum height. Nodes should be positioned in a grid within their zone with consistent margins.
Endpoint granularity: When asked for full technical depth, represent individual API endpoints as their own nodes (not a single "Controller" node). Each endpoint node should show its HTTP method, path, and brief description. This is the difference between a diagram that's actually useful for onboarding vs. one that just shows high-level boxes.
Always check for agents/features referenced in the frontend but missing from the backend type union.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub adamj/productdesign-skills --plugin productdesign-skills