# Svg Animate

> Create, edit, or remix an animated SVG file from a natural-language description. Use this whenever the user asks you to make, build, design, generate, animate, or "draw something that moves" — mascots, logos, loaders, badges, icons, characters, brand marks, or any visual asset that should animate. Always prefer this skill over hand-writing SVG strings. Trigger phrases (use this skill even on subtle variants): "做一个X动画", "给我画个会动的Y", "搞一个跳跃/旋转/脉动的Z", "make me an animated X", "create a bouncing/spinning/pulsing X", "build a logo that does Y", "design a loader that ...", "I need an SVG mascot for ...". Also use when the user provides a reference image or sketch and asks to "animate this" or "make this lively". When the user says they want output "as an SVG file" or asks for something to drop into output/, this skill is the right entry point.

- Skill: `chanmeng666/svg-animate` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add chanmeng666/svg-animate`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chanmeng666/svg-animate/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: ChanMeng666 (https://skillmd.com/u/chanmeng666)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chanmeng666/svg-animate

---


You are the entry point for SVG animation requests in this repository.

The repository (`svg-animation-studio`) is a compounding system: every animation
reuses primitives from `lib/primitives/`, every new primitive earns the right
to be added through `/svg-add-primitive`. Your job is to translate one
sentence of natural language into a working `output/<slug>.svg` that visually
delights — without breaking that compounding discipline.

## Why this skill exists

LLMs that template-literal SVG strings end up with subtly broken markup,
inconsistent IDs, and no way to evolve. This skill funnels everything through
`lib/composer.js` so the system stays composable, snapshot-testable, and
reusable across sessions. If you find yourself wanting to write `<svg ...>`
inline anywhere, stop — `composer.composeSVG` exists for exactly that need.

## Step 1 — Understand what's being asked

1. Read any user-provided reference from `ref/` (sketches, sample SVGs, screenshots).
2. Identify the asset class: character mascot, logo mark, loader/spinner,
   notification badge, ambient background, or icon.
3. Identify the motion verbs: jumping, bobbing, pulsing, spinning, waving,
   talking, glowing, drifting, flickering.
4. Identify the style cues: pixel-art, gradient-smooth, flat, neon, comic.

If the request is vague ("make it cool"), ask one clarifying question — pick
the highest-leverage one (usually: "what shape/character?" or "what motion?").
Don't grill the user.

## Step 2 — Read the catalog before composing

Open `lib/presets/index.js` to see what already exists. Look at each
candidate's `compose()` (~30 lines each) to learn the patterns. Decide one of:

- **Fork** — closest existing preset is 80%+ right. Copy its file to a new
  slug, adjust params/colors.
- **Compose from primitives** — no existing preset fits, but the needed
  primitives all exist in `lib/primitives/`. Build a new preset.
- **Stop and request a primitive** — a needed motion / shape / filter doesn't
  exist. Output a one-line summary plus:
  > "I need a `<primitive-name>` primitive in `lib/primitives/<category>.js`.
  > Please run `/svg-add-primitive <name>`."
  Do NOT add primitives inline. See `docs/extension-protocol.md` rule 1.

For inspiration mapping ("user wants X → reach for Y"), open
`references/preset-cookbook.md`.

For the full lib API (signatures + defaults), open `references/lib-api.md`.

**For any branded / multi-layer asset (cover, banner, logo, loader), use the
modern composition path** (it's how the quality bar is reproduced):
- Pull a palette with `getPalette(opts.palette || '<default>')` from `lib/palettes.js`
  and reference accents by index (`pal.accents[0]`) — never hardcode hex.
- Build the body with `composeScene({ layers, defs, style })` from `lib/scene.js`:
  it orders layers back-to-front and auto-nests a layer's static `transform` +
  animated `className` (so the CSS transform can't clobber positioning — Gotcha 2).
- Then fork the closest family template: `brandCover.js` / `gradientCover.js`
  (covers), `heroStrip.js` / `repoHero.js` (banners), `orbitLogo.js` /
  `pulseMonoLogo.js` / `spinBadge.js` (logos/badges), `dotLoader.js` /
  `rippleLoader.js` / `bounceChar.js` (loaders/characters). `chan-cover` is the
  FROZEN reference — fork `brand-cover` instead.

For why timing / squash / staggering matter, open
`references/animation-principles.md`. The 5-point quality checklist there is
the same one `/svg-verify` will grade against — design with it in mind.

## Step 3 — Write the preset

A preset file lives at `lib/presets/<slugCamelCase>.js` and exports:

```js
module.exports = {
  name: '<slug-kebab>',
  viewBox: '0 0 W H',
  width:  W, height: H,
  compose(opts = {}) {
    motion.resetIdCounter();          // mandatory first line
    // pull primitives, compose body + style, return composeSVG({...})
  }
};
```

Add the new slug to `lib/presets/index.js`.

Constraints, in priority order:

- `composeSVG` is the only allowed way to assemble the root `<svg>` document.
- Call `motion.resetIdCounter()` as the first line of `compose()` so class
  names are deterministic across calls — this is what makes snapshots stable.
- Default colors and durations should match the source's intent; allow the
  user to override via `opts`.
- Re-use existing primitives wherever possible. Each new preset that re-uses
  ≥ 1 primitive validates the compounding contract.

## Step 4 — Render

```bash
node lib/render-cli.js <slug>
```

This writes to `output/<slug>.svg`. Inspect file size — if it's < 200 bytes,
something is wrong (probably an empty body); if it's > 20 KB without good
reason (heavy gradients or many elements), something is duplicated.

## Step 5 — Snapshot

```bash
npm run test:snapshot
```

First time for a new preset → snapshot is created. Subsequent runs → diff is
shown. If diff is intentional (you tuned params), update with:

```bash
npm run snapshot:update
```

Always re-verify visually after a snapshot update.

## Step 6 — Visually verify

Invoke `/svg-verify <slug>` — it runs in an isolated subagent context, opens
the SVG in chrome-devtools MCP, scores against the 5-point rubric, and
returns ≤ 100 words. The screenshots and console messages stay in the
subagent's context so this main thread doesn't drown in image data.

## Step 7 — Iterate or finalize

If the verdict is `tweak`: adjust params (duration, easing, magnitude,
stagger), re-render, re-verify. Cap at 3 rounds before pausing to ask the
user. If `fail`: probably a structural issue — re-read the source primitives
and reconsider composition rather than tweaking magnitudes.

If `pass`: report to the user with:

- Path: `output/<slug>.svg`
- Primitives used: `motion.foo`, `shapes.bar`, ...
- The verdict's one-line summary
- (Optional) Whether to run `/svg-export <slug>` to optimize and ship.

## Anti-patterns

- ❌ Writing `<svg ...>` markup directly in a skill or preset. Always go
  through `composer.composeSVG`.
- ❌ Adding a function to `lib/primitives/*.js` without going through
  `/svg-add-primitive`. The protocol exists to keep JSDoc, snapshot coverage,
  and lib-api.md in sync.
- ❌ Calling `npm run snapshot:update` without a visual recheck. Snapshots
  are the only thing protecting you from silent regressions.
- ❌ Burning the user's time on > 3 silent iterations. After three rounds
  without a pass, pause and ask.
- ❌ Hand-writing keyframe values when a `motion.*` primitive already covers
  the motion. Composability is the whole point.

## When the user wants multiple variants

If the user asks for "a few options", "show me 3 styles", "give me variants",
or "compare different approaches", delegate to the `svg-explorer` subagent
instead of running variants serially in this thread. The Agent dispatch
pattern:

```
Use the svg-explorer agent to produce <N> variants of
"<user's description>" varying along axis <timing|palette|style|energy>.
```

It returns a comparison block with file paths + a recommendation. Then run
`/svg-verify <recommended-slug>` on the chosen winner, and `/svg-export` if
the user accepts.

Why delegate? Generating N presets in parallel + rendering N SVGs + reading
N preset diffs would pump verbose intermediate output into this thread.
The fork keeps the comparison clean: you only see the final summary.

## When something goes wrong

- `npm test` fails on a preset you didn't touch → you broke a primitive
  signature. Diff your primitive changes and either fix them or update
  the snapshot deliberately after visual recheck.
- `compose()` throws → almost certainly a missing or renamed primitive.
  Open `docs/lib-api.md` and grep for the function you tried to call.
- Visual verification keeps failing on stagger → check
  `animation-principles.md` section "Staggering"; the magnitude is probably
  outside 0.05–0.15 s.

