---
name: visual-builder
description: "Create SVG/HTML visuals — diagrams, illustrations, infographics, charts, and visual explanations for Canvas pages."
---

> **IMPORTANT: `cairosvg` plus the cairo system library are required for SVG conversion.**
> The skill auto-installs these on first use (macOS, via Homebrew). No manual setup needed.

# Visual Builder Skill

> **Plugin**: ASU Canvas Course Builder
> **Standards**: `standards/scientific-visuals.md`

## Purpose

Generate publication-quality SVG/HTML visuals for Canvas pages. This skill covers any visual that benefits from a custom-built representation rather than a photograph or stock image:

- **Diagrams** — labeled structures, anatomical cross-sections, system architectures
- **Process flows** — step-by-step sequences, decision trees, pipelines
- **Infographics** — data-driven visual summaries, statistical highlights
- **Charts & graphs** — custom visualizations beyond what a spreadsheet produces
- **Timelines** — historical sequences, project phases, developmental stages
- **Comparison visuals** — side-by-side feature comparisons, before/after, Venn diagrams
- **Concept maps** — relationship diagrams, hierarchies, taxonomies
- **Cycles** — biological cycles, feedback loops, iterative processes
- **Illustrations** — simplified visual explanations of abstract concepts

This is NOT a closed list. Claude should freely design novel visual representations when a unique approach better serves the learning objective. The examples above are starting points, not constraints.

## How It Works

1. **User describes what they need** — a concept, topic, or data to visualize
2. **Claude generates SVG** following `standards/scientific-visuals.md` (kept as intermediate source)
3. **SVG is converted to PNG** at 2x scale via `scripts/convert_svg.py` for retina quality
4. **PNG is uploaded to Canvas Files** via `upload_image()` to `images/m{N}/` or `images/shared/`
5. **Embedded as `<img>`** inside a `<figure>` with `<figcaption>` and alt text

### Why SVG → PNG?
- **Canvas strips raw SVGs** from page HTML (XSS prevention) — inline SVG delivery does not work
- **SVG as authoring format** gives precise control: scalable, editable, accessible source
- **PNG as delivery format** renders natively in Canvas — no iframe, no stripping
- **2x scale** ensures retina-quality images (crisp on all displays)
- **Editable** — the SVG source is preserved for iteration before re-converting
- **Lightweight pipeline** — `cairosvg` converts in a single function call

## Auto-Install Check (Mandatory — runs silently on first use)

Before any SVG conversion work, run the check silently:

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/ensure_cairosvg.py --check
```

If it exits non-zero on macOS, immediately run the installer without asking the user (brief one-line status: "Installing cairo + cairosvg for SVG conversion..."):

```bash
${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/ensure_cairosvg.py
```

This installs `cairo`, `pkg-config` (via Homebrew), and `cairosvg` (pip into the plugin venv), then verifies the import before continuing. Do NOT prompt the user — this is a transparent dependency bootstrap. Only surface an error if the installer exits non-zero; in that case, report the exact failure and fall back to offering `images` skill alternatives (search or AI gen).

Non-macOS platforms require manual cairo install (brew equivalent for the OS). The installer will print instructions if run there.

## Required Inputs

- **Course context**: Read from `course-config.json` — module objectives, CLOs, topic details
- **User description**: What concept or data to visualize, any specific requirements
- **Placement**: Which module and page the visual goes on (if applicable)

## Flow

### Step 1: Understand the Visual Need
Ask about the content, not the technology:
- What concept, process, or data should this visual explain?
- What's the key takeaway students should get from looking at it?
- Any specific elements, labels, or relationships to include?
- Is there existing content on the page this should complement?

### Step 2: Check Alternatives
Before generating an SVG, quickly consider:
- Would a real photograph work better? → Route to `images` (Mode 1: Search)
- Would an AI-generated image be more appropriate? → Route to `images` (Mode 2: Generate)
- Does this need user interaction (click, drag, animate)? → Route to `interactive-content`
- Is a custom SVG/HTML the best fit? → Continue with this skill

### Step 3: Generate the Visual
Create the SVG following `standards/scientific-visuals.md`:
- Use `viewBox` for responsive scaling, `width="100%"`
- All text as `<text>` elements with system font stack
- Presentation attributes for styling (not CSS classes or `<style>` blocks)
- `role="img"`, `<title>`, `<desc>` for accessibility
- Wrap in `<figure>` with `<figcaption>`
- Colors appropriate to the subject matter (full color freedom — see standards)

### Step 4: Convert & Upload
1. Save the SVG source to a temporary file (preserve for future iteration)
2. On macOS, verify dependencies first: `${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/ensure_cairosvg.py --check`
3. If the check fails on macOS, run: `${ASUCB_PLUGIN_ROOT:-${CODEX_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}}/bin/python3 scripts/ensure_cairosvg.py`
4. Convert to PNG: `python scripts/convert_svg.py source.svg --output visual.png --scale 2`
5. Upload PNG via `upload_image()` with the appropriate module number
6. Embed in the Canvas page using the image template below

### Step 5: Deliver
- Confirm the course and page, convert to PNG, upload, and embed
- Include descriptive alt text in the `<img>` tag and a visible caption in `<figcaption>`

## Visual Specification Format

When designing a visual, produce this specification:

```
### Metadata
- **Visual Name**: [descriptive name]
- **Module**: M[#] — [title] (if applicable)
- **Placement**: [which page, where on the page]
- **Learning Objective(s)**: [what this visual helps students understand]

### Visual Description
- **What it depicts**: [concept, process, data]
- **Key elements**: [list of labeled components]
- **Relationships shown**: [what connections or flows are illustrated]

### Accessibility
- **Alt text**: [1-2 sentence description for screen readers]
- **Long description**: [detailed text description of all visual information]

### Canvas Integration
- **Delivery**: SVG source → PNG conversion (2x) → Canvas image upload → `<img>` embed
- **Page**: [Canvas page slug]
```

## Quality Standards

All visuals must follow `standards/scientific-visuals.md`. Key points:

### Color
- Use colors appropriate to the subject matter — no restriction to ASU palette for visual content
- WCAG 4.5:1 contrast for all text-on-background
- No color-only encoding — supplement with labels, shapes, or patterns

### Accessibility (WCAG 2.1 AA)
- `role="img"` on root `<svg>`
- `<title>` with short alt text
- `<desc>` with detailed screen-reader description
- `aria-label` on logical `<g>` groups
- `aria-describedby` linking to visible text for complex diagrams
- No color-only information encoding

### Labels
- Adjacent to what they describe (Mayer contiguity)
- Minimum 12px font size
- Leader lines (1px, #595959) when labels can't sit next to their element
- Never overlapping

### Scientific Accuracy
- Label units on measurements and axes
- Use standard notation
- Cite data sources in figcaption
- Note simplifications ("Not to scale", "Simplified representation")

### Canvas Compatibility
- All SVG styling via presentation attributes (`fill`, `stroke`, `font-size`) — these render correctly in cairosvg
- PNG output is typically 200-500KB at 2x scale (well within Canvas limits)
- Keep SVG source clean and under ~50KB for fast conversion
- Test the PNG renders correctly in Canvas page preview

## Image Embed Template

After converting to PNG and uploading, embed using this template:

```html
<figure style="margin: 25px 0; text-align: center;">
  <img src="/courses/{COURSE_ID}/files/{FILE_ID}/preview"
       alt="{descriptive alt text}"
       style="max-width: 100%; height: auto; border-radius: 8px;" />
  <figcaption style="font-size: 13px; color: #595959; margin-top: 8px; line-height: 1.4;">
    <strong>Figure N:</strong> Caption text
    <span style="display: block; font-size: 11px; color: #888; margin-top: 4px;">Source: Attribution if applicable</span>
  </figcaption>
</figure>
```

## Output

When invoked, this skill produces:
1. SVG source file (intermediate artifact, preserved for iteration)
2. PNG image (converted at 2x scale, uploaded to Canvas Files)
3. `<figure>` embed with `<img>`, alt text, and `<figcaption>`
4. Canvas page integration (where to embed, how to push)
5. Alignment to learning objectives (if in course context)
