The SvgIcon Component: Inline, Sprite and External Icons
One component, four loading modes, and SVGO cleanup in the build, so icons stay small, themeable and cache-friendly.

Icons are small, but a page can carry dozens of them. SvgIcon lets each icon choose how it loads, and a build step cleans every source file first.
Four modes
| Mode | What it does | Use it for |
|---|---|---|
inline |
Prints the mono SVG markup into the page | Icons above the fold, with no extra request |
internal-sprite |
References a generated theme sprite | Repeated UI icons shared across pages |
local-url |
Starts from a tiny placeholder, then swaps in a local SVG file | Icons far down the page |
external-url |
Same lazy swap, from an external image URL | Brand marks hosted elsewhere |
Older force values (inline, sprite, external, file) still work.
<SvgIcon name="email" group="common" size="md" mode="inline" decorative={true} />
Mono and brand icons
Mono icons live in icons/mono/ (core) and src/site/assets/icons/mono/ (your project) and use currentColor, so they follow the surrounding text colour in light and dark themes. Brand icons keep their original colours and are served as single files.
Cleanup during the build
core/scripts/build/icons.mjs runs each source file through SVGO with the options in src/site/config/svg-optimization.mjs. The configuration keeps the viewBox and titles, adds a missing viewBox from the width and height, and warns when a mono icon hard-codes a fill or stroke instead of currentColor. The same pipeline produces the sprite files, which are hashed so they can be cached for a long time.
Accessibility
Pass decorative={true} for icons that repeat adjacent text, or a title when the icon carries meaning on its own.