Icons
Feature logic never references an icon — an icon is pure presentation. @evolve-storefront/ui
owns one module mapping semantic names to SVG components, and that map is the single override
seam. Components render <Icon name="shoppingList" />, never a scattered
import { ShoppingBag } from "lucide-react".
Name icons by role, not shape: shoppingList and remove, not shopping-bag and trash. A
brand that wants a heart instead of a bag remaps one entry and the meaning stays stable everywhere.
Restyle every icon
Section titled “Restyle every icon”[data-component="icon"] { @apply size-5 text-primary;}Swap one icon at one call site
Section titled “Swap one icon at one call site”Components that render an icon accept it as a prop. A ReactNode crosses the RSC boundary fine.
<AddToShoppingListButton icon={<HeartIcon />} />Swap an icon, or the whole set, everywhere
Section titled “Swap an icon, or the whole set, everywhere”Spread the defaults and override the keys you want:
// src/ui/icons.tsimport { icons as base } from "@evolve-storefront/ui/icons";import { BrandList } from "#icons";
export const icons = { ...base, shoppingList: BrandList };export type IconName = keyof typeof icons;Pointing packages at that file means aliasing the subpath, which is the escape hatch — see the alias band in the parent skill before doing it. Switching icon library outright is the one case that genuinely earns it: it is a markup change, it applies build-wide by nature, and it touches no feature package and no page.
Avoid an SVG sprite sheet (awkward per-icon tree-shaking and override) and a runtime context icon provider (unreadable in Server Components). Per-icon React components behind the semantic map give both tree-shaking and clean overrides.

