Install
$ agentstack add skill-yesterday-ai-skills-excalidraw-diagram ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Excalidraw Diagram Creator
Generate .excalidraw JSON files that argue visually, not just display information.
Setup: If the renderer hasn't been set up yet:
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 "Frontend" Good: "AG-UI streams events (RUNSTARTED, STATEDELTA, 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 " / "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: "", 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:
- On the text element: set
containerId: "". - On
A.boundElements: remove{id: "", type: "text"}. - On
B.boundElements: append{id: "", type: "text"}. - On the text element: update
originalTextto match the currenttextfield (Excalidraw usesoriginalTextfor 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.mdfor the per-element shapes and copy items fromreferences/libraries/. - Use the builder (recommended for premium / complex infographics) --
references/infographic_builder.pyis 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), thens.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
- Create the base file with the JSON wrapper (
type,version,appState,files) and the first section of elements. - Add one section per edit. Each section gets its own dedicated pass.
- Use descriptive string IDs (e.g.,
"trigger_rect","arrow_fan_left") so cross-section references are readable. - Namespace seeds by section (e.g., section 1 uses 100xxx, section 2 uses 200xxx) to avoid collisions.
- 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 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.
{
"id": "myElement1",
"text": "Start",
"originalText": "Start"
}
Settings: fontSize: 16, fontFamily: 3, textAlign: "center", verticalAlign: "middle"
JSON Structure
{
"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
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Yesterday-AI
- Source: Yesterday-AI/skills
- License: MIT
- Homepage: https://github.com/Yesterday-AI/skills
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.