From Design to Code: Shipping Icons That Don't Break Your Build
Designer-exported SVGs routinely carry 10-100x more data than they need — editor metadata, embedded thumbnails, base64 junk. Here is a practical pipeline for turning design assets into clean, type-safe, accessible components.
Icora Team
Engineering

If you have never opened an SVG in a text editor, try it with the next one a design tool hands you. Depending on the export settings, a simple 24x24 icon can arrive carrying editor metadata, layer names, embedded raster thumbnails, and base64-encoded junk — Illustrator's "Preserve Illustrator Editing Capabilities" option alone can turn a 1KB icon into a few hundred kilobytes. Multiply that by an icon library and it quietly becomes a real bundle-size problem.
The fix starts with a mindset shift: in a modern web application, an icon is not an image. It is code. It is a React component, a function that returns JSX. It deserves the same review standards as the rest of your codebase.
Bad SVG vs Good SVG
Here is the anatomy of a typical unprocessed export, abbreviated:
<!-- BAD SVG -->
<svg xmlns:x="adobe:ns:meta/" width="24" height="24">
<metadata>...</metadata>
<g id="Layer_1" data-name="Layer 1">
<g>
<image width="500" height="500" href="data:image/png;base64,..." />
</g>
</g>
</svg>And here is what the same icon should look like:
<!-- GOOD SVG -->
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M18 6L6 18M6 6l12 12" />
</svg>The differences are not cosmetic. The fixed width/height makes the first one rigid; the viewBox makes the second one scale anywhere. The embedded image makes the first one a bitmap in disguise; the path makes the second one a true vector. And stroke="currentColor" means the clean version inherits its color from CSS — one asset works in light mode, dark mode, and every brand theme.
A Three-Step Icon Pipeline
Every icon should pass through the same gate before entering your codebase:
- The Purge: Automated removal of all
xml,doctype,metadata, and editor-namespace tags. SVGO with its default preset handles most of this. - The Precision Cut: Rounding coordinates to 1-2 decimal places. Nobody can see the difference between 11.999998 and 12, but your bundle can.
- The Componentization: Wrapping the cleaned SVG in a typed,
forwardReffunctional component that accepts size, color, and ARIA props.
Tree Shaking & Imports
A related and equally common mistake is importing a massive icon library just to use a handful of icons. If your bundler cannot tree-shake the package (and barrel files often defeat it), you ship thousands of icons your users never see. Prefer per-icon imports:
// Risky: may pull in the whole library
import { Icon } from "massive-library";
// Safe: imports exactly one icon
import { IconHome } from "massive-library/home";Accessibility (ARIA)
An icon without a label is invisible to a screen reader — or worse, announced as "unlabeled graphic." Your icon components need two modes: decorative icons should carry aria-hidden="true", and meaningful icons (like an icon-only button) must accept an aria-label or render a <title> element. Build both into the component API so doing the right thing is the default.
How much does the cleanup matter? Results vary with the source file, but running typical design-tool exports through an optimizer looks like this:
| Metric | Raw Export | Optimized | Typical Reduction |
|---|---|---|---|
| Single icon | 8-15KB | 0.5-2KB | 80-90% |
| Path points | Hundreds | Dozens | ~80% |
| Set of 50 icons | 400KB+ | Under 100KB | 75%+ |
This pipeline is the engine behind Icora's "Export Code" feature: cleanup, precision rounding, and componentization run automatically, so what you copy out is the optimized, accessible component — not the raw export.
Try Icora FreeFound this helpful? Share it!
Ready to Create Stunning Icons?
Put these principles into practice with Icora's AI-powered icon generator, professional studio tools, and developer-ready export.
Start Creating Free