nuxt-compose-icons
| Install | |
|---|---|
npm install nuxt-compose-icons |
|
| Latest Version: | 0.12.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 21, 2026 |
| Links: | GitHub · npm |
Nuxt-Compose-Icons
CI gates every PR on unit + e2e tests, lint, and a full build (module, playground, showcase, docs) across Node 22 & 24 — not just formatting. → Latest run
flowchart LR
L[Lint · Style · Format] --> B[Build<br/>module · playground · showcase · docs]
T[Unit + E2E Tests] --> B
B -->|push to main| D[Deploy docs & showcase]
This module generates fully customizable Vue components from your initial raw SVG files at build time, and gives you:
- 🧩 The flexibility of raw SVG
- 🎨 Theming control:
- At build time via configuration
- At runtime via CSS variables
- 🏔 ️Native Nuxt auto-import support
For building design systems or simply use in-house icons.
Used in production at reteach
📦 Installation
Using pnpm:
pnpm add nuxt-compose-icons
Using npm
npm install nuxt-compose-icons
Using yarn
yarn add nuxt-compose-icons
🛠 Quick start
1. Add to nuxt.config.ts:
export default defineNuxtConfig({
modules: ['nuxt-compose-icons'],
composeIcons: {
pathToIcons: './assets/icons',
},
});
2. Drop your SVGs in ./assets/icons
3. Use them anywhere — no imports needed:
<template>
<ArrowUpIcon size="md" color="var(--primary)" />
<UserBadgeIcon size="lg" fill="currentColor" />
</template>
That's it. Every .svg becomes a typed, auto-imported Vue component.
🎯 Motivation
Existing icon solutions often force trade-offs between DX, accessibility, and flexibility:
- Third-party libraries → limited customization
- Manual Vue components → repetitive and hard to scale
- SVG loaders → flexible but lack structure and typing
| Feature | Third-party Libraries | Manual Vue Components | SVG Loaders (vite-svg-loader) |
Nuxt Compose Icons |
|---|---|---|---|---|
| Setup | ✅ Easy | ⚠️ Manual | ⚠️ Requires config | ✅ Minimal |
| Source of truth | External package | Vue files | SVG files | SVG files |
| SVG output | Clean (often wrapped) | Custom | Inline | Clean, no wrappers |
| SVG control | Often abstracted | ✅ Full | ✅ Full | ✅ Full |
| Theming | ⚠️ Prop-based, limited | ✅ Manual CSS | ✅ CSS-based | ✅ CSS variables + props |
| Naming consistency | Library-defined | Developer-defined | File-based | Deterministic, file-based |
| Typing | ✅ Provided | ✅ Manual | Depends on setup | ✅ Generated & inferred |
| Scaling | Dependent on library updates | Maintenance-heavy | Flexible but unstructured | Structured, build-generated |
| Nuxt integration | ✅ Works | ✅ Auto-importable | ⚠️ Requires configuration | ✅ Native auto-import |
@nuxt/icon is the most common example of the "Third-party Libraries" column above.
nuxt-icons doesn't fit that column — it's
bring-your-own-SVG like this module — but it's a runtime name-lookup (<nuxt-icon name="..." />
injecting SVG markup at render time) rather than generating standalone components, so it lands
on the same side of that specific distinction as @nuxt/icon.
Nuxt also has an excellent official icon module, @nuxt/icon — for a huge, ready-made icon set with zero setup, use it. This module solves a different problem: turning your own SVG files into standalone, ownable Vue components, for a design system or an in-house icon library, without the trade-offs above.
→ How this compares to @nuxt/icon · Common Approaches
Features
- SVG to Vue Component at build time — one component per
.svgfile, named in PascalCase or kebab-case with optional prefix/suffix - Auto-registered in Nuxt — no manual imports, type-safe usage in
<template> - No wrappers — the component root is a single
<svg>element, original attributes preserved - Theming via CSS Custom Properties —
fill,stroke,stroke-widthbecomevar(--icon-*, original), overridable via props, cascading styles, or scoped CSS - Developer Experience — full autocompletion/type-checking, and Vue DevTools support since generated icons are real components
<!-- Input: user-badge.svg -->
<svg fill="#000" stroke="#fff" stroke-width="2">
<path d="..." />
</svg>
<!-- Output: UserBadgeIcon.vue -->
<template>
<svg
fill="var(--icon-fill, #000)"
stroke="var(--icon-stroke, #fff)"
stroke-width="var(--icon-stroke-width, 2)"
>
<path d="..." />
</svg>
</template>
<!-- Theme it -->
<template>
<UserBadgeIcon stroke="blue" fill="red" size="lg" />
</template>
→ Full feature list with examples
Own your components
Each icon is a real, standalone Vue component — not a runtime lookup like @nuxt/icon's <Icon name="my:user-badge" /> or nuxt-icons' <nuxt-icon name="user-badge" />. That distinction matters once icons need to live outside a single Nuxt app:
- The generated
.vue/.tsfiles are committed to your repo, versioned like any other component - A UI library can ship
<UserBadgeIcon />directly — apps that consume the UI library never install or configurenuxt-compose-iconsthemselves (the UI library still does, as a normal dependency, since the generated components import from it) - Set
component.destDirand acompose-icons.cssfile is generated alongside the components, with your project's actual theme baked in — commit both, and that's everything a downstream consumer needs for full theming - Add
component.hasIndexFile: truefor anindex.tsbarrel that re-exports every icon — one import for the whole set - Add a new icon, rebuild — no separate publish/sync step to keep a design system's icon set current
→ Monorepo guide — with a live example repo (Nx + pnpm)
Schema
📖 Documentation
Full documentation and advanced configuration:
👉 https://nuxt-compose-icons.dev
27d19cf (iconSizes refactor option - full replace)
▶️ Try it
🗺 Roadmap
Related Packages
Nuxt module for easily integrating Solar Icons into your Nuxt 3+ applications.
Nuxt module to load SVG files as Vue components, using SVGO for optimization.
Version History
| Version | Released | License |
|---|---|---|
| 0.12.0 | MIT | |
| 0.11.3 | MIT | |
| 0.11.2 | MIT | |
| 0.11.1 | MIT | |
| 0.11.0 | MIT | |
| 0.10.0 | MIT | |
| 0.9.0 | MIT | |
| 0.8.0 | MIT | |
| 0.7.0 | MIT | |
| 0.6.9 | MIT | |
| 0.6.8 | MIT | |
| 0.6.7 | MIT | |
| 0.6.6 | MIT | |
| 0.6.5 | MIT | |
| 0.6.4 | MIT | |
| 0.6.3 | MIT | |
| 0.6.2 | MIT | |
| 0.6.1 | MIT | |
| 0.6.0 | MIT | |
| 0.5.2 | MIT | |
| 0.5.1 | MIT | |
| 0.5.0 | MIT | |
| 0.4.6 | MIT | |
| 0.4.5 | MIT | |
| 0.4.4 | MIT | |
| 0.4.3 | MIT | |
| 0.4.2 | MIT | |
| 0.4.1 | MIT | |
| 0.4.0 | MIT | |
| 0.3.0 | MIT |
Showing the latest 30 of 44. See every release on npm