SVG Illustration skill for Codex
Hand-written SVG art you can still edit later. Codex draws illustrations directly in SVG with a stated style and a palette taken from your tokens, composes on a viewBox grid, and writes paths, symbols and gradients a developer can still edit by hand. Art themes through CSS custom properties for dark mode, patterns tile without visible edges, animation respects reduced motion, and SVGO output is checked so viewBox, titles and referenced IDs survive.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- svg-illustration Installs to ~/.agents/skills/svg-illustration/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install svg-illustration The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project svg-illustration Installs to .agents/skills/svg-illustration/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/svg-illustration.zipunzip -o svg-illustration.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) svg-illustration PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $svg-illustration, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Hand-authors SVG illustrations, spot graphics, hero art, backgrounds and repeating patterns - composition on a viewBox grid, path commands and arcs written deliberately, reuse with defs, symbol and use, gradients, clipPath and mask, theming with currentColor and CSS custom properties, optional CSS animation with reduced-motion fallbacks, SVGO optimisation and accessible markup. Use when asked to draw an illustration, empty-state graphic, decorative background, pattern or animated SVG in code rather than in a drawing app.
Use it when
- A screen needs a spot illustration or empty-state graphic drawn in code
- You want a decorative background or tiling pattern as SVG
- An illustration must follow theme tokens and switch with dark mode
- An existing SVG illustration is bloated and needs a clean rewrite
Use something else when
- Designing a logo or brand mark: use svg-logo-design
- Randomised or algorithmic artwork driven by code and seeds: use generative-art
How to check the result
The SVG renders correctly at its smallest and largest sizes in light and dark themes, two copies on one page do not interfere, and reduced-motion emulation stops all animation.
The mistake it prevents
Reusing generic IDs like gradient1 in several inline SVGs, so one illustration's gradient silently paints another on the same page.
A good code-drawn illustration has a clear focal point, a limited palette pulled from the product’s tokens, consistent stroke and corner language, and markup small and tidy enough that another developer can edit it by hand. It themes with CSS and degrades gracefully when motion is off.
Workflow
- Define the job: where it appears, size range, what it should communicate.
- Pick a style and palette from the product’s tokens (3-5 colors).
- Block out composition with simple shapes on the viewBox grid.
- Refine shapes with paths; add detail only where the eye lands.
- Factor repeats into
<defs>, theme with CSS variables. - Optimise, add accessibility markup, check at smallest and largest sizes.
1. Brief and style
Placement: empty state on Projects page, 160-240px wide, light and dark themes
Message: "nothing here yet, but it is easy to start"
Style: flat shapes, 2px strokes, 4px corner radius, no outlines on fills
Palette: --illus-bg, --illus-primary (brand-500), --illus-accent, --illus-line (neutral-700)
Pick one style and stay inside it:
| Style | Traits | Good for |
|---|---|---|
| Flat geometric | Primitives, no strokes, 2-3 tones per object | Empty states, onboarding |
| Line art | Single stroke weight, round caps/joins, minimal fills | Docs, feature explainers |
| Isometric | 30-degree axes, three tones per face (top light, left mid, right dark) | Architecture or product overviews |
| Abstract blobs and gradients | Organic curves, soft gradients | Hero backgrounds |
2. Canvas and composition
- Choose a
viewBoxmatching the aspect ratio of the slot, in round numbers (0 0 240 160). Work on an 8-unit grid; snap key points to it. - Place the focal object off-centre (rule of thirds) and give it the highest contrast.
- Ground objects with a soft shadow ellipse or base shape; floating objects look pasted.
- Keep a margin of about 8% of the width empty so the art does not touch its container.
3. Paths you will write by hand
| Command | Meaning | Use for |
|---|---|---|
M x y | Move | Start each subpath |
L, H, V | Lines | Hard edges |
C x1 y1 x2 y2 x y | Cubic Bezier | Organic curves |
S x2 y2 x y | Smooth cubic (reflects previous control) | Chained curves without kinks |
Q, T | Quadratic | Simple arcs, waves |
A rx ry rot large sweep x y | Elliptical arc | Rounded corners, circles in paths, pie slices |
Z | Close | Fills that should close |
Lowercase is relative to the current point, which makes repeated shapes easier to move.
For smooth curves, keep the incoming and outgoing control points collinear with the
anchor. Use <rect rx>, <circle>, <ellipse> and <line> instead of paths when the
shape is primitive; they stay readable.
4. Structure and reuse
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 160" role="img" aria-labelledby="ep-t">
<title id="ep-t">Empty project board with a plus card</title>
<style>
.ep-bg { fill: var(--illus-bg, #eef2ff); }
.ep-shadow { fill: var(--illus-shadow, #e2e8f0); }
.ep-surface { fill: var(--illus-surface, #fff); stroke: var(--illus-line, #334155); stroke-width: 2; }
.ep-muted { fill: var(--illus-muted, #cbd5e1); }
.ep-primary { fill: var(--illus-primary, #4f46e5); }
</style>
<defs>
<symbol id="ep-card" viewBox="0 0 56 40">
<rect class="ep-surface" x="1" y="1" width="54" height="38" rx="4"/>
<rect class="ep-muted" x="8" y="10" width="28" height="4" rx="2"/>
<rect class="ep-muted" x="8" y="20" width="40" height="4" rx="2"/>
</symbol>
</defs>
<rect class="ep-bg" width="240" height="160"/>
<ellipse class="ep-shadow" cx="120" cy="136" rx="84" ry="8"/>
<use href="#ep-card" x="40" y="56" width="56" height="40"/>
<use href="#ep-card" x="104" y="44" width="56" height="40" opacity=".6"/>
<g transform="translate(168 64)">
<rect class="ep-primary" width="40" height="40" rx="8"/>
<path d="M20 12v16M12 20h16" stroke="#fff" stroke-width="3" stroke-linecap="round"/>
</g>
</svg>
- Group related shapes in
<g>with a meaningfulidor comment; translate groups instead of editing every coordinate. hrefon<use>works in all current browsers;xlink:hrefis only needed for old tooling.- IDs and
<style>rules inside inline SVG are global in the page. Prefix both (ep-) when several inline SVGs can appear together, or one SVG’s rules will paint another.
5. Theming
- Inline SVG can use
currentColorand CSS custom properties, as in the example, so dark mode works by redefining variables. Putvar()in CSS (a<style>block orstyleattribute) rather than in presentation attributes, and give fallbacks. - SVG loaded via
<img>or CSSbackground-imagecannot read page CSS variables; bake colors in or ship light and dark files with<picture>andprefers-color-scheme. - In dark mode, swap rather than invert: lighter lines, darker surfaces, slightly lower saturation for large fills.
6. Patterns and backgrounds
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs>
<pattern id="dots" width="16" height="16" patternUnits="userSpaceOnUse">
<circle cx="2" cy="2" r="1.5" fill="currentColor" opacity=".25"/>
</pattern>
</defs>
<rect width="100%" height="100%" fill="url(#dots)"/>
</svg>
For CSS backgrounds, URL-encode the SVG (# becomes %23) in a data URI, or reference
a file. Hide tile edges by letting shapes that cross one edge reappear on the
opposite edge (draw them twice, offset by the tile size).
7. Animation (optional)
Animate transform and opacity with CSS; set transform-box: fill-box so
transform-origin refers to the shape itself:
.float { animation: float 4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
@keyframes float { 50% { transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { .float { animation: none; } }
Line-drawing effect: set stroke-dasharray and stroke-dashoffset to the path length
(pathLength="1" on the path lets you use 1 instead of measuring). Avoid SMIL for
anything important; CSS is easier to control and to disable.
Optimise and ship
npx svgo illus.svg -o illus.min.svg --multipass --precision 2 # needs network on first run
Check that optimisation kept viewBox, <title>, and the IDs your CSS or <use>
references. Inline SVGs used as React components: convert attributes to camelCase
(strokeWidth) or use SVGR.
Accessibility
- Meaningful illustration:
role="img"plus<title>(andaria-labelledby), with a short description of what it shows. - Decorative:
aria-hidden="true"andfocusable="false", or<img alt="">. - Never put essential information only in the illustration.
Gotchas
- Strokes scale with the viewBox. If the SVG is shown at very different sizes and stroke
weight must stay constant, use
vector-effect="non-scaling-stroke". - Huge path data from tracing tools is unmaintainable. Redraw with primitives.
- Filters (
feGaussianBlur,feDropShadow) are expensive when animated or used over large areas; use them sparingly, or pre-blur shapes with gradients. - Text in illustrations will not be translated and may lack its font; avoid it, or keep it as HTML outside the SVG.
Verification
- Render in a browser at the smallest and largest intended sizes, light and dark theme.
- Two copies on one page do not interfere (unique IDs).
- File under about 10 KB for spot illustrations after SVGO; inspect anything larger.
- Reduced-motion emulation (DevTools Rendering panel) stops all animation.
Related: logos and marks in $svg-logo-design; UI icon sets in $icon-systems;
algorithmic or randomised art in $generative-art.
What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "SVG Illustration"
short_description: "Hand-written SVG art you can still edit later"
default_prompt: "$svg-illustration Draw an SVG empty-state illustration for the projects page that works in dark mode" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.