Icons
Icons renders icon-related <link> tags from the build-time configuration resolved by the integration. The component is intentionally thin: file names, MIME types, and inferred sizes are computed before the virtual module is serialized, and the component only renders the resolved tags.
When you pass the icons prop, it merges over the integration-provided tags for that render. Matching entries are deduplicated by href, with later runtime entries overriding earlier build-time entries.
| prop | type | default | required | description |
|---|---|---|---|---|
icons | Record<string, IconTag | false> | {} | No | Per-href overrides. Each key is the tag’s href. An IconTag value replaces a matching build-time entry or adds a new one. false removes a matching build-time tag from the rendered output. |
Examples
Section titled “Examples”Input:
<Icons />Output:
<link rel="icon" href="/favicon.ico" type="image/x-icon" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" type="image/png"/>Automatic
Section titled “Automatic”When the integration is configured with an SVG source and no explicit favicon.svg entry, all five default icons are generated and a copied SVG favicon tag is automatically prepended. These are the defaults produced when only source is set:
favicon.ico— multi-size ICO (16, 32, 48)favicon.png— 32×32 raster faviconapple-touch-icon.png— 180×180 Apple touch iconicon-192.png— 192×192 manifest iconicon.png— 512×512 manifest icon
Input:
<Icons />Output:
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml" /><link rel="icon" href="/favicon.ico" type="image/x-icon" /><link rel="icon" href="/favicon.png" sizes="32x32" type="image/png" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" type="image/png"/><link rel="icon" href="/icon-192.png" sizes="192x192" type="image/png" /><link rel="icon" href="/icon.png" sizes="512x512" type="image/png" />Complete
Section titled “Complete”Input:
<Icons icons={{ "/favicon.ico": false, "/campaign.png": { rel: "icon", href: "/campaign.png", sizes: "32x32", type: "image/png", media: "dark", }, }}/>Output:
Assuming the integration resolved favicon.ico, favicon.svg, and apple-touch-icon.png into config.icons:
<link rel="icon" href="/favicon.svg" sizes="any" type="image/svg+xml" /><link rel="apple-touch-icon" href="/apple-touch-icon.png" sizes="180x180" type="image/png"/><link rel="icon" href="/campaign.png" sizes="32x32" type="image/png" media="(prefers-color-scheme: dark)"/>Decisions Made
Section titled “Decisions Made”Build-time resolution owns inference
Section titled “Build-time resolution owns inference”The integration resolves href, type, and inferred sizes before Icons renders. This avoids repeating file-extension logic in every page render and keeps the component surface small.
The runtime prop merges by href
Section titled “The runtime prop merges by href”The icons prop is a Record keyed by each tag’s href. An IconTag value replaces the matching build-time entry (or appends a new one); false removes the matching build-time entry entirely. Entries not mentioned in the prop are passed through unchanged.
Light and dark media values expand automatically
Section titled “Light and dark media values expand automatically”When a tag uses media: "light" or media: "dark", the component expands that shorthand into the matching prefers-color-scheme query. Other custom media strings are passed through unchanged.
Deduplication is runtime-only and href-based
Section titled “Deduplication is runtime-only and href-based”Build-time resolution preserves the raw tag array. Icons loads all config tags into an href-keyed map, then applies the icons prop entries — replacing or deleting matching hrefs — so the final render order follows insertion order with prop modifications layered on top.
Source code
Section titled “Source code”---import type { IconTag } from "../integration/generate-icons";import config from "virtual:eminence-astro-suite/head-tags";
interface Props { /** * Late-bound `<link>` tag overrides. * These are merged over the build-time resolved icon tags from the virtual module. */ /** * Per-href overrides keyed by the tag's `href` value. * An `IconTag` value replaces the matching build-time tag or adds a new one. * `false` removes the matching build-time tag from the rendered output. */ icons?: Record<string, IconTag | false>;}
const { icons: overrideIcons } = Astro.props;
const iconTagsMap = new Map<string, IconTag>();
for (const iconTag of config.icons ?? []) { iconTagsMap.set(iconTag.href, iconTag);}
for (const [href, iconTag] of Object.entries(overrideIcons ?? {})) { if (iconTag === false) { iconTagsMap.delete(href); } else { iconTagsMap.set(href, { ...iconTag, href }); }}
const iconTagsToRender = Array.from(iconTagsMap.values());
const resolveMedia = (media: IconTag["media"]): string | undefined => { if (media === undefined) { return undefined; }
if (media === "light" || media === "dark") { return `(prefers-color-scheme: ${media})`; }
return media;};---
{ iconTagsToRender.map(({ media, ...iconTag }) => ( <link {...iconTag} media={resolveMedia(media)} /> ))}