Skip to content
Back to skills

Excalidraw Diagram

ASecurity

Create Excalidraw diagram JSON files that make visual arguments -- workflows, architectures, concepts. Use when the user wants to visualize systems, processes, or ideas as .excalidraw files. Covers design methodology, section-by-section building, render-validate loop, and quality checklist.

  • 2 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
ai-agentspythonrustgokotlinbashnodeexpressspringdockerterraform

Works with

  • terminal
  • cli
  • api

Security analysis

A100/100

Pro scans all 13 files and shows the line behind each finding

Scanned August 31, 2026

npx -y skills add Yesterday-AI/skills --skill excalidraw-diagram --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Excalidraw Diagram?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Excalidraw Diagram
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yesterday-ai-excalidraw-diagram/badge)](https://www.skillsdirectory.com/skills/yesterday-ai-excalidraw-diagram)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: excalidraw-diagram
description: >
  Create Excalidraw diagram JSON files that make visual arguments -- workflows, architectures,
  concepts. Use when the user wants to visualize systems, processes, or ideas as .excalidraw files.
  Covers design methodology, section-by-section building, render-validate loop, and quality checklist.
metadata:
  author: Yesterday-AI
  version: "1.1"
  category: design
  source: https://github.com/coleam00/excalidraw-diagram-skill
compatibility: >
  File write access required. Rendering to PNG requires Python 3.11+, uv, and Playwright (chromium).
---

# Excalidraw Diagram Creator

Generate `.excalidraw` JSON files that **argue visually**, not just display information.

**Setup:** If the renderer hasn't been set up yet:
```bash
cd skills/excalidraw-diagram/references
uv sync
uv run playwright install chromium
```

## Customization

**All colors and brand-specific styles live in one file:** `references/color-palette.md`. Read it before generating any diagram and use it as the single source of truth for all color choices -- shape fills, strokes, text colors, evidence artifact backgrounds, everything.

To make this skill produce diagrams in a different brand style, edit `color-palette.md`. Everything else in this file is universal design methodology and Excalidraw best practices.

---

## Premium Infographic Mode (opt-in)

Use this mode when the goal is an **eye-catching, educational infographic** in the
hand-drawn Daily-Dose-of-DS / Akshay-Pachaar style (think a single shareable
visual that *teaches* a concept), not a plain architecture/flow diagram. It is
**opt-in**: the skill's defaults (monospace font, `roughness: 0`, white canvas,
container discipline) are unchanged unless you explicitly switch this on.

**To switch on, set these across the whole diagram:**

| Setting | Value | Why |
|---------|-------|-----|
| Font (`fontFamily`) | `5` Excalifont (or `1` Virgil) -- both hand-drawn | the signature warm look -- verified to load in the renderer |
| Title accent (optional) | `7` Lilita One (bold display) | chunky headline weight when a hand-drawn title needs more punch |
| Sans labels (optional) | `6` Nunito (rounded) -- or `2`/`9` Helvetica/Liberation | clean labels/annotations when hand-drawn is too casual |
| Code/data (`fontFamily`) | `3` Cascadia or `8` Comic Shanns (mono) ONLY | mono everywhere = "cheap terminal" look |
| `roughness` | `1` | hand-drawn wobble, not sterile |
| Canvas `viewBackgroundColor` | `#F7F3E9` (warm cream) | NOT pure white |
| Render command | `--theme light` | dark theme inverts colors + forces white bg |
| Palette | "Premium Infographic Palette" in `color-palette.md` | 6-hue, state-coded |
| Containers | pastel pills are encouraged here | the colored pills ARE the style (the default <30%-container rule is relaxed in this mode) |

**Fonts available.** The renderer ships 8 built-in families (no custom fonts):
hand-drawn `1` Virgil / `5` Excalifont; sans `2` Helvetica / `6` Nunito / `9`
Liberation Sans; bold display `7` Lilita One; mono `3` Cascadia / `8` Comic
Shanns. (`4` is unused.) These are the ONLY fonts — an unregistered
`fontFamily` silently falls back, so don't reference Google Fonts or arbitrary
typefaces. Type ramp for a premium figure: title `5`/`7`, body `5`, labels
`6`, code `3`/`8`. Visual swatches: `references/font-catalog.png`.

**Signature elements** (assemble these -- see `references/element-templates.md` for
JSON and `references/libraries/` for drop-in shapes):

- **Title pill** -- the headline in a filled rounded-rect, color-coded.
- **State-coded pastel pills** -- green=good/done, coral=bad, lavender=special, blue=neutral, butter=highlight.
- **Highlighter swipe** -- a thin filled rounded-rect behind a free-floating arrow label.
- **Mascot / narrator** -- a stick figure (confused at the problem, happy at the resolution) from the bundled `stick-figures` library.
- **Speech / thought bubble** -- short commentary in the narrator's voice (bundled `bubbles` library).
- **Evidence pills** -- concrete data/code in `fontFamily: 3` mono inside light pills.
- **Numbered steps** -- small butter circles (1..n) sitting on the flow arrows.
- **Dashed = pending / grouping** -- masked/optional items, grouping banners, outer loops.
- **Card grid / matrix** -- his dominant format: N identical self-contained mini-diagrams in a grid, each with a colored title pill, for enumerating/comparing variants ("8 RAG Architectures").
- **Consistent concept-icon system** -- reuse the SAME glyph for the same concept across the whole figure (embedding-brain, LLM-brain, vector-DB+✦, doc-stack, envelope=query, gear, globe, graph-nodes, brand logos). The consistency IS the signature.
- **Bottom-summary thesis (MANDATORY)** -- one plain-language sentence at the bottom stating the single argument the graphic makes.

**Full element vocabulary:** the basics above are a starting set. The complete
rich catalog -- card-grid, left-edge section tabs, insight-column panels, formula
annotation, the concept-icon system + library mapping, the `+` combiner glyph,
color-coded keywords in prose, tensor grids, token-sequence columns, math
limitations, and which styles to AVOID (dark-neon) -- lives in
`references/signature-elements.md`. **Read it before building a premium infographic.**

**The one-thesis rule:** every premium infographic argues exactly ONE thing.
Decide that sentence first (it becomes the bottom-summary), then build the visual
to prove it. If you can't write the bottom-summary, the diagram has no point yet.

### From research to storyline (the conceptual layer)

A great infographic is a *story*, not a labelled diagram. Before any JSON:

1. **Distill** the source (article, transcript, paper, wiki) down to the single
   thesis — the one sentence a reader should leave with. That sentence is the
   bottom-summary.
2. **Pick the narrative shape** that fits the thesis. The shape *is* the layout —
   choose it deliberately, don't default to boxes-and-arrows:

   | If the thesis is about… | Narrative shape | Layout | Example |
   |---|---|---|---|
   | a before→after change | **transformation** | banded comparison / before-after panels | `rag-infographic`, `micro-venture-studio` |
   | how something flows step by step | **journey / process** | linear pipeline + numbered steps | `innovation-pipeline` |
   | "how does this end / which path?" | **decision / fork** | one source → branched outcomes | `three-exit-framework` |
   | "it's X, not Y" | **contrast** | side-by-side panels | `micro-venture-studio` |
   | "what's really going on inside" | **dissection** | formula sheet + insight column / concept-space | `set-diagram`, `typography-grid` |
   | "N things, and here's the point" | **enumeration that argues** | card grid (the grid must make ONE point, not be a list) | — |

3. **Give it an arc:** a **hook** (title as a question or a provocation, e.g.
   "How does a project end?"), a **tension** (the problem / the naive approach /
   the confused mascot), and a **payoff** (the thesis, bottom-summary, happy
   mascot). Add the narrator (mascot) to carry the emotion: confused at the hook,
   resolved at the payoff.
4. **Make reading-order = story-order.** The eye must traverse the canvas in the
   order the story is told (left→right or top→bottom); the thesis lands LAST.

If the figure doesn't read as hook → tension → payoff, it's a diagram, not a story.

**Worked examples (reference):** nine in `references/examples/` spanning the
shapes above — `rag-infographic` (transformation + mascot), `innovation-pipeline`
(journey), `three-exit-framework` (fork), `micro-venture-studio` (contrast),
`set-diagram` (dissection), `typography-grid` (type ramp), `yesterday-ci-infographic`
(Yesterday CI theme), `dark-agent-memory` + `dark-inference-grid` (flat dark-mode
technical-reference theme). Open the PNGs to see the target quality bar before building.

**Three opt-in themes** (all in `color-palette.md`): default = light pastel
hand-drawn (DDoDS/Pachaar); **Yesterday CI** = clean cream+orange editorial;
**Dark Technical Reference** = flat dark-mode for dense reference posters (render
`--theme light`). Builder palettes: `PREMIUM` / `YESTERDAY` / `DARK`.

---

## Core Philosophy

**Diagrams should ARGUE, not DISPLAY.**

A diagram isn't formatted text. It's a visual argument that shows relationships, causality, and flow that words alone can't express. The shape should BE the meaning.

**The Isomorphism Test**: If you removed all text, would the structure alone communicate the concept? If not, redesign.

**The Education Test**: Could someone learn something concrete from this diagram, or does it just label boxes? A good diagram teaches--it shows actual formats, real event names, concrete examples.

---

## Depth Assessment (Do This First)

Before designing, determine what level of detail this diagram needs:

### Simple/Conceptual Diagrams
Use abstract shapes when:
- Explaining a mental model or philosophy
- The audience doesn't need technical specifics
- The concept IS the abstraction (e.g., "separation of concerns")

### Comprehensive/Technical Diagrams
Use concrete examples when:
- Diagramming a real system, protocol, or architecture
- The diagram will be used to teach or explain (e.g., YouTube video)
- The audience needs to understand what things actually look like
- You're showing how multiple technologies integrate

**For technical diagrams, you MUST include evidence artifacts** (see below).

---

## Research Mandate (For Technical Diagrams)

**Before drawing anything technical, research the actual specifications.**

If you're diagramming a protocol, API, or framework:
1. Look up the actual JSON/data formats
2. Find the real event names, method names, or API endpoints
3. Understand how the pieces actually connect
4. Use real terminology, not generic placeholders

Bad: "Protocol" -> "Frontend"
Good: "AG-UI streams events (RUN_STARTED, STATE_DELTA, A2UI_UPDATE)" -> "CopilotKit renders via createA2UIMessageRenderer()"

**Research makes diagrams accurate AND educational.**

---

## Evidence Artifacts

Evidence artifacts are concrete examples that prove your diagram is accurate and help viewers learn. Include them in technical diagrams.

**Types of evidence artifacts** (choose what's relevant to your diagram):

| Artifact Type | When to Use | How to Render |
|---------------|-------------|---------------|
| **Code snippets** | APIs, integrations, implementation details | Dark rectangle + syntax-colored text (see color palette for evidence artifact colors) |
| **Data/JSON examples** | Data formats, schemas, payloads | Dark rectangle + colored text (see color palette) |
| **Event/step sequences** | Protocols, workflows, lifecycles | Timeline pattern (line + dots + labels) |
| **UI mockups** | Showing actual output/results | Nested rectangles mimicking real UI |
| **Real input content** | Showing what goes IN to a system | Rectangle with sample content visible |
| **API/method names** | Real function calls, endpoints | Use actual names from docs, not placeholders |

The key principle: **show what things actually look like**, not just what they're called.

---

## Multi-Zoom Architecture

Comprehensive diagrams operate at multiple zoom levels simultaneously.

### Level 1: Summary Flow
A simplified overview showing the full pipeline or process at a glance.

### Level 2: Section Boundaries
Labeled regions that group related components. These create visual "rooms" that help viewers understand what belongs together.

### Level 3: Detail Inside Sections
Evidence artifacts, code snippets, and concrete examples within each section. This is where the educational value lives.

**For comprehensive diagrams, aim to include all three levels.**

### Bad vs Good

| Bad (Displaying) | Good (Arguing) |
|------------------|----------------|
| 5 equal boxes with labels | Each concept has a shape that mirrors its behavior |
| Card grid layout | Visual structure matches conceptual structure |
| Icons decorating text | Shapes that ARE the meaning |
| Same container for everything | Distinct visual vocabulary per concept |
| Everything in a box | Free-floating text with selective containers |

---

## Steady-State Principle (Not a Changelog)

**A diagram is a portrait of what the system IS today, not how it got there.** Release-history content belongs in a changelog or release notes, not on the canvas.

**Hard "never" list — these turn the diagram into a changelog:**
- "SHIPPED <month> <year>" / "Recent additions" / "What's new" sections.
- Ticket-id badges (`PROJ-123`, `M007`, `JIRA-…`) anywhere on the canvas.
- Date stamps next to pills or captions (`(added 2026-05-15)`, `(sandboxed 2026-…)`).
- Ticket tags inside feature titles (`Dashboard (M003)`, `Auth Service (PROJ-42)`) — the title is the *thing*, not the work item it shipped under.

**How to integrate a newly-shipped capability instead:** make it a noun in the body. Extend a pillar's description, add a small caption next to the box that owns it, increment a stat-card if the count moved, add a chip to a list of substrates. If a feature has no place in the steady-state portrait it isn't diagram-worthy — document it elsewhere (PROCESS docs, KNOWLEDGE log, release notes).

**Test**: read the diagram cold six months from now. Is every box still true, or are some captions only true if you remember when they shipped? Strip the time-bound captions.

---

## Container vs. Free-Floating Text

**Not every piece of text needs a shape around it.** Default to free-floating text. Add containers only when they serve a purpose.

| Use a Container When... | Use Free-Floating Text When... |
|------------------------|-------------------------------|
| It's the focal point of a section | It's a label or description |
| It needs visual grouping with other elements | It's supporting detail or metadata |
| Arrows need to connect to it | It describes something nearby |
| The shape itself carries meaning (decision diamond, etc.) | Typography alone creates sufficient hierarchy |
| It represents a distinct "thing" in the system | It's a section title, subtitle, or annotation |

**The container test**: For each boxed element, ask "Would this work as free-floating text?" If yes, remove the container.

### Mutating bound text: the `containerId` footgun

When a text element has `containerId: "<rect_id>"`, the renderer reads the *container's* position and lays the text inside it. **Changing the text's `x` / `y` does nothing visually** — the move is silently ignored.

Symptom: you re-position a bound text in JSON, re-render, and the text either disappears or stays at the old location while the new (empty) rectangle sits at the moved coordinates.

To relocate a bound text from card A → card B:
1. On the text element: set `containerId: "<B_rect_id>"`.
2. On `A.boundElements`: remove `{id: "<text_id>", type: "text"}`.
3. On `B.boundElements`: append `{id: "<text_id>", type: "text"}`.
4. On the text element: update `originalText` to match the current `text` field (Excalidraw uses `originalText` for wrap calculations; mismatch causes layout glitches).

When in doubt, prefer `containerId: null` + `boundElements: []` from the start — gives you free positioning at the cost of losing auto-text-wrap-to-container.

---

## Design Process (Do This BEFORE Generating JSON)

### Step 0: Assess Depth Required
- **Simple/Conceptual**: Abstract shapes, labels, relationships
- **Comprehensive/Technical**: Concrete examples, code snippets, real data

**If comprehensive**: Do research first. Look up actual specs, formats, event names, APIs.

### Step 1: Understand Deeply
Read the content. For each concept, ask:
- What does this concept **DO**? (not what IS it)
- What relationships exist between concepts?
- What's the core transformation or flow?
- **What would someone need to SEE to understand this?**

### Step 2: Map Concepts to Patterns
For each concept, find the visual pattern that mirrors its behavior:

| If the concept... | Use this pattern |
|-------------------|------------------|
| Spawns multiple outputs | **Fan-out** (radial arrows from center) |
| Combines inputs into one | **Convergence** (funnel, arrows merging) |
| Has hierarchy/nesting | **Tree** (lines + free-floating text) |
| Is a sequence of steps | **Timeline** (line + dots + free-floating labels) |
| Loops or improves continuously | **Spiral/Cycle** (arrow returning to start) |
| Is an abstract state or context | **Cloud** (overlapping ellipses) |
| Transforms input to output | **Assembly line** (before -> process -> after) |
| Compares two things | **Side-by-side** (parallel with contrast) |
| Separates into phases | **Gap/Break** (visual separation between sections) |

### Step 3: Ensure Variety
For multi-concept diagrams: **each major concept must use a different visual pattern**. No uniform cards or grids.

### Step 4: Sketch the Flow
Before JSON, mentally trace how the eye moves through the diagram. There should be a clear visual story.

### Step 5: Generate JSON
Only now create the Excalidraw elements. **See below for how to handle large diagrams.**

Two ways to produce the elements:
- **Write JSON directly** -- fine for simple/conceptual diagrams. Use `references/element-templates.md` for the per-element shapes and copy items from `references/libraries/`.
- **Use the builder (recommended for premium / complex infographics)** -- `references/infographic_builder.py` is a thin composition layer so you don't hand-write 100+ raw element dicts or redo coordinate math. It *places library items by name* (`s.place("Vector DB", x, y, h=90)`) and adds the connective tissue (`title`, `arrow(..., numbered=1)`, `pill`, `thesis`), then `s.save(path)`. Palettes (`PREMIUM`, `YESTERDAY`) and font IDs (`FONT`) are constants in the module. A library gives you shapes; the builder gives you layout. Example at the bottom of the module's docstring.

### Step 6: Render & Validate (MANDATORY)
After generating the JSON, you MUST run the render-view-fix loop until the diagram looks right. See the **Render & Validate** section below.

---

## Large / Comprehensive Diagram Strategy

**For comprehensive or technical diagrams, build the JSON one section at a time.** Do NOT attempt to generate the entire file in a single pass -- token limits and quality both demand section-by-section building.

### The Section-by-Section Workflow

**Phase 1: Build each section**

1. **Create the base file** with the JSON wrapper (`type`, `version`, `appState`, `files`) and the first section of elements.
2. **Add one section per edit.** Each section gets its own dedicated pass.
3. **Use descriptive string IDs** (e.g., `"trigger_rect"`, `"arrow_fan_left"`) so cross-section references are readable.
4. **Namespace seeds by section** (e.g., section 1 uses 100xxx, section 2 uses 200xxx) to avoid collisions.
5. **Update cross-section bindings** as you go.

**Phase 2: Review the whole**

After all sections are in place, read through the complete JSON and check:
- Are cross-section arrows bound correctly on both ends?
- Is the overall spacing balanced?
- Do IDs and bindings all reference elements that actually exist?

**Phase 3: Render & validate**

Run the render-view-fix loop from the Render & Validate section.

### What NOT to Do

- **Don't generate the entire diagram in one response.** You will hit the output token limit and produce truncated, broken JSON.
- **Don't use a coding agent** to generate the JSON. The agent won't have sufficient context about the skill's rules.
- **Don't write a Python generator script.** Hand-crafted JSON with descriptive IDs is more maintainable.

---

## Visual Pattern Library

### Fan-Out (One-to-Many)
Central element with arrows radiating to multiple targets. Use for: sources, PRDs, root causes, central hubs.

### Convergence (Many-to-One)
Multiple inputs merging through arrows to single output. Use for: aggregation, funnels, synthesis.

### Tree (Hierarchy)
Parent-child branching with connecting lines and free-floating text (no boxes needed). Use `line` elements for the trunk and branches, free-floating text for labels.

### Spiral/Cycle (Continuous Loop)
Elements in sequence with arrow returning to start. Use for: feedback loops, iterative processes.

### Cloud (Abstract State)
Overlapping ellipses with varied sizes. Use for: context, memory, conversations, mental states.

### Assembly Line (Transformation)
Input -> Process Box -> Output with clear before/after. Use for: transformations, processing, conversion.

### Side-by-Side (Comparison)
Two parallel structures with visual contrast. Use for: before/after, options, trade-offs.

### Gap/Break (Separation)
Visual whitespace or barrier between sections. Use for: phase changes, context resets, boundaries.

### Lines as Structure
Use lines (type: `line`, not arrows) as primary structural elements instead of boxes:
- **Timelines**: Vertical/horizontal line with small dots (10-20px ellipses) at intervals, free-floating labels beside each dot
- **Tree structures**: Vertical trunk line + horizontal branch lines, with free-floating text labels
- **Dividers**: Thin dashed lines to separate sections
- **Flow spines**: A central line that elements relate to

Lines + free-floating text often creates a cleaner result than boxes + contained text.

---

## Shape Meaning

Choose shape based on what it represents -- or use no shape at all:

| Concept Type | Shape | Why |
|--------------|-------|-----|
| Labels, descriptions, details | **none** (free-floating text) | Typography creates hierarchy |
| Section titles, annotations | **none** (free-floating text) | Font size/weight is enough |
| Markers on a timeline | small `ellipse` (10-20px) | Visual anchor, not container |
| Start, trigger, input | `ellipse` | Soft, origin-like |
| End, output, result | `ellipse` | Completion, destination |
| Decision, condition | `diamond` | Classic decision symbol |
| Process, action, step | `rectangle` | Contained action |
| Abstract state, context | overlapping `ellipse` | Fuzzy, cloud-like |
| Hierarchy node | lines + text (no boxes) | Structure through lines |

**Rule**: Default to no container. Add shapes only when they carry meaning. Aim for <30% of text elements to be inside containers.

---

## Color as Meaning

Colors encode information, not decoration. Every color choice should come from `references/color-palette.md`.

**Key principles:**
- Each semantic purpose (start, end, decision, AI, error, etc.) has a specific fill/stroke pair
- Free-floating text uses color for hierarchy (titles, subtitles, details)
- Evidence artifacts (code snippets, JSON examples) use their own dark background + colored text scheme
- Always pair a darker stroke with a lighter fill for contrast

**Do not invent new colors.** If a concept doesn't fit an existing semantic category, use Primary/Neutral or Secondary.

---

## Modern Aesthetics

### Roughness
- `roughness: 0` -- Clean, crisp edges. **Default for most use cases.**
- `roughness: 1` -- Hand-drawn, organic feel. Use for brainstorming/informal diagrams.

### Stroke Width
- `strokeWidth: 1` -- Thin, elegant. Good for lines, dividers, subtle connections.
- `strokeWidth: 2` -- Standard. Good for shapes and primary arrows.
- `strokeWidth: 3` -- Bold. Use sparingly for emphasis.

### Opacity
**Always use `opacity: 100` for all elements.**

### Small Markers Instead of Shapes
Use small dots (10-20px ellipses) as timeline markers, bullet points, connection nodes, visual anchors.

---

## Layout Principles

### Hierarchy Through Scale
- **Hero**: 300x150 - visual anchor, most important
- **Primary**: 180x90
- **Secondary**: 120x60
- **Small**: 60x40

### Whitespace = Importance
The most important element has the most empty space around it (200px+).

### Flow Direction
Guide the eye: typically left->right or top->bottom for sequences, radial for hub-and-spoke.

### Connections Required
Position alone doesn't show relationships. If A relates to B, there must be an arrow.

---

## Text Rules

**CRITICAL**: The JSON `text` property contains ONLY readable words.

```json
{
  "id": "myElement1",
  "text": "Start",
  "originalText": "Start"
}
```

Settings: `fontSize: 16`, `fontFamily: 3`, `textAlign: "center"`, `verticalAlign: "middle"`

---

## JSON Structure

```json
{
  "type": "excalidraw",
  "version": 2,
  "source": "https://excalidraw.com",
  "elements": [...],
  "appState": {
    "viewBackgroundColor": "#ffffff",
    "gridSize": 20
  },
  "files": {}
}
```

## Element Templates

See `references/element-templates.md` for copy-paste JSON templates for each element type (text, line, dot, rectangle, arrow). Pull colors from `references/color-palette.md` based on each element's semantic purpose.

---

## Pre-bundled Libraries

`references/libraries/` ships four curated `.excalidrawlib` shape vocabularies covering the full architecture-diagramming spectrum:

- **`lo-fi-wireframing-kit`** -- UI mockups (buttons, forms, alerts, cards, page frames, phone/desktop/tablet)
- **`system-design`** -- generic architecture shapes (DB types, server, cache, LB, message queue, pipeline, CDN)
- **`technology-logos`** -- concrete tech-stack logos (K8s, Docker, Terraform, Kafka, Redis, Spring, Kotlin, Neo4j, ...)
- **`cloud-design-patterns`** -- distributed-system patterns as full mini-diagrams (retry, circuit breaker, sharding, throttling, queue-based load leveling)

Read `references/libraries/README.md` for the decision matrix and per-library preview PNGs. When a diagram needs a recognizable shape that fits one of these vocabularies, lift the relevant `libraryItems[*].elements` array into your diagram instead of redrawing from scratch -- re-seed `id`/`seed`/`versionNonce` to avoid collisions, and translate coordinates to your target position.

The skill's "shape = meaning" mandate still applies: pick libraries that *encode meaning* (system-design = "this is a DB", technology-logos = "this is Postgres specifically"), not libraries that decorate.

---

## Render & Validate (MANDATORY -- minimum 3 passes)

You **cannot** judge a diagram from JSON alone. Coordinates that look correct routinely produce overlapping text, clipped labels, and broken layouts when rendered. **Never deliver a diagram without completing the render loop.**

### The Rule

**Minimum 3 render-verify-adapt passes.** No exceptions. Each pass follows this exact sequence:

1. **Render** -- Run the render script to produce a PNG
2. **View** -- Read the PNG with the Read tool and actually look at it
3. **List issues** -- Write down every problem you see (be specific: "label X overlaps shape Y", "arrow Z points into empty space")
4. **Fix** -- Edit the JSON to address every listed issue
5. **Go to 1**

A diagram is done when a pass finds **zero issues**, not when you've completed 3 passes. 3 is the floor, not the ceiling.

**Do NOT skip this loop.** Do NOT render once and declare it done. The first render almost always has problems -- that's expected and fine. The loop is how you fix them.

### How to Render

```bash
cd skills/excalidraw-diagram/references && uv run python render_excalidraw.py <path-to-file.excalidraw>
```

This outputs a PNG next to the `.excalidraw` file. Then use the **Read tool** on the PNG to actually view it.

**Scale caveat for large diagrams.** The default `--scale 2` produces a 2× device-pixel PNG. On diagrams whose final pixel dimensions exceed ~10 000 px per side, the Chrome canvas-pixel ceiling silently drops content from the rendered SVG — entire boxes vanish with no error. The renderer auto-downgrades to `--scale 1` when the projected size would cross this threshold (and logs a warning); you can force `--scale 1` manually if a section is missing from a `--scale 2` render. A smaller PNG with all content always beats a sharper PNG with missing boxes.

### Static checks before render (cheap, catch the obvious)

The render loop is the only complete validator, but two programmatic checks catch the most common defects before paying for a chromium round-trip. Run them after every JSON edit:

**Bbox-overlap scan** — for every pair of `text` elements, compute bbox-intersection area. Flag any pair >100 px². Catches a multi-line text spilling through siblings (e.g. you set a `text` element's text to 3 lines but its parent rect is sized for 1).

**Glyph-width estimation** — for every text element, estimate the rendered width of the widest line:

```python
fs = el.get("fontSize", 20)
coef = 0.60 if el.get("fontFamily") == 3 else 0.55   # 3 = Cascadia mono; else proportional
widest_chars = max(len(line) for line in el["text"].split("\n"))
est_w = widest_chars * fs * coef
```

Compare `est_w` against the element's declared `width` AND against the containing card's *interior* width. Flag any element where `est_w > declared_width + 5`. This catches monospace strings overflowing a card sideways with no warning — bbox says "fits", glyphs say "no".

Both checks are ~10 lines of Python and run in milliseconds. Use them as a pre-flight gate before the slow render-validate loop, not as a replacement for it.

### What to Check Each Pass

**Vision check** -- compare rendered result to your design intent:
- Does the visual structure match the conceptual structure?
- Does each section use the pattern you intended?
- Does the eye flow through the diagram in the right order?
- Is the visual hierarchy correct?
- For technical diagrams: are evidence artifacts readable?

**Defect check** -- look for these specific issues:
- Text clipped by or overflowing its container
- Text or shapes overlapping other elements
- Embedded images covering labels or descriptions
- Arrows crossing through elements instead of routing around
- Arrows landing on the wrong element or pointing into empty space
- Labels floating ambiguously between multiple elements
- Uneven spacing between elements that should be evenly spaced
- Text too small to read at the rendered size
- Overall composition lopsided or unbalanced
- Whole sections missing from the PNG (scale=2 canvas-ceiling silent-drop; try `--scale 1`)

**Don't trust the full-image thumbnail alone.** When the Read tool displays a large PNG, it downscales for viewing — overlaps and clipping under ~20 px vanish. For every edited region, also crop ~25% × 25% around the change and view at ≥1600 px wide. The thumbnail is for vibe; the zoom-crop is for review.

### When to Stop

The loop is done when:
- A full pass finds zero vision or defect issues
- No text is clipped, overlapping, or unreadable
- Arrows route cleanly and connect to the right elements
- Spacing is consistent and the composition is balanced
- You'd show it to someone without caveats

### First-Time Setup
```bash
cd skills/excalidraw-diagram/references
uv sync
uv run playwright install chromium
```

---

## Quality Checklist

### Depth & Evidence (Check First for Technical Diagrams)
1. **Research done**: Did you look up actual specs, formats, event names?
2. **Evidence artifacts**: Are there code snippets, JSON examples, or real data?
3. **Multi-zoom**: Does it have summary flow + section boundaries + detail?
4. **Concrete over abstract**: Real content shown, not just labeled boxes?
5. **Educational value**: Could someone learn something concrete from this?

### Conceptual
6. **Isomorphism**: Does each visual structure mirror its concept's behavior?
7. **Argument**: Does the diagram SHOW something text alone couldn't?
8. **Variety**: Does each major concept use a different visual pattern?
9. **No uniform containers**: Avoided card grids and equal boxes?

### Storyline (premium infographics)
- **One thesis**: Can you state, in one sentence, the single thing the figure argues? Is it written as the bottom-summary?
- **Narrative shape chosen**: Did you pick a shape (transformation / journey / fork / contrast / dissection / arguing-enumeration) on purpose, not default to boxes-and-arrows?
- **Arc present**: Is there a hook (title question/provocation), a tension (problem / naive path / confused mascot), and a payoff (the thesis)?
- **Reading-order = story-order**: Does the eye traverse the canvas in the order the story is told, with the thesis landing last?

### Container Discipline
10. **Minimal containers**: Could any boxed element work as free-floating text instead?
11. **Lines as structure**: Are tree/timeline patterns using lines + text rather than boxes?
12. **Typography hierarchy**: Are font size and color creating visual hierarchy?

### Structural
13. **Connections**: Every relationship has an arrow or line
14. **Flow**: Clear visual path for the eye to follow
15. **Hierarchy**: Important elements are larger/more isolated

### Technical
16. **Text clean**: `text` contains only readable words
17. **Font**: `fontFamily: 3`
18. **Roughness**: `roughness: 0` for clean/modern (unless hand-drawn style requested)
19. **Opacity**: `opacity: 100` for all elements
20. **Container ratio**: <30% of text elements should be inside containers

### Visual Validation (Render Required)
21. **Rendered to PNG**: Diagram has been rendered and visually inspected
22. **No text overflow**: All text fits within its container (bbox AND glyph-width estimate)
23. **No overlapping elements**: Shapes and text don't overlap unintentionally
24. **Even spacing**: Similar elements have consistent spacing
25. **Arrows land correctly**: Arrows connect to intended elements
26. **Readable at export size**: Text is legible in the rendered PNG
27. **Balanced composition**: No large empty voids or overcrowded regions
28. **Zoom-crop reviewed**: Every edited region viewed at ≥1600 px wide, not just full-image thumbnail
29. **No silent-drop**: All sections present (verify if diagram is large and scale=2 was used)

### Steady-State Discipline
30. **No release-history captions**: Zero "SHIPPED <month>" sections, ticket-id badges, date stamps, or ticket-tagged titles
31. **Present-tense reading**: Every caption reads true six months from now without remembering when it shipped

Files in this skill

  • .plugin.json558 B
  • SKILL.md33.3 KB
  • references/.gitignore19 B
  • references/color-palette.md8.7 KB
  • references/element-templates.md4 KB
  • references/examples/dark-agent-memory.excalidraw54.8 KB
  • references/examples/dark-inference-grid.excalidraw22.9 KB
  • references/examples/innovation-pipeline.excalidraw25.1 KB
  • references/examples/micro-venture-studio.excalidraw25.4 KB
  • references/examples/rag-infographic.excalidraw33.2 KB
  • references/examples/set-diagram.excalidraw13.8 KB
  • references/examples/three-exit-framework.excalidraw15.3 KB
  • references/examples/typography-grid.excalidraw29.2 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.