Help us improve
Share bugs, ideas, or general feedback.
From svg-creator
Creates, edits, reviews, and validates high-quality SVG graphics with W3C compliance, CSS independence, accessibility, and safety.
npx claudepluginhub jawwadfirdousi/agent-skills --plugin svg-creatorHow this skill is triggered — by the user, by Claude, or both
Slash command
/svg-creator:svg-creatorThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Produce SVGs that are spec-correct (W3C SVG 2), **CSS-independent**, accessible when meaningful, safe to render in untrusted contexts, optimized in size, and readable enough to edit.
agents/openai.yamlexamples/document-scanner.svgexamples/heart.svgexamples/paper-plane.svgexamples/search.svgexamples/spinner.svgexamples/star.svgexamples/sun.svgexamples/wave.svgexamples/waving-beach.svgreferences/svg-path-guide.mdreferences/svg-quality-standard.mdreferences/svg-security.mdreferences/svg-templates.mdreferences/svg-validation-checklist.mdscripts/validate_svg.pyGenerates and edits SVG logos, icons, and graphics. Covers path commands, shape primitives, styling, accessibility, gradients, masks, sprites, optimization, and animation techniques like CSS keyframes and SVG-specific methods.
Generates dark-themed standalone SVG diagrams for architecture, flowcharts, sequence diagrams, mind maps, timelines, state machines, data flows, and more.
Optimizes SVGs with SVGO minification, compares inline/external delivery and sprite sheets, improves accessibility attributes, and enhances rendering performance for icon systems and complex graphics.
Share bugs, ideas, or general feedback.
Produce SVGs that are spec-correct (W3C SVG 2), CSS-independent, accessible when meaningful, safe to render in untrusted contexts, optimized in size, and readable enough to edit.
The SVG must render identically in any compliant renderer — Chrome, Inkscape, librsvg, CairoSVG, native iOS/Android SVG support, COLR/SVG fonts, design tools, server-side rasterizers — without depending on a CSS engine, an HTML host, or external stylesheets. This means:
<style> element. Use presentation attributes (fill="...", stroke="...", opacity="...") instead of CSS rules.style="..." attribute on elements. Same reason.currentColor unless the user explicitly asks for an icon themeable via CSS color. currentColor resolves through the CSS cascade; renderers without CSS fall back to black.var(--name)).@keyframes, animation: shorthand). For motion, use SMIL elements: <animate>, <animateTransform>, <animateMotion>, <set>.:hover / :focus rules. Interactivity that requires CSS belongs in the host page, not in the SVG.@import, no external fonts, no remote <image> hrefs.When the user explicitly opts in to web-only output ("for an HTML icon system", "themeable via parent color", "use Tailwind classes"), currentColor and a minimal <style> block are acceptable. Otherwise default to pure SVG.
xmlns="http://www.w3.org/2000/svg" on the root <svg>. It is required for standalone SVG, <img src>, and copy-paste portability; only HTML5 inline-SVG tolerates its absence.viewBox. The attribute name is camelCase (viewBox, not viewbox). Format: min-x min-y width height, four finite numbers, width and height positive.preserveAspectRatio is xMidYMid meet. Set it explicitly only when you need cropping (slice) or non-uniform stretch (none).version or baseProfile attributes.<!DOCTYPE>, <!ENTITY>, or <?xml-stylesheet?>. Plain <?xml ?> declaration is allowed but unnecessary inside HTML.viewBox="0 0 24 24", stroke 1.5–2.viewBox="0 0 64 64".viewBox="0 0 512 512" or 0 0 1200 800.0 0 800 500).Keep all rendered geometry inside the viewBox. Strokes that touch an edge will be clipped by half their stroke-width unless inset.
M or m. After M, extra coordinate pairs are implicit L/l commands; after m, implicit l.S/s, T/t) reflect the previous control point only if the previous command was the matching curve type (C/c for S; Q/q for T). Otherwise the inferred control point collapses to the current point and produces a degenerate curve. Never emit S after L.rx ry x-axis-rotation large-arc-flag sweep-flag x y. Flags must be 0 or 1. The path-data parser treats arc flags as a single digit each; do not write 10 thinking it means "1, 0".fill defaults to black, stroke defaults to none. A bare <path d="..."/> renders solid black. For a stroke-only icon, set fill="none" and a stroke explicitly.fill="#3b82f6", stroke="#0f172a". Avoid currentColor by default; reach for it only when the user explicitly asks for a CSS-themeable icon (and only on the targeted shape, not as a global default).stroke-linecap="round" and stroke-linejoin="round" for friendly UI icons and organic line art. Use miter only for sharp technical/geometric styles, and set stroke-miterlimit to avoid spikes at sharp joins.vector-effect="non-scaling-stroke".paint-order defaults to fill stroke markers. To outline text without eating into letterforms, set paint-order="stroke" on <text>.fill-rule defaults to nonzero. For shapes drawn as nested sub-paths where direction matters, consider fill-rule="evenodd".id must be unique. Prefix with the subject (mountain-gradient-a, chart-clip, arrow-marker).url(#id) and href="#id" must resolve. Sanitize both href and xlink:href; legacy xlink:href still resolves if href is absent.xlink:href in new output. SVG 2 supports plain href everywhere.gradientUnits default is objectBoundingBox (x1/y1/x2/y2 are 0–1 fractions of the filled element's bounding box). Use userSpaceOnUse when you want absolute placement.x1=0% y1=0% x2=100% y2=0%. Set vectors explicitly when you want diagonal or vertical gradients.spreadMethod defaults to pad. Use reflect or repeat only intentionally.[0, 1].clipPath is binary (in or out, no soft edge). mask is alpha or luminance, allowing soft edges and gradients.clipPathUnits defaults to userSpaceOnUse. maskUnits defaults to objectBoundingBox. They are opposite. Set explicitly when in doubt.mask defaults to mask-type="luminance": white pixels show, black pixels hide. Naive masks drawn with default colors render as invisible. Either set mask-type="alpha" or use white fills.x="-10%" y="-10%" width="120%" height="120%". This expands the source bounds 10% on each side. Effects extending further (drop shadows, glows, large blurs) get clipped. For a shadow with dy=8 stdDeviation=10, expand to e.g. x="-25%" y="-25%" width="150%" height="150%".feDropShadow is the safest way to draw a shadow. It consolidates blur + offset + flood + composite + merge into one element.feMerge stacks <feMergeNode> children bottom-to-top in document order.color-interpolation-filters defaults to linearRGB (not sRGB). For color-accurate blending against non-filtered content, set color-interpolation-filters="sRGB" on the <filter>.feTurbulence, feMorphology, feDisplacementMap, feConvolveMatrix rasterize per frame. Cache or pre-render.markerUnits defaults to strokeWidth: marker dimensions scale with the host stroke. Use userSpaceOnUse to fix marker size regardless of stroke.orient="auto" rotates the marker to match path direction; auto-start-reverse lets one arrowhead serve both ends.fill="context-stroke" on the marker's geometry so the arrowhead inherits the line's color.For SVGs that carry meaning (illustrations, charts, diagrams, meaningful logos):
role="img" on the root for atomic graphics. Use role="graphics-document" (subclass of document) for charts/maps/diagrams whose layout conveys meaning, with children navigable. Use role="graphics-symbol" (subclass of img) for atomic glyphs whose meaning matters more than visual detail.<title> and <desc> as the first direct children of the root. Spec allows them anywhere among children, but several screen readers historically required first-child placement.aria-labelledby="<title-id> <desc-id>". aria-labelledby and aria-describedby take precedence over <title>/<desc> for accessible name/description computation.<title> and at most one <desc> per element.For purely decorative SVGs (next to visible text, button icons with labels, ambient marks):
aria-hidden="true" and focusable="false". The latter suppresses a legacy IE/Edge focus quirk.role="img" simultaneously with aria-hidden="true".<script> element.on (event handlers including onclick, onload, onerror, onbegin, onend, onrepeat, onzoom).javascript: URLs in href, xlink:href, or any URL-bearing attribute.<foreignObject> (full HTML inside SVG, the highest-risk element).<image>, <use>, <feImage>, <a>, CSS url(...), @import, @font-face. Allow only fragment refs (#id).data: URLs limited to image/png, image/jpeg, image/gif, image/webp in <image href>. Never data:image/svg+xml (equivalent to inline SVG).<!DOCTYPE>, <!ENTITY> (XXE), <?xml-stylesheet?> PI.to/from/values change href/xlink:href to javascript: or data:image/svg+xml.For output that may end up in untrusted hands, recommend the consumer pass it through DOMPurify with USE_PROFILES: { svg: true, svgFilters: true }, and parse server-side with external entity resolution disabled (defusedxml in Python, disallow-doctype-decl feature in Java).
For CSS-independent SVG, animation is always SMIL — declarative animation elements baked into the SVG document. CSS animations require a CSS engine the renderer may not have.
<animate> for scalar attributes (cx, r, opacity, fill, stroke-width, etc.).<animateTransform> for transform animation. The type attribute is required: translate, scale, rotate, skewX, skewY. Never use <animate attributeName="transform"> — that doesn't work.<animateMotion> for path-following motion. Provide a path attribute or a child <mpath href="#path-id"/>. Optional rotate="auto" aligns the moved element to the path tangent.<set> for instantaneous attribute changes at a begin time (no interpolation).attributeName (case-sensitive, kebab-case e.g. stroke-width), one of from+to / by / values, and dur.repeatCount is 1. Use repeatCount="indefinite" to loop. fill="freeze" keeps the end state at animation completion instead of reverting; fill="remove" (default) reverts.values="a;b;c;d" with optional keyTimes="0;0.25;0.5;1" (lengths must match) and calcMode="linear" (default), discrete, paced, or spline (with keySplines).begin="otherAnim.end" and begin="elementId.click" to chain animations declaratively.prefers-reduced-motion automatically. For inclusive output, keep motion subtle, brief, looping, and never essential to comprehension. Always provide a static equivalent when motion isn't required by the brief.Reference and full element list: W3Schools SVG Animation, MDN SMIL animation.
mergePaths mentally when authoring.<filter> chain rather than nesting filters across groups.Identify the output type: icon, logo, illustration, diagram, chart, pattern, animation, or markup repair.
Resolve missing brief details with sensible defaults (do not interrogate the user) unless brand colors, exact dimensions, or a sensitive logo recreation are involved.
Plan before drawing: pick viewBox, palette, accessibility mode, and target size.
Write the SVG as clean, indented standalone markup with stable IDs and meaningful group names.
Validate before returning, when code execution is available:
python3 ${CLAUDE_SKILL_DIR}/scripts/validate_svg.py output.svg --strict
Fix every reported error and rerun until clean.
If code execution is unavailable, manually apply references/svg-validation-checklist.md.
Return either a complete .svg file or a complete inline <svg> element. For markup repair, return the full corrected SVG, not a patch.
Read these on demand only:
references/svg-quality-standard.md for detailed illustrations, logos, diagrams, patterns, or anything where aesthetics matter.references/svg-templates.md when starting from a blank prompt or producing a specific SVG type.references/svg-path-guide.md before writing or repairing complex d data, especially smooth curves and arcs.references/svg-security.md when output may be rendered in untrusted contexts, or when reviewing/sanitizing existing SVG.references/svg-validation-checklist.md when the validator script can't run.For new SVGs, produce one of:
.svg file with valid XML and resolved references.<svg> element suitable for HTML.For SVG repair, return the corrected complete SVG. For sets (icon families, multi-state graphics), use a consistent coordinate system, stroke language, ID prefix, and palette across all members.
<style> and style="..." break portability. A renderer without a CSS engine ignores them. Use presentation attributes.currentColor defaults to black in non-CSS renderers. Use explicit colors unless the user asks for CSS theming.viewBox is camelCase. viewbox silently fails in strict XML parsing.fill default is black. Forgetting fill="none" on a stroked outline produces a solid black blob.mask-type default is luminance. White-on-black masks reveal; alpha-style masks need mask-type="alpha".A 25,25 0 016,3 parses as flags 0, 1 then number 6.S/T after a non-matching curve degenerate. Always pair C→S and Q→T.href and xlink:href must be sanitized; the deprecated form still resolves.<animate attributeName="transform"> does not work; use <animateTransform type="...">.data:image/svg+xml URLs are equivalent to inline SVG and unsafe in <image href>.