Skip to content
jmlwebPublic

About

Turn a folder of SVGs into type-safe, cacheable SVG sprites. Zero client JS, Next.js Server Components and Astro.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

300 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

svgworm

Turn a folder of SVG files into type-safe, cacheable SVG sprites.
Zero client JavaScript, deterministic output, and adapters for Next.js Server Components, Astro, Vue and Svelte.

npm npm CI License: MIT

svgworm.com

svgworm turns a folder of SVG files into a hashed sprite, a manifest and types

const home = <Icon name="home" />; // <svg><use href="/icons/icons.f84bac71.svg#i-home"/></svg>
const nope = <Icon name="nope" />; // type error: "nope" is not an icon name

Why

  • Icons that render right, with no config. Each icon is mono (follows currentColor) or multicolor (keeps its colors). Gradients, masks and filters render in Chromium, Firefox and WebKit.
  • Zero client JS. The browser fetches one hashed sprite and caches it.
  • Type-safe names. A wrong icon name fails tsc.
  • No bundler plugin required. It is a CLI that writes files, so it works with Turbopack, webpack and Vite. Vite users can add the optional svgworm/vite plugin to rebuild icons inside vite dev.
  • Deterministic. The same input gives byte-identical output on every OS.

Get started

Requires Node ^22.20 || >=24.11, and React 19 for @svgworm/react. The example uses Next.js App Router.

1. Install and set up

pnpm add -D svgworm && pnpm add @svgworm/react && pnpm svgworm init
# npm: npm install -D svgworm && npm install @svgworm/react && npx svgworm init

init asks a few questions (or takes --yes), writes svgworm.config.json, adds predev and prebuild scripts, and creates components/icon.tsx (src/components/icon.tsx when src/ exists). When icons/ is missing or empty, it adds a sample icons/svgworm.svg. Then it builds once, so the app runs and type-checks before you add an icon.

2. Add your icons and build

Put SVG files in icons/ (delete the sample) and run pnpm svgworm (or npx svgworm). The build prints what it did (abridged):

svgworm: build done
  icons     8 (5 mono, 3 multicolor)
  delivery  use 6, img 2, mask 0
  output    3.5 KiB (sprite 2.2 KiB, stack 1.3 KiB)
  time      15 ms

3. Use the component in any Server Component

import { Icon } from '@/components/icon';

export const Nav = () => (
  <nav>
    <Icon name="home" />
    <Icon name="home" title="Go home" width={32} height={32} />
  </nav>
);

Tip

Names come from the file paths: home is icons/home.svg, lower-cased with - between words, and a wrong name is a type error. The icon is aria-hidden unless you pass title or label.

Commit public/icons/ and svgworm/ and run svgworm check in CI, or ignore both folders and rely on the predev/prebuild scripts. The Next.js guide weighs the two.

Also works with Astro, Vue (Nuxt) and Svelte (SvelteKit): svgworm init detects them and writes a React-free Icon.astro, Icon.vue or Icon.svelte, see the Astro, Vue and Svelte guides. Doing it by hand, long-term caching, and basePath are in the Next.js guide. A complete app, built with Turbopack and checked for zero client JS in CI, is in examples/next-app-router.

How it compares

If you... Use
Have your own icon folder in a Next.js App Router app svgworm
Want one tree-shaken component per icon and accept the JS cost SVGR
Need several sprites or a webpack plugin today @neodx/svg
Use Vite and all your icons are single-color vite-plugin-icons-spritesheet

The full comparison has spike numbers and says where each tool is the better choice.

Docs

  • Next.js guide: manual setup, caching for a year, basePath
  • Astro guide: the generated Icon.astro, caching, base
  • Vite guide: Vite + React, the optional svgworm/vite plugin, base, caching, examples/vite-react
  • Vue guide: the generated Icon.vue for Vue and Nuxt, base
  • Svelte guide: the generated Icon.svelte for Svelte and SvelteKit (static/), paths.base
  • Icon component: props, the markup per delivery, sizing and coloring
  • How it works: sprite, stack, delivery forms, manifest, determinism
  • ⌨️ CLI: commands, flags, exit codes, check in CI, watch
  • Config: svgworm.config.json and its JSON Schema
  • Output contract: exact shape of the generated files
  • Comparison: SVGR, @neodx/svg and others, with the numbers behind each claim
  • Migrate from SVGR: npx svgworm migrate svgr rewrites the imports into <Icon name="…" />
  • Troubleshooting: blank icons, 404s, wrong colors, collisions, every diagnostic code

For AI agents

Read llms.txt. Everything is non-interactive: flags, --json, stable exit codes, and a JSON Schema for the config. The agent skill walks an agent through setting svgworm up in a Next.js app and fixing each error code:

npx skills add jmlweb/svgworm --skill svgworm-nextjs

For an Astro site, use --skill svgworm-astro.

Status

Note

0.x, on npm since 2026-10-13. Before 1.0 the output contract and flags can still change in a minor version; each change is in the changelog.

Contributing

Issues and pull requests are welcome. Start with CONTRIBUTING.md and AGENTS.md. Background lives in docs/vision.md and the ADRs.

License

MIT

About

Turn a folder of SVGs into type-safe, cacheable SVG sprites. Zero client JS, Next.js Server Components and Astro.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages