diagram-design-editorial

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Diagram Design — Editorial HTML+SVG Diagrams

图表设计——专业级HTML+SVG图表

Skill by ara.so — Daily 2026 Skills collection.
Editorial-quality diagrams for blog posts and documentation. 13 types, self-contained HTML+SVG, no build step, no Mermaid, no shadows. Brand-matched in 60 seconds by reading your website.

ara.so开发的技能——2026日常技能合集。
适用于博客文章和文档的专业级图表。共13种类型,采用独立HTML+SVG格式,无需构建步骤,无需Mermaid,无阴影效果。只需读取你的网站,60秒即可匹配品牌样式。

Installation

安装

bash
git clone git@github.com:cathrynlavery/diagram-design.git ~/.claude/skills/diagram-design
bash
git clone git@github.com:cathrynlavery/diagram-design.git ~/.claude/skills/diagram-design

restart Claude Code — skill registers as
diagram-design

重启Claude Code——技能将注册为
diagram-design


Or symlink from another location:

```bash
git clone git@github.com:cathrynlavery/diagram-design.git ~/code/diagram-design
ln -s ~/code/diagram-design ~/.claude/skills/diagram-design
Browse all 13 types locally:
bash
open ~/.claude/skills/diagram-design/assets/index.html


或者从其他位置创建符号链接:

```bash
git clone git@github.com:cathrynlavery/diagram-design.git ~/code/diagram-design
ln -s ~/code/diagram-design ~/.claude/skills/diagram-design
在本地浏览全部13种图表类型:
bash
open ~/.claude/skills/diagram-design/assets/index.html

The 13 Diagram Types

13种图表类型

TypeUse when…
ArchitectureComponents + connections (services, APIs, infra)
FlowchartDecision logic, yes/no branches
SequenceMessages over time (OAuth, API calls, user flows)
State machineStates + transitions (order lifecycle, auth states)
ER / data modelEntities + fields + relationships
TimelineEvents on a horizontal or vertical axis
SwimlaneCross-functional flows (who does what, when)
QuadrantTwo-axis positioning (impact vs effort, risk vs value)
NestedHierarchy by containment (layers inside layers)
TreeParent → children (org chart, file tree, decision tree)
Layer stackStacked abstractions (OSI model, tech stack)
VennSet overlap (2–3 circles)
Pyramid / funnelRanked hierarchy or conversion drop-off
Selection rule: ask "would a reader learn more from this than from a well-written paragraph?" If no, don't draw. Default to deletion over addition.

类型适用场景…
Architecture(架构图)组件与连接(服务、API、基础设施)
Flowchart(流程图)决策逻辑、是非分支
Sequence(时序图)随时间传递的消息(OAuth、API调用、用户流程)
State machine(状态机图)状态与转换(订单生命周期、认证状态)
ER / data model(ER/数据模型图)实体、字段与关系
Timeline(时间线图)水平或垂直轴上的事件
Swimlane(泳道图)跨职能流程(谁在何时做什么)
Quadrant(四象限图)双轴定位(影响 vs 投入、风险 vs 价值)
Nested(嵌套图)包含式层级(层内分层)
Tree(树形图)父→子结构(组织结构图、文件树、决策树)
Layer stack(分层堆叠图)堆叠式抽象(OSI模型、技术栈)
Venn(维恩图)集合重叠(2-3个圆)
Pyramid / funnel(金字塔/漏斗图)排序层级或转化漏斗
选择规则: 自问“读者从图表中学到的内容是否比一段优秀的文字更多?”如果不是,就不要绘制图表。优先删除而非添加。

Quickstart

快速开始

undefined
undefined

In Claude Code — just describe what you need:

在Claude Code中——只需描述你的需求:

"Make me an architecture diagram: frontend, backend, Postgres, Redis cache." "I need a quadrant of Q2 projects by impact vs effort." "Give me a sequence diagram of the OAuth 2.0 handshake." "Draw a state machine for an e-commerce order: pending → paid → shipped → delivered." "Timeline of the Roman Empire's key turning points."

Claude picks the right type, builds HTML, saves the file. To use a template directly:

```bash
cp assets/template.html my-diagram.html        # minimal light
cp assets/template-full.html my-diagram.html   # editorial with summary cards

"帮我生成一张架构图:包含前端、后端、Postgres、Redis缓存。" "我需要一张按影响 vs 投入划分的Q2项目四象限图。" "给我一张OAuth 2.0握手流程的时序图。" "绘制一张电商订单的状态机图:pending → paid → shipped → delivered。" "绘制罗马帝国关键转折点的时间线图。"

Claude会选择合适的图表类型,生成HTML并保存文件。如需直接使用模板:

```bash
cp assets/template.html my-diagram.html        # 极简浅色模板
cp assets/template-full.html my-diagram.html   # 带摘要卡片的专业模板

Brand Onboarding (60 seconds)

品牌适配(60秒完成)

Without onboarding, diagrams render in neutral stone + rust (warm off-white paper, charcoal ink, rust-orange accent). Run onboarding to match your site:
"onboard diagram-design to https://yoursite.com"
Claude will:
  1. Fetch your homepage
  2. Extract dominant palette + font stack
  3. Map values to semantic roles:
    paper
    ,
    ink
    ,
    muted
    ,
    accent
    ,
    link
  4. Run WCAG AA contrast checks (auto-adjusts failures)
  5. Show a proposed diff → write tokens to
    references/style-guide.md
未进行品牌适配时,图表会采用中性石色+铁锈色(暖调米白纸底色、炭黑文字、铁锈橙强调色)。运行适配命令即可匹配你的网站样式:
"onboard diagram-design to https://yoursite.com"
Claude将执行以下操作:
  1. 获取你的主页
  2. 提取主色调与字体栈
  3. 将值映射到语义角色:
    paper
    (底色)、
    ink
    (主文字色)、
    muted
    (次要文字色)、
    accent
    (强调色)、
    link
    (链接色)
  4. 运行WCAG AA对比度检查(自动调整不达标项)
  5. 展示建议的差异→将标记写入
    references/style-guide.md

What gets extracted

提取内容对应关系

Detected from your siteBecomes
<body>
background
paper
token
Primary text color
ink
token
Secondary / caption text
muted
token
Cards or containers
paper-2
token
Most-used brand color (CTA, link, heading)
accent
token
<h1>
font family
title
font
<body>
font family
node-name
font
<code>
/
<pre>
font
sublabel
font
从网站检测到的元素对应为
<body>
背景色
paper
标记
主文字颜色
ink
标记
次要/说明文字颜色
muted
标记
卡片或容器样式
paper-2
标记
使用最频繁的品牌色(CTA、链接、标题)
accent
标记
<h1>
字体族
title
字体
<body>
字体族
node-name
字体
<code>
/
<pre>
字体
sublabel
字体

Manual token override

手动覆盖标记

Edit
references/style-guide.md
directly:
markdown
| Token      | Value     | Role                          |
|------------|-----------|-------------------------------|
| paper      | #F8F5F0   | diagram background            |
| ink        | #1A1A1A   | primary text, borders         |
| muted      | #6B6560   | secondary labels, grid lines  |
| paper-2    | #EEEAE4   | card fills, lane backgrounds  |
| accent     | #B5523A   | focal nodes, 1–2 per diagram  |
| accent-fg  | #FFFFFF   | text on accent-colored nodes  |
First-run gate: on first use in a new project, if
style-guide.md
is still at default, Claude pauses and asks: "Run onboarding, paste tokens manually, or proceed with default?"

直接编辑
references/style-guide.md
markdown
| 标记      || 角色                          |
|------------|-----------|-------------------------------|
| paper      | #F8F5F0   | 图表背景色                    |
| ink        | #1A1A1A   | 主文字、边框色                |
| muted      | #6B6560   | 次要标签、网格线颜色          |
| paper-2    | #EEEAE4   | 卡片填充、泳道背景色          |
| accent     | #B5523A   | 焦点节点,每张图表仅用1-2个  |
| accent-fg  | #FFFFFF   | 强调色节点上的文字颜色        |
首次运行提示: 在新项目中首次使用时,如果
style-guide.md
仍为默认值,Claude会暂停并询问:"运行品牌适配、手动粘贴标记,还是使用默认样式?"

Design System Rules

设计系统规则

Every diagram generated by this skill follows these non-negotiable constraints:
本技能生成的所有图表均遵循以下不可协商的约束:

Grid

网格规范

  • All coordinates, widths, gaps divisible by 4px — prevents the AI-generated jitter
  • No shadows anywhere
  • Max border-radius: 10px
  • Borders: 1px hairline only
  • 所有坐标、宽度、间距均为4px的倍数——避免AI生成的错位问题
  • 全程无阴影
  • 最大圆角半径:10px
  • 边框:仅使用1px细边框

Typography (three families, three roles)

排版规范(三种字体,三种角色)

Instrument Serif  → titles, italic editorial callouts
Geist Sans        → node names, labels (primary UI text)
Geist Mono        → technical sublabels (ports, URLs, field types, IDs)
Mono is for technical content specifically — not a blanket "dev aesthetic."
Instrument Serif  → 标题、斜体专业注释
Geist Sans        → 节点名称、标签(主要UI文字)
Geist Mono        → 技术子标签(端口、URL、字段类型、ID)
等宽字体仅用于技术内容——而非通用的"开发者风格"。

Color discipline

色彩规范

  • One accent color per diagram
  • Accent reserved for 1–2 focal nodes — the things the reader looks at first
  • Everything else:
    ink
    ,
    muted
    ,
    paper-2
  • Target visual density: 4/10 — ruthlessly sparse
  • 每张图表仅使用一种强调色
  • 强调色仅用于1-2个焦点节点——即读者最先关注的元素
  • 其他所有元素:使用
    ink
    muted
    paper-2
  • 目标视觉密度:4/10——尽可能简洁

Focal nodes (coral tint)

焦点节点(珊瑚色调)

html
<!-- Accent node — use sparingly, 1–2 per diagram -->
<rect width="160" height="48" rx="6" fill="var(--accent)"/>
<text fill="var(--accent-fg)" font-family="Geist, sans-serif" font-size="13">
  Primary Component
</text>

<!-- Standard node -->
<rect width="160" height="48" rx="6" fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
<text fill="var(--ink)" font-family="Geist, sans-serif" font-size="13">
  Secondary Component
</text>

html
<!-- 强调节点——谨慎使用,每张图表仅1-2个 -->
<rect width="160" height="48" rx="6" fill="var(--accent)"/>
<text fill="var(--accent-fg)" font-family="Geist, sans-serif" font-size="13">
  Primary Component
</text>

<!-- 标准节点 -->
<rect width="160" height="48" rx="6" fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
<text fill="var(--ink)" font-family="Geist, sans-serif" font-size="13">
  Secondary Component
</text>

Code Examples

代码示例

Architecture Diagram (minimal structure)

架构图(极简结构)

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <style>
    :root {
      --paper:    #F8F5F0;
      --ink:      #1A1A1A;
      --muted:    #6B6560;
      --paper-2:  #EEEAE4;
      --accent:   #B5523A;
      --accent-fg:#FFFFFF;
    }
    body { background: var(--paper); margin: 0; padding: 40px; }
    svg  { display: block; }
  </style>
</head>
<body>
<svg width="640" height="400" viewBox="0 0 640 400"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <!-- Background -->
  <rect width="640" height="400" fill="var(--paper)"/>

  <!-- Title -->
  <text x="32" y="40" font-size="15" font-weight="600" fill="var(--ink)">
    Application Architecture
  </text>

  <!-- Focal node: API Gateway (accent) -->
  <rect x="240" y="80" width="160" height="48" rx="6" fill="var(--accent)"/>
  <text x="320" y="100" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--accent-fg)">API Gateway</text>
  <text x="320" y="116" text-anchor="middle" font-size="10"
        fill="var(--accent-fg)" opacity="0.8">:443</text>

  <!-- Standard node: Frontend -->
  <rect x="60" y="196" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="140" y="216" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Frontend</text>
  <text x="140" y="232" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">Next.js</text>

  <!-- Standard node: Auth Service -->
  <rect x="420" y="196" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="500" y="216" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Auth Service</text>
  <text x="500" y="232" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">JWT / OAuth</text>

  <!-- Standard node: Database -->
  <rect x="240" y="312" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="320" y="332" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Postgres</text>
  <text x="320" y="348" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">:5432</text>

  <!-- Connections — 1px hairline, muted -->
  <line x1="320" y1="128" x2="140" y2="196"
        stroke="var(--muted)" stroke-width="1"/>
  <line x1="320" y1="128" x2="500" y2="196"
        stroke="var(--muted)" stroke-width="1"/>
  <line x1="320" y1="128" x2="320" y2="312"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Arrow markers -->
  <defs>
    <marker id="arrow" markerWidth="6" markerHeight="6"
            refX="5" refY="3" orient="auto">
      <path d="M0,0 L6,3 L0,6 Z" fill="var(--muted)"/>
    </marker>
  </defs>
</svg>
</body>
</html>
html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <style>
    :root {
      --paper:    #F8F5F0;
      --ink:      #1A1A1A;
      --muted:    #6B6560;
      --paper-2:  #EEEAE4;
      --accent:   #B5523A;
      --accent-fg:#FFFFFF;
    }
    body { background: var(--paper); margin: 0; padding: 40px; }
    svg  { display: block; }
  </style>
</head>
<body>
<svg width="640" height="400" viewBox="0 0 640 400"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <!-- Background -->
  <rect width="640" height="400" fill="var(--paper)"/>

  <!-- Title -->
  <text x="32" y="40" font-size="15" font-weight="600" fill="var(--ink)">
    Application Architecture
  </text>

  <!-- Focal node: API Gateway (accent) -->
  <rect x="240" y="80" width="160" height="48" rx="6" fill="var(--accent)"/>
  <text x="320" y="100" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--accent-fg)">API Gateway</text>
  <text x="320" y="116" text-anchor="middle" font-size="10"
        fill="var(--accent-fg)" opacity="0.8">:443</text>

  <!-- Standard node: Frontend -->
  <rect x="60" y="196" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="140" y="216" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Frontend</text>
  <text x="140" y="232" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">Next.js</text>

  <!-- Standard node: Auth Service -->
  <rect x="420" y="196" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="500" y="216" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Auth Service</text>
  <text x="500" y="232" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">JWT / OAuth</text>

  <!-- Standard node: Database -->
  <rect x="240" y="312" width="160" height="48" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="320" y="332" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Postgres</text>
  <text x="320" y="348" text-anchor="middle" font-size="10"
        font-family="'Geist Mono', monospace" fill="var(--muted)">:5432</text>

  <!-- Connections — 1px hairline, muted -->
  <line x1="320" y1="128" x2="140" y2="196"
        stroke="var(--muted)" stroke-width="1"/>
  <line x1="320" y1="128" x2="500" y2="196"
        stroke="var(--muted)" stroke-width="1"/>
  <line x1="320" y1="128" x2="320" y2="312"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Arrow markers -->
  <defs>
    <marker id="arrow" markerWidth="6" markerHeight="6"
            refX="5" refY="3" orient="auto">
      <path d="M0,0 L6,3 L0,6 Z" fill="var(--muted)"/>
    </marker>
  </defs>
</svg>
</body>
</html>

Quadrant Diagram

四象限图

html
<svg width="520" height="520" viewBox="0 0 520 520"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <rect width="520" height="520" fill="var(--paper)"/>

  <!-- Axes -->
  <line x1="64" y1="456" x2="456" y2="456"
        stroke="var(--ink)" stroke-width="1"/>  <!-- x-axis -->
  <line x1="64" y1="64"  x2="64"  y2="456"
        stroke="var(--ink)" stroke-width="1"/>  <!-- y-axis -->

  <!-- Quadrant dividers -->
  <line x1="260" y1="64" x2="260" y2="456"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="64" y1="260" x2="456" y2="260"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Axis labels -->
  <text x="260" y="488" text-anchor="middle" font-size="11"
        fill="var(--muted)">← Low Effort · High Effort →</text>
  <text x="20" y="260" text-anchor="middle" font-size="11"
        fill="var(--muted)" transform="rotate(-90, 20, 260)">
    ← Low Impact · High Impact →
  </text>

  <!-- Quadrant labels -->
  <text x="162" y="88" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">QUICK WINS</text>
  <text x="358" y="88" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">MAJOR PROJECTS</text>
  <text x="162" y="448" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">FILL-INS</text>
  <text x="358" y="448" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">THANKLESS TASKS</text>

  <!-- Focal item (accent) -->
  <circle cx="148" cy="148" r="28" fill="var(--accent)" opacity="0.9"/>
  <text x="148" y="144" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--accent-fg)">Auth</text>
  <text x="148" y="158" text-anchor="middle" font-size="9"
        fill="var(--accent-fg)" opacity="0.85">redesign</text>

  <!-- Standard items -->
  <circle cx="200" cy="200" r="22" fill="var(--paper-2)"
          stroke="var(--ink)" stroke-width="1"/>
  <text x="200" y="196" text-anchor="middle" font-size="9"
        fill="var(--ink)">Dark</text>
  <text x="200" y="208" text-anchor="middle" font-size="9"
        fill="var(--ink)">mode</text>

  <circle cx="340" cy="160" r="26" fill="var(--paper-2)"
          stroke="var(--ink)" stroke-width="1"/>
  <text x="340" y="156" text-anchor="middle" font-size="9"
        fill="var(--ink)">API v2</text>
  <text x="340" y="168" text-anchor="middle" font-size="9"
        fill="var(--ink)">migration</text>
</svg>
html
<svg width="520" height="520" viewBox="0 0 520 520"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <rect width="520" height="520" fill="var(--paper)"/>

  <!-- Axes -->
  <line x1="64" y1="456" x2="456" y2="456"
        stroke="var(--ink)" stroke-width="1"/>  <!-- x-axis -->
  <line x1="64" y1="64"  x2="64"  y2="456"
        stroke="var(--ink)" stroke-width="1"/>  <!-- y-axis -->

  <!-- Quadrant dividers -->
  <line x1="260" y1="64" x2="260" y2="456"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="64" y1="260" x2="456" y2="260"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Axis labels -->
  <text x="260" y="488" text-anchor="middle" font-size="11"
        fill="var(--muted)">← Low Effort · High Effort →</text>
  <text x="20" y="260" text-anchor="middle" font-size="11"
        fill="var(--muted)" transform="rotate(-90, 20, 260)">
    ← Low Impact · High Impact →
  </text>

  <!-- Quadrant labels -->
  <text x="162" y="88" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">QUICK WINS</text>
  <text x="358" y="88" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">MAJOR PROJECTS</text>
  <text x="162" y="448" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">FILL-INS</text>
  <text x="358" y="448" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--muted)" letter-spacing="0.05em">THANKLESS TASKS</text>

  <!-- Focal item (accent) -->
  <circle cx="148" cy="148" r="28" fill="var(--accent)" opacity="0.9"/>
  <text x="148" y="144" text-anchor="middle" font-size="10"
        font-weight="600" fill="var(--accent-fg)">Auth</text>
  <text x="148" y="158" text-anchor="middle" font-size="9"
        fill="var(--accent-fg)" opacity="0.85">redesign</text>

  <!-- Standard items -->
  <circle cx="200" cy="200" r="22" fill="var(--paper-2)"
          stroke="var(--ink)" stroke-width="1"/>
  <text x="200" y="196" text-anchor="middle" font-size="9"
        fill="var(--ink)">Dark</text>
  <text x="200" y="208" text-anchor="middle" font-size="9"
        fill="var(--ink)">mode</text>

  <circle cx="340" cy="160" r="26" fill="var(--paper-2)"
          stroke="var(--ink)" stroke-width="1"/>
  <text x="340" y="156" text-anchor="middle" font-size="9"
        fill="var(--ink)">API v2</text>
  <text x="340" y="168" text-anchor="middle" font-size="9"
        fill="var(--ink)">migration</text>
</svg>

Sequence Diagram

时序图

html
<svg width="600" height="360" viewBox="0 0 600 360"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <rect width="600" height="360" fill="var(--paper)"/>

  <!-- Actor boxes -->
  <rect x="40"  y="40" width="100" height="36" rx="6"
        fill="var(--accent)"/>
  <text x="90"  y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--accent-fg)">Browser</text>

  <rect x="248" y="40" width="100" height="36" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="298" y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Auth Server</text>

  <rect x="456" y="40" width="100" height="36" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="506" y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">API</text>

  <!-- Lifelines -->
  <line x1="90"  y1="76" x2="90"  y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="298" y1="76" x2="298" y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="506" y1="76" x2="506" y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Messages -->
  <defs>
    <marker id="seq-arrow" markerWidth="6" markerHeight="6"
            refX="5" refY="3" orient="auto">
      <path d="M0,0 L6,3 L0,6 Z" fill="var(--ink)"/>
    </marker>
  </defs>

  <!-- 1: redirect to auth -->
  <line x1="90" y1="120" x2="292" y2="120"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="114" text-anchor="middle" font-size="10"
        fill="var(--muted)">GET /authorize</text>

  <!-- 2: login page -->
  <line x1="298" y1="152" x2="96" y2="152"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="146" text-anchor="middle" font-size="10"
        fill="var(--muted)">302 → login page</text>

  <!-- 3: credentials -->
  <line x1="90" y1="188" x2="292" y2="188"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="182" text-anchor="middle" font-size="10"
        fill="var(--muted)">POST credentials</text>

  <!-- 4: code -->
  <line x1="298" y1="220" x2="96" y2="220"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="214" text-anchor="middle" font-size="10"
        fill="var(--muted)">302 + code</text>

  <!-- 5: exchange code -->
  <line x1="90" y1="260" x2="500" y2="260"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="295" y="254" text-anchor="middle" font-size="10"
        fill="var(--muted)">GET /resource + Bearer token</text>

  <!-- 6: response -->
  <line x1="506" y1="292" x2="96" y2="292"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="295" y="286" text-anchor="middle" font-size="10"
        fill="var(--muted)">200 OK + data</text>
</svg>

html
<svg width="600" height="360" viewBox="0 0 600 360"
     xmlns="http://www.w3.org/2000/svg"
     font-family="Geist, system-ui, sans-serif">

  <rect width="600" height="360" fill="var(--paper)"/>

  <!-- Actor boxes -->
  <rect x="40"  y="40" width="100" height="36" rx="6"
        fill="var(--accent)"/>
  <text x="90"  y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--accent-fg)">Browser</text>

  <rect x="248" y="40" width="100" height="36" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="298" y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">Auth Server</text>

  <rect x="456" y="40" width="100" height="36" rx="6"
        fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1"/>
  <text x="506" y="63" text-anchor="middle" font-size="12"
        font-weight="600" fill="var(--ink)">API</text>

  <!-- Lifelines -->
  <line x1="90"  y1="76" x2="90"  y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="298" y1="76" x2="298" y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>
  <line x1="506" y1="76" x2="506" y2="340"
        stroke="var(--muted)" stroke-width="1" stroke-dasharray="4 3"/>

  <!-- Messages -->
  <defs>
    <marker id="seq-arrow" markerWidth="6" markerHeight="6"
            refX="5" refY="3" orient="auto">
      <path d="M0,0 L6,3 L0,6 Z" fill="var(--ink)"/>
    </marker>
  </defs>

  <!-- 1: redirect to auth -->
  <line x1="90" y1="120" x2="292" y2="120"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="114" text-anchor="middle" font-size="10"
        fill="var(--muted)">GET /authorize</text>

  <!-- 2: login page -->
  <line x1="298" y1="152" x2="96" y2="152"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="146" text-anchor="middle" font-size="10"
        fill="var(--muted)">302 → login page</text>

  <!-- 3: credentials -->
  <line x1="90" y1="188" x2="292" y2="188"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="182" text-anchor="middle" font-size="10"
        fill="var(--muted)">POST credentials</text>

  <!-- 4: code -->
  <line x1="298" y1="220" x2="96" y2="220"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="194" y="214" text-anchor="middle" font-size="10"
        fill="var(--muted)">302 + code</text>

  <!-- 5: exchange code -->
  <line x1="90" y1="260" x2="500" y2="260"
        stroke="var(--ink)" stroke-width="1"
        marker-end="url(#seq-arrow)"/>
  <text x="295" y="254" text-anchor="middle" font-size="10"
        fill="var(--muted)">GET /resource + Bearer token</text>

  <!-- 6: response -->
  <line x1="506" y1="292" x2="96" y2="292"
        stroke="var(--ink)" stroke-width="1" stroke-dasharray="4 3"
        marker-end="url(#seq-arrow)"/>
  <text x="295" y="286" text-anchor="middle" font-size="10"
        fill="var(--muted)">200 OK + data</text>
</svg>

Primitives

基础元素

Annotation Callout

注释标注

Italic Instrument Serif + dashed Bézier leader for editorial asides in diagram margins:
html
<!-- Editorial annotation callout -->
<defs>
  <style>
    .callout-text {
      font-family: 'Instrument Serif', Georgia, serif;
      font-style: italic;
      font-size: 12px;
      fill: var(--muted);
    }
  </style>
</defs>

<!-- Bézier leader line (dashed, 1px) -->
<path d="M 180,200 C 200,180 220,160 260,148"
      stroke="var(--muted)" stroke-width="1"
      stroke-dasharray="3 3" fill="none"/>

<!-- Callout text — sits in margin -->
<text x="80" y="204" class="callout-text">only runs on cold start</text>
使用斜体Instrument Serif字体+虚线贝塞尔引导线,用于图表边缘的专业注释:
html
<!-- Editorial annotation callout -->
<defs>
  <style>
    .callout-text {
      font-family: 'Instrument Serif', Georgia, serif;
      font-style: italic;
      font-size: 12px;
      fill: var(--muted);
    }
  </style>
</defs>

<!-- Bézier leader line (dashed, 1px) -->
<path d="M 180,200 C 200,180 220,160 260,148"
      stroke="var(--muted)" stroke-width="1"
      stroke-dasharray="3 3" fill="none"/>

<!-- Callout text — sits in margin -->
<text x="80" y="204" class="callout-text">only runs on cold start</text>

Sketchy Filter (hand-drawn variant)

手绘风格滤镜

For essays and informal posts — not technical docs:
html
<defs>
  <filter id="sketchy" x="-5%" y="-5%" width="110%" height="110%">
    <feTurbulence type="fractalNoise" baseFrequency="0.04"
                  numOctaves="3" seed="2" result="noise"/>
    <feDisplacementMap in="SourceGraphic" in2="noise"
                       scale="2.5" xChannelSelector="R"
                       yChannelSelector="G"/>
  </filter>
</defs>

<!-- Apply to any element -->
<rect x="100" y="100" width="160" height="48" rx="6"
      fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1.5"
      filter="url(#sketchy)"/>

适用于随笔和非正式文章——不适用于技术文档:
html
<defs>
  <filter id="sketchy" x="-5%" y="-5%" width="110%" height="110%">
    <feTurbulence type="fractalNoise" baseFrequency="0.04"
                  numOctaves="3" seed="2" result="noise"/>
    <feDisplacementMap in="SourceGraphic" in2="noise"
                       scale="2.5" xChannelSelector="R"
                       yChannelSelector="G"/>
  </filter>
</defs>

<!-- Apply to any element -->
<rect x="100" y="100" width="160" height="48" rx="6"
      fill="var(--paper-2)" stroke="var(--ink)" stroke-width="1.5"
      filter="url(#sketchy)"/>

File Structure

文件结构

diagram-design/
├── SKILL.md                         # type selection guide, design rules
├── references/
│   ├── style-guide.md               # color + font tokens (edit for your brand)
│   ├── onboarding.md                # URL-to-tokens extraction spec
│   ├── type-architecture.md
│   ├── type-flowchart.md
│   ├── type-sequence.md
│   ├── type-state.md
│   ├── type-er.md
│   ├── type-timeline.md
│   ├── type-swimlane.md
│   ├── type-quadrant.md
│   ├── type-nested.md
│   ├── type-tree.md
│   ├── type-layers.md
│   ├── type-venn.md
│   ├── type-pyramid.md
│   ├── primitive-annotation.md
│   └── primitive-sketchy.md
├── assets/
│   ├── index.html                   # live gallery, all 13 types, 3 variants each
│   ├── template.html                # minimal light scaffold
│   ├── template-full.html           # editorial with summary cards
│   └── example-<type>.html          # 39 files: 3 variants × 13 types
└── docs/screenshots/
Context loading (what Claude reads per request):
RequestFiles loaded
Any specific type
SKILL.md
+
references/type-<name>.md
Onboarding
SKILL.md
+
onboarding.md
+
style-guide.md
Add annotation
SKILL.md
+
primitive-annotation.md
Hand-drawn variant
SKILL.md
+
primitive-sketchy.md
Only the relevant reference file loads — keeps context tight regardless of how many types exist.

diagram-design/
├── SKILL.md                         # 类型选择指南、设计规则
├── references/
│   ├── style-guide.md               # 颜色+字体标记(可编辑以适配你的品牌)
│   ├── onboarding.md                # URL到标记的提取规范
│   ├── type-architecture.md
│   ├── type-flowchart.md
│   ├── type-sequence.md
│   ├── type-state.md
│   ├── type-er.md
│   ├── type-timeline.md
│   ├── type-swimlane.md
│   ├── type-quadrant.md
│   ├── type-nested.md
│   ├── type-tree.md
│   ├── type-layers.md
│   ├── type-venn.md
│   ├── type-pyramid.md
│   ├── primitive-annotation.md
│   └── primitive-sketchy.md
├── assets/
│   ├── index.html                   # 在线画廊,包含全部13种类型,每种3种变体
│   ├── template.html                # 极简浅色脚手架
│   ├── template-full.html           # 带摘要卡片的专业模板
│   └── example-<type>.html          # 39个文件:13种类型×3种变体
└── docs/screenshots/
上下文加载(Claude每次请求读取的文件):
请求类型加载的文件
指定特定类型
SKILL.md
+
references/type-<name>.md
品牌适配
SKILL.md
+
onboarding.md
+
style-guide.md
添加注释
SKILL.md
+
primitive-annotation.md
手绘风格变体
SKILL.md
+
primitive-sketchy.md
仅加载相关参考文件——无论有多少种类型,都能保持上下文简洁。

Common Patterns

常见模式

Choosing the right type

选择合适的图表类型

undefined
undefined

Decision logic with yes/no branches → flowchart

带是非分支的决策逻辑→流程图

"Should I use X?" branching → flowchart
"是否应该使用X?"分支→流程图

Time-ordered messages between actors → sequence

角色间按时间顺序传递的消息→时序图

OAuth, webhooks, API calls → sequence
OAuth、webhooks、API调用→时序图

Lifecycle with transitions → state machine

带转换的生命周期→状态机图

Order status, auth state, connection state → state machine
订单状态、认证状态、连接状态→状态机图

Two-axis comparison → quadrant

双轴对比→四象限图

Impact vs effort, risk vs value → quadrant
影响 vs 投入、风险 vs 价值→四象限图

Ranked importance → pyramid

重要性排序→金字塔图

Priority tiers, conversion funnel → pyramid
优先级层级、转化漏斗→金字塔图

System components and how they connect → architecture

系统组件及其连接方式→架构图

Services, databases, queues → architecture
undefined
服务、数据库、队列→架构图
undefined

Controlling focal emphasis

控制焦点强调

undefined
undefined

Accent = 1–2 nodes only — the main point of the diagram

强调色仅用于1-2个节点——图表的核心要点

If everything is accent, nothing is accent

如果所有节点都用强调色,就没有焦点了

Wrong: 5 accent nodes in a 7-node diagram

错误:7个节点的图表中使用5个强调节点

Right: 1 accent node (the bottleneck / the thing that matters)

正确:仅1个强调节点(瓶颈/关键元素)

undefined
undefined

Density calibration

密度校准

undefined
undefined

Target: 4/10 density

目标密度:4/10

5 nodes is usually enough

通常5个节点足够

8 nodes is usually too many

通常8个节点过多

12 nodes → split into two diagrams or use layers/nested

12个节点→拆分为两个图表或使用嵌套/分层类型

Eliminate any node the reader doesn't need to understand the point

删除任何读者理解核心要点不需要的节点


---

---

Troubleshooting

故障排除

Diagrams look generic / AI-generated
  • Check all coordinates are divisible by 4 — misaligned grids are the tell
  • Reduce node count; every node must earn its place
  • Confirm only 1–2 nodes use
    var(--accent)
    ; the rest should be
    var(--paper-2)
Colors don't match my site
  • Run onboarding:
    "onboard diagram-design to https://yoursite.com"
  • Or edit
    references/style-guide.md
    directly with your hex values
Fonts not loading
  • Diagrams use system fallbacks by default — Geist and Instrument Serif only load if available
  • Add Google Fonts or Bunny Fonts link in
    <head>
    for exact rendering:
html
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=instrument-serif:400,400i|geist:400,600&display=swap"
      rel="stylesheet">
WCAG contrast failing on my brand colors
  • Onboarding runs contrast checks automatically and proposes adjustments
  • Manual fix: darken
    ink
    or lighten
    paper
    until ratio ≥ 4.5:1 at 12px
Diagram too dense / cluttered
  • Delete nodes until it hurts, then delete one more
  • Split into two diagrams: overview + detail
  • Use a nested or layers type if you need to show hierarchy without individual connections
Wrong type chosen
  • Override explicitly:
    "Make this a swimlane, not a flowchart — rows for Design, Eng, PM"

图表看起来通用/AI生成痕迹明显
  • 检查所有坐标是否都是4的倍数——错位网格是明显特征
  • 减少节点数量;每个节点都必须有存在的意义
  • 确认仅1-2个节点使用
    var(--accent)
    ;其余节点应使用
    var(--paper-2)
颜色与网站不匹配
  • 运行品牌适配:
    "onboard diagram-design to https://yoursite.com"
  • 或直接编辑
    references/style-guide.md
    ,填入你的十六进制颜色值
字体未加载
  • 图表默认使用系统 fallback 字体——仅当Geist和Instrument Serif可用时才会加载
  • <head>
    中添加Google Fonts或Bunny Fonts链接,以实现精确渲染:
html
<link rel="preconnect" href="https://fonts.bunny.net">
<link href="https://fonts.bunny.net/css?family=instrument-serif:400,400i|geist:400,600&display=swap"
      rel="stylesheet">
品牌颜色未通过WCAG对比度检查
  • 品牌适配会自动运行对比度检查并提出调整建议
  • 手动修复:加深
    ink
    颜色或减淡
    paper
    颜色,直到12px文字的对比度≥4.5:1
图表过于密集/杂乱
  • 删除节点直到难以割舍,然后再删除一个
  • 拆分为两个图表:概览+细节
  • 如果需要展示层级但无需单独连接,使用嵌套或分层类型
选择了错误的图表类型
  • 显式覆盖:
    "请生成泳道图而非流程图——行对应设计、开发、产品经理"

When NOT to use this skill

不适用场景

  • Quick ASCII/unicode diagrams for terminal or tweets → use wiretext
  • Before/after comparisons → use a table
  • Simple lists → use bullets
  • Single-shape "diagrams" (one box, one label) → write the sentence instead
  • 用于终端或推文的快速ASCII/unicode图表→使用wiretext
  • 前后对比→使用表格
  • 简单列表→使用项目符号
  • 单一形状的“图表”(一个框、一个标签)→直接用文字描述