OpenChamber uses an SVG sprite-based icon system for performance. Remixicon glyphs and explicitly registered custom glyphs are rendered via a single hidden SVG sprite injected into the DOM, referenced by `<use href="#oc-icon-name"/>`.
Custom product glyphs are registered in `scripts/generate-icon-sprite.mjs`. They must use the shared `24x24` viewbox and `currentColor` so they match Remixicon sizing and theme behavior.
-`sprite.ts` — Auto-generated SVG path data (run `bun run generate-icon-sprite` to regenerate)
-`Icon.tsx` — The `<Icon>` component, injects sprite on first mount
-`icons.ts` — TypeScript type `IconName`
The sprite is injected as a hidden `<svg id="openchamber-icon-sprite">` element containing `<symbol>` elements. Each `<Icon>` renders `<svg><use href="#oc-{name}"/></svg>`.
## Migration from @remixicon/react
Old:
```tsx
import{RiArrowDownSLine}from"@remixicon/react";
<RiArrowDownSLineclassName="h-4 w-4"/>
```
New:
```tsx
import{Icon}from"@/components/icon/Icon";
<Iconname="arrow-down-s"className="h-4 w-4"/>
```
If an icon is used as a component reference (not JSX):