Adding icons
Drop an SVG, add metadata, run one command.
Jedd Icons is built from source-of-truth SVGs in the repo. Adding an icon is easy and involves just three steps: drop the SVG, add metadata, run the build.
Drop the SVG
Save your file at icons/<variant>/<name>.svg using kebab-case, where
<variant> is stroke or fill. Icons must fit inside a 24×24 viewBox and
use strokes only (no fills on child elements). The canonical root attributes
are:
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="butt" stroke-linejoin="miter">
<!-- geometry only: <path>, <circle>, <rect>, <line>, <polygon>, <polyline> -->
</svg>Child elements should contain geometry attributes only (d, cx, r,
points, …) — not presentation attributes like stroke or fill. Those are
set on the root <svg> and inherited at render time so the color and
strokeWidth props work.
If your SVGs have inline presentation attributes on child elements (common
with design-tool exports), pnpm icons:clean strips them automatically and
normalizes the root attributes.
Design rules
- Stay inside the
24×24viewBox with ~1px padding on each side. - Stroke-only — no
fillon child elements. - Keep geometry flat: no
<g>groups,<defs>, or<mask>. The parser is intentionally simple.
Add metadata
Create icons/<variant>/<name>.json next to the SVG. The required fields are
$schema, contributors, tags, and categories:
{
"$schema": "../../icon.schema.json",
"contributors": ["yourname"],
"tags": ["search-keyword-1", "search-keyword-2"],
"categories": ["shapes"]
}The full set of fields lives in icon.schema.json at the repo root. Useful
optional fields:
{
"aliases": [{ "name": "older-name" }],
"deprecated": true,
"deprecationReason": "Use new-name instead"
}categories is an enum — valid values are listed in icon.schema.json.
Build everything
pnpm iconsThis single command runs the full pipeline:
icons:clean— normalizes root<svg>attributes and strips inline presentation attributes from child elements.icons:check— checks the normalized SVGs and their metadata without changing them, and stops on problems such as transforms, dots too short for Safari, geometry outside the 1px margin, or metadata that doesn't matchicon.schema.json.build— builds@jedd-icons/shared, generates the per-icon TS files, then builds@jedd-icons/coreand@jedd-icons/react.
Verify in the gallery
pnpm --filter www-docs devOpen the gallery, search for your icon by name, and use the sliders to confirm
the size / strokeWidth / color / absoluteStrokeWidth props behave.
Individual commands
| Command | What it does |
|---|---|
pnpm icons | Full pipeline: clean + check SVGs, then build all packages |
pnpm icons:clean | Normalize source SVGs (strip inline attrs, set root defaults) |
pnpm icons:check | Check source SVGs without changing them; exits 1 on errors |
pnpm build | Build all packages via Turbo |
pnpm --filter @jedd-icons/react gen | Regenerate icon TS files only |
pnpm --filter @jedd-icons/react build | Build the React package |
pnpm --filter @jedd-icons/react dev | Watch & rebuild on changes |
pnpm --filter www-docs dev | Run the gallery / docs site |
Changesets
If your change touches a published package (@jedd-icons/react or
@jedd-icons/core), add a changeset so it lands in the changelog:
pnpm changesetPick the package(s), choose a bump level, and write a one-line summary — that summary becomes the public changelog line. Docs-only, chore, and internal-package changes don't need one.
While the project is on 0.x, breaking changes ride on a minor bump:
patch for fixes and new icons, minor for features or breaking changes,
major reserved for 1.0.0.