Skip to content

Features ​

Compose your own Icon components library, from SVG files to customizable Vue Components that you own.

Build-time SVG to Vue Component: ​

  • One Vue component is created per .svg file
  • Use of the initial name of the icon, converted to PascalCase or snake-case with optional prefix and suffix. Example user-badge.svg can give:
    • <IconUserBadge />
    • <UserBadgeIcon />
    • <user-badge />
  • Optional support for folder-based namespacing - icon Components can directly be generated in your codebase, making versioning possible

Auto-Registration in Nuxt and Typing ​

  • Full auto-import support (no manual registration) - each icon will be automatically imported and registered in the Nuxt project as individual Vue component in the tree
  • Type-safe usage in <template>
  • Works with Volar, <script setup>, and TSX

SVG Output - Accessibility ​

  • Components render a single <svg> element
  • No additional wrappers or nested templates
  • Attributes from the original SVG are preserved

Theming with CSS Custom Properties and Runtime Access ​

  • fill, stroke, and stroke-width are replaced with CSS Custom Properties (CSS Custom Properties Guide) making theming directly possible
  • Original values are preserved as fallbacks
  • Since CSS Custom Properties work at runtime, they can be used to dynamically change icons components in cascade for each individual icons and property (fill, stroke, stroke-width, etc.)
  • Compatible with global tokens or scoped styles

Developer Experience: ​

  • Can provide auto-completion and type-checking in your editor for each icons, as they are directly part of the Nuxt Build like any other component
  • Vue DevTools support - unlike other solutions, this module generates Vue components that can be inspected and debugged in the Vue DevTools

The aim is to combine the control and quality of hand-authored components with the scalability and consistency of a build tool.

Comparison with Other Icon Strategies ​

FeatureThird-party LibrariesManual Vue ComponentsSVG Loaders (vite-svg-loader)Nuxt Compose Icons
Setup✅ Easy⚠️ Manual⚠️ Requires config✅ Minimal
Source of truthExternal packageVue filesSVG filesSVG files
SVG outputClean (often wrapped)CustomInlineClean, no wrappers
SVG controlOften abstracted✅ Full✅ Full✅ Full
Theming⚠️ Prop-based, limited✅ Manual CSS✅ CSS-based✅ CSS variables + props
Naming consistencyLibrary-definedDeveloper-definedFile-basedDeterministic, file-based
Typing✅ Provided✅ ManualDepends on setup✅ Generated & inferred
ScalingDependent on library updatesMaintenance-heavyFlexible but unstructuredStructured, 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. If you're specifically weighing this module against @nuxt/icon, here's a direct comparison:

How This Compares to @nuxt/icon ​

Nuxt already has an excellent official icon module, @nuxt/icon — if you want instant access to a huge, ready-made icon set (Iconify, emoji, custom collections) with zero setup, use it.

nuxt-compose-icons solves a different problem: turning your own SVG files into standalone, ownable Vue components — for a design system or an in-house icon library, where the icons need to exist as real components in your codebase, not just a runtime lookup.

@nuxt/iconNuxt Compose Icons
Best forA large, ready-made icon setYour own SVGs — a design system or in-house icon library
Usage<Icon name="my:user-badge" /> — a string-name lookup<UserBadgeIcon /> — a real, individually importable component
OwnershipIcons live inside the module's runtime/collectionGenerated files in your repo — committed and versioned like any other component
Usable without the moduleNo — needs <Icon> and the collection registeredYes — a generated file is a plain .vue/.ts component; a UI library can ship it without depending on this module at runtime
ThemingPer-usage customize() callback, or CSS overrides on <Icon>fill/stroke/stroke-width become CSS variables on the SVG itself — cascades naturally through design tokens
NamingIconify name rules (kebab-case only)Derived from your filename — accepts whatever your design tool exports

When to reach for @nuxt/icon instead ​

  • You want instant access to a large, pre-built icon set without maintaining your own SVGs
  • You don't need the generated icons to exist independently of Nuxt — e.g. consumed by a separate UI library that shouldn't depend on this module
  • Per-icon customization via a JS callback fits your styling approach better than CSS variables

Both modules can coexist in the same project — reach for whichever fits the icon at hand.