| name | render |
| description | Use when the user says '/render', 'render this', 'render diagrams', 'generate SVG', 'mdview render', or wants to render markdown files with ASCII art diagrams to HTML via mdview. This skill generates DiagramSpec JSON for ASCII art blocks, embeds specs as HTML comments in the markdown, and calls mdview to produce themed SVG output. The AI provides the structural intelligence that makes asciisvg rendering accurate. |
| version | 1.0.0 |
Render: ASCII Art → Themed SVG via mdview
Generate DiagramSpec for ASCII art. Embed in markdown. Render via mdview.
AIs know what they're drawing. This skill serializes that knowledge as DiagramSpec JSON
so mdview's asciisvg renderer produces accurate, themed SVG — no heuristics, no network
calls to kroki.io.
How to Run
/render EPISTEMIC_MAP.md # Render specific file
/render # Render all .md files in current directory
/render --serve # Render and start live-reload server
/render --check # Audit: show which files have/lack specs
Phase 1: Discover ASCII Art Blocks
Read the target markdown file(s). For each file:
- Find all fenced code blocks (
```)
- Classify each block:
mermaid → skip (mdview handles these via mermaid.ink)
svgbob/ditaa → skip (explicitly typed)
- Unmarked or
text/ascii → check if ASCII art (box-drawing chars, arrows, borders)
- For each ASCII art block, check if a
<!-- diagram-spec: {...} --> comment already exists in the preceding lines
- Blocks WITH specs → already handled, skip
- Blocks WITHOUT specs → need spec generation (Phase 2)
Report what was found:
Found 3 ASCII art blocks in EPISTEMIC_MAP.md:
Block 1 (lines 15-77): No spec — NEEDS GENERATION
Block 2 (lines 83-103): No spec — NEEDS GENERATION
Block 3 (lines 120-145): Has spec — OK
Phase 2: Generate DiagramSpec JSON
For each ASCII art block without a spec, analyze the diagram and generate a DiagramSpec.
DiagramSpec Schema
{
"type": "<flow|sequence|box|table|wireframe|state_machine>",
"title": "Optional title",
"layout": "<auto|horizontal|vertical|grid|nested|sequence>",
"elements": [
{
"id": "unique_id",
"label": "Display text",
"type": "<node|actor|box|panel|header|row|decision>",
"children": ["child_id_1"],
"properties": {
"sections": [["line 1", "line 2"], ["section 2 line 1"]]
}
}
],
"connections": [
{
"from": "source_id",
"to": "target_id",
"label": "Optional label",
"style": "solid"
}
]
}
Type Selection Guide
| ASCII Pattern | DiagramSpec Type | Layout |
|---|
| Boxes with arrows between them | flow | horizontal or vertical |
| Vertical lifelines with horizontal messages | sequence | sequence |
| Standalone boxes with sections/content | box | horizontal or vertical |
| Rows and columns of data | table | grid |
| UI mockup with panels | wireframe | nested |
| States with transitions | state_machine | auto |
| Nested boxes (box within box) | box with children | vertical |
Box Diagram Guide (Most Common)
For boxes with sections (headers + content lines):
{
"type": "box",
"title": "System Overview",
"layout": "horizontal",
"elements": [
{
"id": "auth",
"label": "Auth Service",
"type": "box",
"properties": {
"sections": [
["JWT validation", "Role guards", "Session mgmt"]
]
}
},
{
"id": "api",
"label": "API Gateway",
"type": "box",
"properties": {
"sections": [
["Rate limiting", "Request routing"],
["Health checks"]
]
}
}
],
"connections": [
{"from": "auth", "to": "api", "label": "validates"}
]
}
Each entry in sections is a group of lines separated by a visual divider in the box.
Flow Diagram Guide
For nodes connected by arrows:
{
"type": "flow",
"layout": "vertical",
"elements": [
{"id": "start", "label": "PREFLIGHT", "type": "node"},
{"id": "check", "label": "Ready?", "type": "decision"},
{"id": "work", "label": "Do Work", "type": "node"},
{"id": "end", "label": "POSTFLIGHT", "type": "node"}
],
"connections": [
{"from": "start", "to": "check"},
{"from": "check", "to": "work", "label": "yes"},
{"from": "work", "to": "end"}
]
}
Elements with "type": "decision" render as diamonds.
Sequence Diagram Guide
For actors exchanging messages:
{
"type": "sequence",
"layout": "sequence",
"elements": [
{"id": "client", "label": "Client", "type": "actor"},
{"id": "server", "label": "Server", "type": "actor"},
{"id": "db", "label": "Database", "type": "actor"}
],
"connections": [
{"from": "client", "to": "server", "label": "POST /login", "properties": {"order": 1}},
{"from": "server", "to": "db", "label": "SELECT user", "properties": {"order": 2}},
{"from": "db", "to": "server", "label": "user record", "properties": {"order": 3, "direction": "return"}},
{"from": "server", "to": "client", "label": "JWT token", "properties": {"order": 4, "direction": "return"}}
]
}
Critical Rules
- Every element needs a unique
id — use short, descriptive slugs (e.g., "auth", "phase2_goal1")
- Connections reference element IDs via
"from" and "to" keys (NOT from_id/to_id)
- Read the ASCII art carefully — the diagram structure is already there, you're just serializing it
- Preserve all text content — every label, annotation, status marker in the ASCII art should appear in the spec
- Nested boxes — use
children array on parent elements to reference child element IDs
- Layout matters — horizontal for wide diagrams, vertical for tall ones
Phase 3: Embed Specs in Markdown
For each generated spec, insert a <!-- diagram-spec: {...} --> HTML comment on the
line immediately before the opening ``` fence of the code block.
Format: Single line, minified JSON (no pretty-printing — it's a comment, not for humans):
<!-- diagram-spec: {"type":"box","layout":"horizontal","elements":[...],"connections":[...]} -->
` `` `
┌─────────────┐ ┌─────────────┐
│ Auth │───>│ API │
└─────────────┘ └─────────────┘
` `` `
Important: The ASCII art stays unchanged. The spec comment is metadata that tells
mdview how to render it. Humans still see the ASCII art in their editor.
Use the Edit tool to insert the comment line before each code block that needs one.
Phase 4: Render
After embedding all specs, render via mdview:
mdview <file>.md --output rendered/<name>.html --no-open
mdview <file>.md --output rendered/<name>.html
Phase 5: Verify
Check the rendered output:
grep -c 'mdview-diagram' rendered/<name>.html
grep -c 'class="svgbob"' rendered/<name>.html
grep -c 'diagram-fallback' rendered/<name>.html
Report results:
Rendered EPISTEMIC_MAP.md:
2 diagrams via asciisvg (themed SVG) ✓
0 kroki/svgbob fallbacks ✓
0 render failures ✓
Output: rendered/epistemic-map.html
If any block fell through to svgbob or failed, the spec JSON is wrong — fix it and re-render.
--check Mode
When run with --check, don't modify files. Just audit and report:
ASCII Art Spec Coverage:
EPISTEMIC_MAP.md: 0/2 blocks have specs ← NEEDS WORK
INTEGRATION_MAP.md: 1/1 blocks have specs ✓
ARCHITECTURE.md: 0/3 blocks have specs ← NEEDS WORK
DIAGRAMS.md: 0/0 ASCII blocks ✓ (all Mermaid)
SPEC.md: 0/1 blocks have specs ← NEEDS WORK
Total: 1/7 ASCII blocks have embedded DiagramSpec (14%)
Design Philosophy
The heuristic routing in mdview (routing.py, boxrender.py, etc.) exists for non-AI
scenarios — humans pasting ASCII art without spec metadata. It's a best-effort fallback.
In AI-assisted workflows (which is the primary use case), the AI always knows what
it's drawing. This skill ensures that knowledge gets persisted as DiagramSpec JSON
alongside the content. Once embedded:
- Any future render (by any tool, any user) produces the same high-quality output
- No network calls to kroki.io or mermaid.ink for ASCII diagrams
- Themed SVG with dark/light mode support via asciisvg
- The ASCII art in the markdown is still human-readable in any editor
The AI's intelligence gets persisted, not thrown away.