CommunityImagegithub.com

xingcanlee/wisp-diagram

Draw Wisp-style concept diagrams, architecture diagrams, model structure diagrams, and algorithm diagrams (self-attention, Transformer, matrix multiplication, KV cache, MoE, RAG, training loops, etc.) for blogs and technical documentation. Use this when you or an Agent need to create diagrams, generate .excalidraw / .drawio source files, export portable SVG/PNG, or mention excalidraw, drawio, draw.io, Wisp-style diagrams, semantic colors (Q/K/V), or diagram palettes. Not suitable for data charts (line charts, bar charts, etc.).

What is wisp-diagram?

The wisp-diagram skill is a self-contained, portable diagramming toolkit designed for creating stylistically consistent, themeable, and portable diagrams for Wisp-based sites, technical blogs, and documentation. It supports three diagramming tools: Excalidraw (for hand-drawn-style concept diagrams), draw.io (for precisely aligned model architecture diagrams), and Mermaid (for structured flowcharts and sequence diagrams). The skill enforces a strict color palette defined in `palette.json`, which maps semantic names like `q`, `k`, `v`, `weight`, and `activation` to light and dark color tokens; during build, light fills are automatically converted to CSS variables that switch between light and dark themes. The workflow includes generating skeleton JSON files, linting with automatic color snapping, building `.wisp.svg` output files, and exporting PNG previews. Caching of frontend assets (Excalidraw bundle, draw.io viewer, fonts) enables offline use after a warm-up step. The skill is implemented in Python with the `uv` runtime and requires no npm or pip install for end users, making it easy to drop into any project's `.claude/skills/` directory.

Works with✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/xingcanlee/astro-wisp/tree/HEAD/skills/wisp-diagram

Installed? Explore more Image skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Preview

From the skill README

Self-Attention: Q scores against K, then weighted sum of V
Residual structure of Transformer Block
Self-attention computation flow

Documentation

wisp-diagram: Produce Wisp-Style Diagrams

Goal: Produce stylistically consistent, themeable, portable diagrams. Source files (.excalidraw / .drawio) + generated *.wisp.svg: the same SVG follows the site theme when inlined in a Wisp site, and follows system light/dark when used as an <img> in GitHub README / other blogs.

This skill directory is self-contained and can be copied as a whole to any project (~/.claude/skills/ or <project>/.claude/skills/). The scripts are Python, run with uv: the entry point scripts/wisp_diagram.py declares dependencies (playwright, fonttools) using PEP 723, and uv run will automatically create an isolated environment — no npm / pip install needed.

SKILL.md
palette.json          Palette (the only source of colors)
reference/           style-guide.md  excalidraw-skeleton.md  drawio-cheatsheet.md  ml-patterns.md
assets/              wisp.excalidrawlib  wisp-drawio-library.xml  drawio-config.json  drawio-colors.txt
scripts/             wisp_diagram.py (unified entry point)  wisp_diagram_lib/ (implementation)  tests/ (pytest)

One-Time Setup

The commands below are run from the project root, and $W represents the entry script of the skill (adjust the path according to the actual location of the skill):

W="uv run skills/wisp-diagram/scripts/wisp_diagram.py"   # e.g. .claude/skills/wisp-diagram/... or ~/.claude/skills/wisp-diagram/...
uv run --with playwright==1.64.1 playwright install chromium   # Headless browser for export (skip if already installed)
$W probe                                                       # Check if Chromium, Excalidraw, draw.io export methods (cli / docker / browser) are available

First run downloads and caches (works offline afterward):

ContentSourceSize
Python dependencies: playwright 1.64.1, fonttoolsPyPI (managed by uv, stored in uv's own cache)≈ 55 MB
Chromium (only if not installed)playwright install chromium, stored in ~/.cache/ms-playwright/hundreds of MB
@excalidraw/excalidraw 0.18.1 and its dependencies (≈110 ES modules)jsDelivr, pinned versions≈ 1.6 MB
svgo 4.1.0 browser build (SVG optimization, runs in Chromium)jsDelivr0.8 MB
Fonts: Excalifont, Inter 5.3.0, Noto Sans SC 5.3.1 (sharded by unicode-range, downloads only needed shards)jsDelivrAll ≈ 4.5 MB
draw.io viewer (only for browser export method)viewer.diagrams.net≈ 4.7 MB

Except for Python dependencies and Chromium, the cache is stored in ~/.cache/wisp-diagram/ (can be changed with WISP_DIAGRAM_CACHE). Use $W cache status to view, and $W cache clear to clear.

Offline usage: Run $W cache warm once on a connected network (downloads all frontend resources listed above, ≈ 11 MB), then set WISP_DIAGRAM_OFFLINE=1 to work completely offline; if the cache is missing files, it will report an error and suggest warming up, rather than silently going online. You can also use WISP_EXCALIDRAW_BUNDLE=<local JS> to specify your own Excalidraw build (must define window.__wisp as an IIFE, or export functions like exportToSvg as an ES module), and WISP_DRAWIO_VIEWER=<local file> to specify a local draw.io viewer.

draw.io export falls back automatically in the order: cli → docker → browser. new, build, and export all require Chromium (Excalidraw export and svgo optimization run in headless browser); lint, normalize, check do not.

1. Choose a Tool First

ScenarioChoiceSource File
Flowcharts, sequence diagrams, state diagrams, class diagrams — structured diagrams, primarily node relationshipsMermaid (simplest, write directly into ```mermaid code blocks; Wisp site renders during build)No separate file
Concept diagrams, intuitive illustrations, hand-drawn style, ML operator data flowExcalidrawname.excalidraw (JSON)
Precisely aligned model structure diagrams, layered architecture diagrams, need right-angle bend lines and multiple pagesdraw.ioname.drawio (uncompressed XML)
Step-by-step demos, interactiveNot part of this skill (React component)—

Rule of thumb: if Mermaid can explain it clearly, don't draw a diagram; hand-drawn style should not exceed about 12 nodes; keep style consistent within the same article.

2. Workflow (5 Steps)

The following uses diagrams/attention as an example; adjust paths according to actual location.

① Determine Type (see table above). After selecting, read the corresponding reference: Excalidraw → reference/excalidraw-skeleton.md; draw.io → reference/drawio-cheatsheet.md; common model diagram patterns can be copied and modified from reference/ml-patterns.md. Layout principles are in reference/style-guide.md.

② Generate Source File

  • Excalidraw: Write a skeleton JSON (position, size, label, semantic color names, arrow start/end IDs), then convert. Do NOT hand-write complete Excalidraw elements (fields like seed, boundElements, version are very error-prone).
    $W new diagrams/attention.skeleton.json -o diagrams/attention.excalidraw
    
    The skeleton file can be deleted after conversion or kept as a generation script; afterward, the .excalidraw file is the authoritative source.
  • draw.io: Write uncompressed mxGraph XML directly; use only the preset style strings from reference/drawio-cheatsheet.md. If you receive a compressed .drawio file, first decompress it with $W normalize diagrams/file.drawio.
  • Draw manually in an editor: Import assets/wisp.excalidrawlib (Excalidraw: right-side Library → Open) or assets/wisp-drawio-library.xml (draw.io: File → Open Library from → Device), and configure the palette according to assets/drawio-colors.txt.

③ Lint (fix first) then Build

$W lint diagrams/attention.excalidraw --fix      # Snap non-palette colors to nearest token; list ones that cannot be auto-fixed
$W lint diagrams/attention.excalidraw --strict   # Pass only if no errors or warnings
$W build diagrams/attention.excalidraw           # Generate diagrams/attention.wisp.svg

Common build arguments: --embed-fonts (embed font subsets, use when publishing to external platforms), --fix, --title T --desc D (override accessibility text, single file only), --drawio cli|docker|browser, --out-dir DIR, --strict. For multi-page draw.io files, pages from page 2 onward output as name.page-2.wisp.svg.

④ Self-Check: Export light and dark previews, view with a Reader tool

$W export diagrams/attention.wisp.svg --theme light -o /tmp/attention.light.png
$W export diagrams/attention.wisp.svg --theme dark  -o /tmp/attention.dark.png

Check for: text overlap, arrows passing through nodes, labels covering arrowheads, unreadable text in dark mode, Chinese characters being clipped. If issues are found, fix the source file and return to step ③ to rebuild. Keep preview PNGs in a temporary directory; do not commit them.

⑤ Reference and Write alt Text: See "Using Output" below. Alt text must be meaningful (describe the conclusion the diagram is meant to convey, not "Figure 1").

3. Palette

Colors can only come from palette.json. When drawing, use only the light values (left column in the table below); the build step maps them to var(--wd-*) (dark values are switched automatically by the SVG). Do not manually pick dark values. Do not use any color outside the palette (lint will error; --fix snaps to the nearest token).

HueStroke (lines, text) light / darkFill (background) light / darkSemantic Name
blue#1d4ed8 / #60a5fa#dbeafe / #1b2740q, active
amber#b45309 / #fbbf24#fef3c7 / #38290ck, highlight
green#15803d / #4ade80#dcfce7 / #122d1cv, done
rose#be123c / #fb7185#ffe4e6 / #3a1620grad, error
violet#7c3aed / #a78bfa#ede9fe / #272040weight
teal#0f766e / #2dd4bf#ccfbf1 / #0f2c29activation
orange#c2410c / #fb923c#ffedd5 / #3a2010bias
slate#475569 / #94a3b8#e2e8f0 / #222831mask, visited

Base colors: body text fg #1d1d1f (Excalidraw default black #000000/#1e1e1e is also treated as fg), secondary muted #5c6067, surface surface #f4f4f2, border border #e2e2dd, canvas white #ffffff (build removes the background).

Semantic Colors (consistent across all articles and diagrams)

Semantic NameMeaningHue
qQueryblue
kKeyamber
vValuegreen
weightWeight, parameterviolet
activationActivation, softmaxteal
gradGradientrose
biasBiasorange
maskMask, inputslate
highlightHighlightamber
visitedVisitedslate
activeCurrent/in-progressblue
doneCompletedgreen
errorError, lossrose

In the skeleton, the color field can be written directly as a semantic name ("color": "q") or a hue name; in draw.io, look up the corresponding fill/stroke from the table by hue.

4. Hard Style Rules

ItemRule
GridAll element x/y/width/height must be multiples of 8px
Font SizeUse only 12 (annotation) / 14 (label) / 18 (title); lint tolerance ±1
Line Width1.5 (normal), 2.5 (emphasis, one or two places per diagram); thin line 1 only for dividers
Corner RadiusRectangle/container corners: Excalidraw round, draw.io rounded=1;arcSize=8
FillSolid fill, use the fill from the hue; no gradients
ShadowNone
FontExcalidraw: Excalifont (Chinese fallback: Noto Sans SC, do not use 小赖体); draw.io: Inter
Hand-drawnroughness: 1; draw.io: do not use sketch=1
BackgroundDo not draw a background rectangle; keep it transparent
Source File.excalidraw is JSON; .drawio is uncompressed XML; embedded images bloat the file (warning if >2MB)

5. Self-Check Checklist

  • lint --strict passes: no non-palette colors, no shadows/gradients, font sizes compliant, elements on 8px grid
  • Semantic colors are correct: Q blue, K amber, V green, weight violet, activation teal, gradient/loss rose, bias orange, mask/input slate
  • One diagram only covers one topic; nodes ≤ 12 (hand-drawn)
  • Lines do not pass through nodes or intersect; short lines (spacing < 96px) have no labels
  • Chinese labels have ≤ 8–10 characters per line and are not clipped
  • Has a title (text with size: "title" / draw.io page name) and one annotation
  • Light and dark preview PNGs have been viewed with a Reader tool
  • .wisp.svg is generated, and the source file was rebuilt after modification
  • Alt text is meaningful

6. Using Output

In a Wisp Site (optional)

The site's pnpm diagram build|check|lint [--fix], pnpm diagram new <skeleton.json> --build, pnpm diagram export <file> --png --theme dark are thin wrappers around this skill (they delegate to uv run skills/wisp-diagram/scripts/wisp_diagram.py with --root <repo> --manifest scripts/diagram/manifest.json for incremental builds). Place source files alongside articles (in the diagrams/ directory); .wisp.svg files must also be committed. In MDX/Markdown, reference the source file using standard image syntax (the site will inline the corresponding .wisp.svg and provide a download link for the source file):

![Self-Attention: Q scores against K, then weighted sum of V](./diagrams/attention.excalidraw "Figure 1: Self-attention computation flow")
![Residual structure of Transformer Block](./diagrams/transformer-block.drawio#page=encoder)

The alt text is written into the SVG's <title>, and the text in quotes becomes the figure caption; #page=<page name> selects a draw.io page. pnpm diagram check only checks content hashes and does not require a browser in CI (but does need uv).

Other projects can also use the same "project mode": $W build --root . --manifest diagrams.manifest.json only rebuilds source files that changed (scans <root>/src/content/**/diagrams/), and $W check --root . --manifest diagrams.manifest.json validates hashes in CI.

Elsewhere (GitHub README, other blogs, IDE preview)

Reference the generated *.wisp.svg directly: it includes its own <style>; when used as an <img>, it follows system light/dark via prefers-color-scheme. Renderers without CSS variable support will fall back to the light values in the attributes.

![Self-attention computation flow](diagrams/attention.wisp.svg)
  • Before publishing to external platforms, use $W build <file> --embed-fonts to embed font subsets (usually a few tens of KB per diagram) to avoid font fallback.
  • Platforms like WeChat Official Accounts or Zhihu that do not support SVG: $W export <file> --theme light --scale 2 -o out.png (use --transparent for a transparent background; fonts are embedded by default).
  • Keep source files in the repository for later editing; .excalidraw can be opened at excalidraw.com, .drawio at app.diagrams.net.

7. Common Mistakes

MistakeHow to Avoid
Hand-writing complete Excalidraw elementsOnly write a skeleton; use $W new to convert
Used a color outside the palette in the editor (eyedropper, default color)Use the asset library; run lint --fix to snap; if errors persist, edit the source file
Manually picked dark values while drawingOnly use light values; dark values are switched automatically by the SVG
Skeleton arrow passes through a third nodeArrows are straight lines on the center connection; adjust the layout, or switch to draw.io bend lines
Short line with a label, label covers arrowheadOnly add labels when node spacing ≥ 96px; otherwise, remove the label
Coordinates not on the 8px gridUse only multiples of 8 for all numerical values
.drawio committed in compressed formatUse $W normalize to decompress; uncheck "Compressed" under File → Properties
& not escaped in draw.io labelWhen html=1, write &amp;amp;, and write newlines as &lt;br&gt;
Chinese label too long, gets clipped≤ 8–10 characters per line, use \n / <br> to break lines, widen the node
Changed source file but forgot to rebuildAfter modifying, rerun $W build (in the site, pnpm diagram check will catch hash mismatches)
Delivered without checking dark previewStep ④ dark preview must be checked
Empty alt text ("Figure 1", "diagram")Alt text should describe the conclusion the diagram illustrates
Used diagram tool to draw data chartsLine/bar/etc. data charts are not part of this skill

8. Troubleshooting

  • uv: command not found: Install uv (curl -LsSf https://astral.sh/uv/install.sh | sh). Needs Python ≥ 3.11; uv will automatically download it if needed.
  • Cannot start Chromium: Run uv run --with playwright==1.64.1 playwright install chromium (version must match the pinned playwright version in the script).
  • Download failed / Offline mode: N files missing from cache: Run $W cache warm once on a connected network; check cache location with $W cache status.
  • draw.io export fails: Run $W probe to see which methods are available; force a method with --drawio browser|cli|docker.
  • To see errors in the browser: Set WISP_DIAGRAM_DEBUG=1.
  • lint reports unrecognised colour: The color is not a hex value (e.g., special values like rgb()); manually change it to a palette light value.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Related Skills