CLI tool
natemoo-re/astro-icon avatar
natemoo-re/astro-icon

Astro Icon: inline SVG components for Astro projects

Inline and sprite-based SVGs in Astro made easy!

1,448 stars86 forksMDXNOASSERTION

At a glance

What is it?
Astro Icon gives Astro applications an `Icon` component for local SVGs and installed Iconify sets. It suits projects that want build-time SVGO optimization and direct control of the rendered `svg`, but server bundles require explicit icon filtering.
Who is it for?
Astro teams that want inline local or Iconify SVG components should adopt it after checking whether the Astro output mode matches the integration's bundling behavior. Projects that need runtime icon loading or a documented sprite mode should choose a different solution.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 59 days ago.
What is it written in?
Mainly MDX, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Astro Icon's place in an Astro application

Astro Icon solves a narrow but common problem in Astro projects: turning individual SVG assets into reusable Astro components without copying SVG markup into every template. Its intended users are developers building sites or applications with Astro who want to reference icons by a short `name` prop, use CSS classes directly on the resulting SVG, and avoid a separate browser-side icon runtime.

The integration supports two documented icon sources. Local icons are individual `.svg` files stored under `src/icons/` by default. Iconify icons come from installed `@iconify-json/*` packages and use names such as `mdi:account`. In both cases, the component inserts the selected SVG into the rendered HTML. The repository description also refers to sprite-based SVGs, but the README documents the inline component workflow and does not give a sprite configuration or usage example.

This is useful when icon styling, dimensions, accessibility metadata, and ordinary HTML attributes need to remain under Astro's control. It is a less suitable choice when icons must be fetched dynamically from a remote service, since the documented flow depends on local files or installed Iconify packages.

Installing Astro Icon and enabling the integration

The fastest documented setup uses Astro's integration command. Run the command for the package manager already used by the project, then accept Astro's prompts. The README presents three equivalent entry points.

bash
npx astro add astro-icon

The Yarn and pnpm variants target the same integration:

bash
yarn astro add astro-icon
bash
pnpm astro add astro-icon

For manual installation, add `astro-icon` to the Astro project, then register it through the `integrations` property. The repository package manifest requires Node.js `>=22.12.0` and declares `[email protected]` as its package manager. Those constraints belong to the repository workspace, so an application should compare them with its own toolchain before copying the configuration.

bash
npm install astro-icon

After installation, add the integration to `astro.config.mjs`:

js
import { defineConfig } from "astro/config";
import icon from "astro-icon";

export default defineConfig({
  integrations: [icon()],
});

A successful Astro build should then have access to `astro-icon/components`. The README does not define a standalone configuration file beyond the integration object in `astro.config.*`.

Rendering a first local SVG through Icon

The first real use starts with the asset layout. Create `src/icons/` inside the Astro project and place each local icon there as a separate `.svg` file. The README does not provide a command for creating directories or copying assets, so those filesystem operations are left outside the example. It also says local SVGs are optimized automatically with `svgo`, with no separate build step.

Suppose the file is `src/icons/filename.svg`. Import the component and pass its filename through `name`:

astro
---
import { Icon } from "astro-icon/components";
---

<!-- Loads the SVG in `/src/icons/filename.svg` -->
<Icon name="filename" />

The rendered result is an inline `svg`, not a browser request for a separate icon file. That matters when the design needs the icon to inherit CSS, accept component classes, or appear directly in server-rendered HTML.

For an Iconify set, install the set first. Material Design Icons is the README's example:

bash
npm i -D @iconify-json/mdi

Then use the set prefix and icon name:

astro
---
import { Icon } from "astro-icon/components";
---

<!-- Automatically fetches and inlines Material Design Icon's "account" SVG -->
<Icon name="mdi:account" />

The wording says the component automatically fetches and inlines the Iconify SVG, but the documented prerequisite remains the installed `@iconify-json/mdi` package. This is not an instruction to query Iconify at runtime.

SVG attributes, sizing, and accessibility

The `Icon` component exposes a small interface for controlling the generated SVG. `name` selects the icon. `size` can set a common dimension, while `width` and `height` provide separate controls. A title and description can also be supplied through `title` and `desc`. The optional `is:inline` prop appears in the documented TypeScript interface, although that section does not explain its exact effect.

The component extends `HTMLAttributes<"svg">` and accepts global HTML and `aria` attributes. According to the README, those attributes are forwarded to the rendered `<svg>` element. That makes selectors such as `class`, `id`, `aria-label`, and framework-provided classes part of the same rendering path rather than requiring a separate icon wrapper.

Styling can target every rendered icon through `[data-icon]`, or one icon name through `[data-icon="annotation"]`. A utility class can also be placed directly on the component:

astro
---
import { Icon } from "astro-icon/components";
---

<Icon name="adjustment" />
<!-- will be blue -->
<Icon name="annotation" />
<!-- will be red -->

<Icon name="annotation" class="text-red-500" />
<!-- will be red-500 -->

The README does not document how `size`, `width`, `height`, `title`, or `desc` interact in conflicting combinations. Developers requiring exact SVG semantics should inspect the generated markup and the referenced `packages/core/components/Icon.astro` implementation.

Server bundles and the Iconify include boundary

The main operational limitation appears in projects using Astro's `output: 'server'` or `output: 'hybrid'`. The README says every icon in a selected Iconify set is bundled into the server JavaScript by default. It therefore recommends setting `include` to the exact icons required by the application. A broad selector such as `"*"` loads the complete set, while a specific string limits that set to one icon.

js
import { defineConfig } from "astro/config";
import icon from "astro-icon";

export default defineConfig({
  integrations: [
    icon({
      include: {
        mdi: ["account"],
      },
    }),
  ],
});

This behavior makes `astro-icon` a poor fit for a large server-side application that needs only a few dynamic icon choices. Installing an entire Iconify package is already a dependency decision, while the default include policy can enlarge the server bundle further. An application that does not control its Iconify name space should confirm that every referenced icon matches the configured allowlist.

Local icons do not share the documented whole-set inclusion problem, but changing `iconDir` affects where the integration looks for them:

js
import { defineConfig } from "astro/config";
import icon from "astro-icon";

export default defineConfig({
  integrations: [
    icon({
      iconDir: "src/assets/icons",
    }),
  ],
});

The source asset move and corresponding `name` resolution must stay consistent. The README does not document runtime downloads, lazy icon retrieval, or automatic pruning of unused local files.

SVGO customization, licensing, and release upkeep

Local SVG optimization is automatic, but Astro Icon accepts `svgoOptions` for projects that need to alter the default transformation. The documented options include `multipass`, plugin configuration, and overrides for `inlineStyles` and `removeDoctype`. These are SVGO settings passed through the integration, so disabling a default plugin could change document structure or styling behavior in the output SVG.

js
import { defineConfig } from "astro/config";
import icon from "astro-icon";

export default defineConfig({
  integrations: [
    icon({
      svgoOptions: {
        multipass: true,
        plugins: [
          {
            name: "preset-default",
            params: {
              overrides: {
                inlineStyles: {
                  onlyMatchedOnce: false,
                },
              },
            },
          },
        ],
      },
    }),
  ],
});

That flexibility is useful when an SVG relies on details that the default optimizer would remove, but it makes output verification part of adopting custom settings. The repository does not provide an expected-output fixture in the available files.

There is also a licensing ambiguity that an engineering team should resolve before distribution. The repository metadata labels the license as a custom license that GitHub cannot classify, while the root `package.json` declares `"license": "MIT"`. The contents of `LICENSE` are not shown in the README, so neither declaration can be treated as definitive. This is not legal advice, but it is a concrete packaging issue: inspect `LICENSE` and the published `astro-icon` package metadata before redistribution.

For upkeep, the repository is not archived and its last push was on 2026-08-25. Version `1.2.0` was released on 2026-08-18, after `1.1.5` from 2024-12-26. The repository uses `.changeset/`, and its root versioning script runs Changesets followed by a pnpm lockfile update. That supports a structured release process, but the README's migration section is truncated and does not provide enough detail to assess every v1 breaking change from the available documentation.

Editorial conclusion

Astro teams that want inline local or Iconify SVG components should adopt it after checking whether the Astro output mode matches the integration's bundling behavior. Projects that need runtime icon loading or a documented sprite mode should choose a different solution. Before adoption, inspect `astro.config.*`, confirm the server-side `include` list, compare the repository `LICENSE` file with the package manifest, and verify that the required local icons and Iconify packages exist in the application.

Frequently asked questions

How do I install Astro Icon in an Astro project?

Run `npx astro add astro-icon` or use the documented Yarn or pnpm equivalent. For npm, manual setup uses `npm install astro-icon` and registers `icon()` in the `integrations` array in `astro.config.*`.

Does Astro Icon work with Iconify icon sets?

Yes. Install an `@iconify-json/*` package and reference an icon with the set prefix, such as `<Icon name="mdi:account" />`. The component then fetches and inlines the selected SVG according to the README.

Why should server and hybrid Astro projects configure an Iconify include list?

Without an exact include list, the README says every icon in the set is bundled into the server JavaScript. Configure `include` with the required icon names to restrict the server bundle.

Can local SVGs in Astro Icon be styled with CSS classes?

Yes. The rendered SVG supports forwarded attributes, including `class`, and `[data-icon]` can target icons generally. The README also shows name-specific selectors such as `[data-icon="annotation"]`.

What license does Astro Icon use?

The repository information is inconsistent: its metadata identifies a custom `LICENSE`, while the root `package.json` declares `"license": "MIT"`. The actual `LICENSE` file and published package metadata should be checked before adoption or redistribution.

Official sources

  1. Issues
  2. natemoo-re/astro-icon on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/natemoo-re-astro-icon.svg)](https://hysenlabs.com/projects/natemoo-re-astro-icon)

Was this useful?