Agent Skill
2/7/2026

svg-graphics

Scalable, accessible, theme-aware visuals.

F
fabioc
2GitHub Stars
1Views
npx skills add fabioc-aloha/Alex_Plug_In

SKILL.md

Namesvg-graphics
DescriptionScalable, accessible, theme-aware visuals.

name: "svg-graphics" description: "Scalable, accessible, theme-aware visuals."

SVG Graphics Skill

Scalable, accessible, theme-aware visuals.

Why SVG

  • Scales infinitely (retina, print)
  • Text is searchable/accessible
  • CSS-styleable (dark mode!)
  • Small file size
  • Version control friendly

Banner Template

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 300">
  <!-- Background -->
  <rect width="100%" height="100%" fill="#1a1a2e"/>

  <!-- Title -->
  <text x="50" y="100" font-size="48" fill="#fff" font-family="system-ui">
    Project Name
  </text>

  <!-- Tagline -->
  <text x="50" y="150" font-size="24" fill="#888">
    One-line description
  </text>

  <!-- Feature pills -->
  <g transform="translate(50, 200)">
    <rect rx="12" width="100" height="24" fill="#4a4a6a"/>
    <text x="50" y="17" text-anchor="middle" fill="#fff" font-size="12">Feature 1</text>
  </g>
</svg>

Key Techniques

TechniqueUse Case
viewBoxResponsive scaling
<defs> + <use>Reusable components
<linearGradient>Modern backgrounds
<clipPath>Shaped containers
CSS variablesTheme switching

Dark/Light Mode

<style>
  @media (prefers-color-scheme: dark) {
    .bg { fill: #1a1a2e; }
    .text { fill: #ffffff; }
  }
  @media (prefers-color-scheme: light) {
    .bg { fill: #ffffff; }
    .text { fill: #1a1a2e; }
  }
</style>

Icon Guidelines

SizeUse
16x16Favicon, small UI
32x32Tab icon, lists
128x128App icon
512x512Store listing

SMIL Animation

Delayed Fade-In Pattern

Elements that should appear after load (hero text, feature pills, etc.):

<!-- Element starts invisible, fades in after delay -->
<g opacity="0">
  <text x="50" y="100" font-size="48" fill="#fff">Title</text>
  <animate
    attributeName="opacity"
    from="0" to="1"
    dur="0.8s"
    begin="0.5s"
    fill="freeze"
  />
</g>

Key attributes:

AttributePurposeValues
beginDelay before start"0.5s", "1s", "click"
durAnimation duration"0.3s" to "2s" typical
fillState after animation"freeze" (keep end state) or "remove" (revert)
repeatCountRepetitions"1", "3", "indefinite"

Staggered Entrance

Multiple elements appearing in sequence:

<g opacity="0">
  <rect rx="12" width="100" height="24" fill="#4a4a6a"/>
  <text x="50" y="17" text-anchor="middle" fill="#fff" font-size="12">Feature 1</text>
  <animate attributeName="opacity" from="0" to="1" dur="0.5s" begin="0.3s" fill="freeze"/>
</g>
<g opacity="0">
  <rect rx="12" width="100" height="24" fill="#4a4a6a"/>
  <text x="50" y="17" text-anchor="middle" fill="#fff" font-size="12">Feature 2</text>
  <animate attributeName="opacity" from="0" to="1" dur="0.5s" begin="0.6s" fill="freeze"/>
</g>
<g opacity="0">
  <rect rx="12" width="100" height="24" fill="#4a4a6a"/>
  <text x="50" y="17" text-anchor="middle" fill="#fff" font-size="12">Feature 3</text>
  <animate attributeName="opacity" from="0" to="1" dur="0.5s" begin="0.9s" fill="freeze"/>
</g>

Pattern: Increment begin by 0.3s per element for smooth staggering.

SMIL Compatibility

PlatformSupport
Chrome/EdgeFull SMIL
FirefoxFull SMIL
SafariFull SMIL
GitHub READMENo animation (static render)
npm/PyPI READMENo animation (static render)

Rule: For README badges/banners, set initial opacity="1" as fallback — animated SVGs render as static first frame in non-animated contexts.

CSS Transform Patterns

The Nested Group Pattern

Problem: Combining position transforms (translate) with animation transforms (rotate, scale) on the same element causes conflicts — the animation resets position.

Solution: Use nested <g> groups to separate concerns:

<!-- Outer group: POSITION (static) -->
<g transform="translate(600, 150)">
  <!-- Inner group: ANIMATION (dynamic) -->
  <g>
    <animateTransform
      attributeName="transform"
      type="rotate"
      from="0" to="360"
      dur="10s"
      repeatCount="indefinite"
    />
    <!-- The actual shape -->
    <circle r="20" fill="#4a90d9"/>
  </g>
</g>

Rule: Never mix static positioning and animated transforms on the same element. Always wrap in a positioning group.

Scale from Center

<g transform="translate(100, 100)">
  <!-- transform-origin doesn't work reliably in SVG; 
       use translate to center, then scale -->
  <g>
    <animateTransform
      attributeName="transform"
      type="scale"
      from="0.8" to="1.0"
      dur="0.5s"
      fill="freeze"
    />
    <!-- Shape centered at origin (0,0) -->
    <circle cx="0" cy="0" r="30" fill="#d3f5db"/>
  </g>
</g>

Pulse Effect

<circle cx="50" cy="50" r="10" fill="#cf222e">
  <animateTransform
    attributeName="transform"
    type="scale"
    values="1;1.2;1"
    dur="1.5s"
    repeatCount="indefinite"
  />
</circle>

ClipPath Container Layering

The 3-Layer Pattern

For shaped containers with content and visible borders:

<defs>
  <clipPath id="container-clip">
    <rect x="50" y="50" width="400" height="200" rx="16"/>
  </clipPath>
</defs>

<!-- Layer 1: BACKGROUND (fill behind clip) -->
<rect x="50" y="50" width="400" height="200" rx="16" fill="#f6f8fa"/>

<!-- Layer 2: CLIPPED CONTENT (stays inside shape) -->
<g clip-path="url(#container-clip)">
  <!-- Content that may overflow is safely clipped -->
  <image href="photo.jpg" x="50" y="50" width="400" height="200"/>
  <text x="70" y="120" font-size="24" fill="#fff">Overlay Text</text>
</g>

<!-- Layer 3: BORDER OUTLINE (drawn last, on top) -->
<rect x="50" y="50" width="400" height="200" rx="16" 
      fill="none" stroke="#d1d9e0" stroke-width="2"/>

Draw order matters:

  1. Background fill (behind everything)
  2. Clipped content group (contained within shape)
  3. Border outline (on top, fill="none")

Rounded Card Pattern

<defs>
  <clipPath id="card">
    <rect width="300" height="180" rx="12"/>
  </clipPath>
</defs>

<g transform="translate(20, 20)">
  <!-- Card background -->
  <rect width="300" height="180" rx="12" fill="#ffffff"/>
  
  <!-- Card content (clipped) -->
  <g clip-path="url(#card)">
    <!-- Header band -->
    <rect width="300" height="48" fill="#0550ae"/>
    <text x="16" y="32" fill="#fff" font-size="16" font-weight="bold">Card Title</text>
    <!-- Body -->
    <text x="16" y="80" fill="#1f2328" font-size="14">Card content here</text>
  </g>
  
  <!-- Card border -->
  <rect width="300" height="180" rx="12" fill="none" stroke="#d1d9e0"/>
</g>

SVG Optimization

SVGO Configuration

{
  "plugins": [
    "preset-default",
    { "name": "removeViewBox", "active": false },
    { "name": "removeDimensions", "active": true },
    { "name": "removeTitle", "active": false }
  ]
}

Critical: Never remove viewBox (breaks scaling) or <title> (breaks accessibility).

Size Budget

SVG TypeTarget SizeMax
Icon< 1 KB2 KB
Badge/shield< 2 KB5 KB
Banner< 10 KB25 KB
Complex diagram< 25 KB50 KB

Common Optimization Wins

TechniqueSavings
Remove editor metadata (Inkscape, Illustrator)20-50%
Simplify paths (reduce decimal precision)10-20%
Remove empty groups/unused defs5-15%
Convert shapes to paths5-10%
Gzip on server60-80% additional

Accessibility

  • role="img" on decorative SVGs
  • <title> for screen readers
  • Sufficient contrast (4.5:1 min)
  • aria-hidden="true" if decorative

Tools

ToolPurpose
SVGOOptimize/minify
InkscapeVisual editing
svg-to-pngRasterization

SVG for Documentation Illustrations

SVG isn't just for branding — it's the best format for polished documentation visuals that need more control than Mermaid provides.

When to Choose SVG Over Mermaid

ScenarioUse SVGUse Mermaid
Architecture overview for README✅ Branded, polished❌ Too generic
Internal dev docs flow❌ Overkill✅ Quick, accurate
Marketing / landing page✅ Full design control❌ Unbranded
Infographic with custom layout✅ Arbitrary positioning❌ Auto-layout only
Dark/light theme required✅ CSS media queries⚠️ Limited theming
Print / high-DPI output✅ Infinitely scalable⚠️ Rasterized at render

Illustration Template

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400" role="img">
  <title>Architecture Overview</title>
  <style>
    @media (prefers-color-scheme: dark) {
      .bg { fill: #1e1e1e; }
      .text { fill: #d4d4d4; }
      .box { fill: #2d2d2d; stroke: #444; }
      .accent { fill: #0078d4; }
    }
    @media (prefers-color-scheme: light) {
      .bg { fill: #ffffff; }
      .text { fill: #1a1a1a; }
      .box { fill: #f5f5f5; stroke: #ddd; }
      .accent { fill: #0078d4; }
    }
    .label { font-family: system-ui, sans-serif; font-size: 14px; }
    .title-text { font-family: system-ui, sans-serif; font-size: 20px; font-weight: 600; }
    .connector { stroke-width: 2; stroke-dasharray: 4 4; }
  </style>

  <rect class="bg" width="100%" height="100%"/>

  <!-- Title -->
  <text class="title-text text" x="400" y="30" text-anchor="middle">Architecture Name</text>

  <!-- Boxes with rounded corners -->
  <g transform="translate(100, 60)">
    <rect class="box" rx="8" width="200" height="80" stroke-width="1.5"/>
    <text class="label text" x="100" y="45" text-anchor="middle">Component A</text>
  </g>

  <!-- Connector arrow -->
  <line class="connector accent" x1="300" y1="100" x2="400" y2="100"/>
  <polygon class="accent" points="400,95 410,100 400,105"/>

  <g transform="translate(420, 60)">
    <rect class="box" rx="8" width="200" height="80" stroke-width="1.5"/>
    <text class="label text" x="100" y="45" text-anchor="middle">Component B</text>
  </g>
</svg>

Key Principles for Illustrations

  1. Always include dark/light mode via @media (prefers-color-scheme: ...) — GitHub renders both
  2. Use semantic class names (.box, .accent, .connector) not inline styles
  3. Center with text-anchor="middle" — more maintainable than manual x positioning
  4. Group with <g transform="translate()"> — move entire components by adjusting one value
  5. Keep viewBox ratio consistent — 800×400 (2:1) for wide illustrations, 600×600 (1:1) for square

Illustrating Real-World Subjects (Animals, Objects, People)

The Snowman Problem

Problem: When asked to draw a dog, cat, person, or any real-world subject, AI defaults to stacking circles and rectangles — producing geometric snowmen with accessories instead of recognizable illustrations.

Root Cause: The model uses primitive shapes (<circle>, <rect>, <ellipse>) as building blocks. Real-world subjects have organic, asymmetric silhouettes that require <path> elements with Bezier curves.

The Snowman Test: If you remove all color, texture, and small details — does the silhouette alone identify the subject? A circle on a circle is always a snowman, no matter how many ears/tails you add.

Mandatory Rules for Subject Illustrations

#RuleWhy
1Start with the silhouette — sketch the outer <path> outline FIRSTThe outline makes or breaks recognition. If the outline looks wrong, details won't fix it.
2Use <path> with Bezier curves for ALL organic shapes<circle> and <ellipse> produce geometric/robotic results. Real animals have no perfect circles.
3Pass the squint test — outline alone must be identifiableRemove all fill colors and details. If the outline doesn't read as the subject, redo the outline.
4Get proportions right before adding detailsHead-to-body ratio, limb length, and placement matter more than eyes/nose/accessories.
5Count limbs correctly — quadrupeds have 4 legs, birds have 2 + wingsThe most common error. Don't draw 2 legs on a 4-legged animal. In side view, show at least 3 legs (near pair + 1 far).
6Differentiate species by key anatomical featuresA dog is not a cat is not a bear. See the feature table below.

Feature Differentiation Table

What makes each animal visually distinct — the features to exaggerate:

AnimalKey Silhouette FeaturesCommon AI Mistakes
DogSnout/muzzle protruding from head, floppy or pointed ears (SIDE of head, not top), 4 legs, wagging tail, body longer than tallFlat face (no snout), cat ears on top, 2 legs, perfect circle head
CatPointed ears on TOP of head, round face, long curved whiskers, slender body, long curving tail, 4 legs with small pawsNo whiskers, dog-like snout added, thick stocky body
BirdBeak (triangular), wings (large relative to body), 2 thin legs, tail feathers, no arms4 legs, no beak, arms instead of wings
FishStreamlined oval body, tail fin, dorsal fin, NO legsLegs added, round body (balloon), no fins
PersonHead on neck on shoulders, 2 arms with hands, 2 legs with feet, torso taller than wideSnowman stack, no neck, T-pose arms
HorseLong neck, elongated head with flat front, 4 long thin legs, mane, flowing tailDog-like proportions, short legs, round head
RabbitLONG upright ears (longer than head), round body, short front legs, large hind legs, cotton tailShort ears (looks like a bear), same-length legs

The Path-First Approach

Never build an animal from primitive shapes. Build from a single continuous <path> outline.

Step-by-Step: Drawing a Dog (Side View)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300" role="img">
  <title>Dog illustration</title>
  
  <!-- Step 1: BODY OUTLINE - single path defining the entire silhouette -->
  <!-- Start at chest, go along back, tail, rear leg, belly, front leg, up to chin, head, ear, back to start -->
  <path d="
    M 120,180
    C 120,140 140,110 180,105
    C 210,100 250,100 280,110
    Q 300,118 310,135
    L 330,115
    L 320,140
    Q 315,160 310,180
    L 305,220
    L 290,220
    L 290,185
    Q 260,195 220,195
    L 180,220
    L 165,220
    L 170,185
    Q 140,180 120,180
    Z
  " fill="#c89050" stroke="#6b4226" stroke-width="2"/>

  <!-- Step 2: HEAD - overlapping path with snout protruding forward -->
  <path d="
    M 130,160
    C 120,130 100,110 85,100
    Q 70,92 60,100
    C 50,110 55,130 60,140
    L 65,148
    Q 80,160 100,165
    Q 115,168 130,160
    Z
  " fill="#c89050" stroke="#6b4226" stroke-width="2"/>
  
  <!-- Step 3: SNOUT/MUZZLE - the feature that makes it a dog, not a snowman -->
  <path d="
    M 72,130
    C 60,125 50,128 48,135
    C 46,142 52,148 62,148
    Q 70,145 72,138
    Z
  " fill="#e8c690" stroke="#6b4226" stroke-width="1.5"/>
  
  <!-- Step 4: EAR - floppy, attached to SIDE of head (not on top!) -->
  <path d="
    M 100,105
    C 105,85 115,75 120,80
    C 125,88 118,105 110,112
    Z
  " fill="#a0703c" stroke="#6b4226" stroke-width="1.5"/>
  
  <!-- Step 5: Details LAST - eye, nose, mouth -->
  <circle cx="82" cy="115" r="4" fill="#2c1810"/>  <!-- Eye -->
  <ellipse cx="52" cy="135" rx="5" ry="4" fill="#2c1810"/>  <!-- Nose -->
  <path d="M 55,142 Q 62,148 68,144" fill="none" stroke="#6b4226" stroke-width="1.5"/>  <!-- Mouth -->
  
  <!-- Step 6: TAIL - curved upward, characteristic dog pose -->
  <path d="M 325,120 Q 345,90 350,100 Q 348,115 330,125" 
        fill="#c89050" stroke="#6b4226" stroke-width="2"/>
</svg>

Why this works:

  • Silhouette reads as "dog" even without color (elongated body, protruding snout, floppy ear)
  • Snout is the dominant facial feature — face is NOT flat
  • 4 legs visible (2 front, 2 back in side view)
  • Body is longer than tall (dog proportions, not snowman proportions)
  • ALL shapes use <path> with curves — no perfect circles

Proportion Guide

For side-view quadrupeds (dog, cat, horse):

┌──────────────────────────────────────────┐
│         HEAD    NECK    BODY             │
│        ┌───┐   ┌─┐   ┌──────────┐      │
│   ear→ │   │───│ │───│          │ ←tail │
│        │ • │   │ │   │          │  /    │
│  snout→│ ▪ │   └─┘   │          │ /     │
│        └───┘         │          │/      │
│                      └──┬──┬──┬─┘       │
│                         │  │  │  │      │
│                     legs (4, not 2!)    │
│                                         │
│  HEAD:BODY ratio ≈ 1:2.5 (dog)         │
│  HEAD:BODY ratio ≈ 1:2   (cat)         │
│  HEAD:BODY ratio ≈ 1:4   (horse)       │
│  LEG length ≈ body height (dog, horse)  │
│  LEG length ≈ 0.7× body height (cat)   │
└──────────────────────────────────────────┘

Color Guidelines for Illustrated Subjects

SubjectNatural PaletteAvoid
DogBrowns (#c89050, #a0703c, #6b4226), Golden (#e8c690), Black, White, GrayGreen, blue, purple (unnatural)
CatGray (#8e8e8e), Orange (#d68c45), Black, White, Siamese (#c4a882)Bright green, neon colors
BirdSpecies-specific; blue (#4a90d9), red (#cf4040), yellow (#e6b422), green (#5ab05a)All one color (usually multi-toned)
PersonSkin tones, clothing colorsGeometric shapes for body parts
TreeGreen canopy (#4a8c3f, #6aad5a), brown trunk (#6b4226, #8b6914)Blue leaves, gray trunk

Rule: Use realistic base colors unless the user specifically requests a stylized/cartoon palette.

Common Failure Modes

FailureCauseFix
"Snowman with ears"Using stacked circles for bodyUse one continuous <path> for body outline
"Cat ears on everything"Triangles placed on top of circular headPlace ears on SIDE of head (dogs), check species table
"Floating face"Features placed on a perfect circle with no jaw/chin structureGive head a distinct shape — snout, jawline, not a circle
"Stick figure animal"Rectangles for legs attached to circlesLegs should taper, connect to body organically with curves
"2-legged quadruped"Forgetting rear or front leg pairAlways count: is this animal 2-legged or 4-legged?
"Psychedelic colors"Using brand/branding palette instead of natural colorsReal animals have earthy, natural tones — check color table
"Giant head, tiny body"No proportion referenceCheck proportion guide — head is usually smaller than body

Workflow for Subject Illustrations

  1. Identify — What species/object? What view? (side/front/3-quarter)
  2. Reference proportions — Check the proportion guide and feature table
  3. Draw silhouette — Single <path> for body outline. Apply squint test.
  4. Add major features — Head shape, ears at correct position, limbs (count them!)
  5. Add details last — Eyes, nose, mouth, texture, color
  6. Squint test — Remove all color. Is the silhouette recognizable?

Synapses

See synapses.json for connections.

Skills Info
Original Name:svg-graphicsAuthor:fabioc