reedware/nova-icons
Adds icon support to Laravel Nova, letting you display icons alongside resources, fields, and navigation items so your admin panel is easier to scan at a glance. Lightweight and simple to configure in any Nova application.
Install via Composer alongside Nova 3.x:
composer require reedware/nova-icons
The package ships a service provider that registers Vue components globally into the Nova asset pipeline — you typically do not need to publish anything to get started. Check vendor/reedware/nova-icons/src/ first to see what's actually exported:
src/ — the service provider (look for Nova::script(...) or Nova::provideToScript(...) calls that push the compiled JS).resources/js/ — the Vue component source files (this is where you'll find the actual <template> markup and the component names).dist/ — the compiled bundle that Nova loads at runtime.The first use case is dropping an icon into a custom Nova card or tool. In your Vue component:
<template>
<div class="card">
<nova-icon name="user" />
<span>{{ label }}</span>
</div>
</template>
Then register your custom component the usual Nova way (Nova::script('my-card', __DIR__.'/../dist/js/card.js')) and npm run dev from your package directory. You should see the icon render inside the Nova layout.
Injecting icons into custom fields. Nova fields are Vue components; if the package registers globally (via Vue.component(...) inside its entry), you can reference the icon tag directly in the field's template without a local import:
<template>
<default-field :field="field">
<template #field>
<nova-icon :name="field.icon" class="mr-2" />
<input v-model="value" class="w-full form-control" />
</template>
</default-field>
</template>
Driving icons from PHP config. Since Nova exposes data through Nova::provideToScript, a common pattern is passing an icon name from your PHP card/tool constructor to the frontend via meta or public $icon. Keep the icon name as a plain string in PHP and let the Vue component resolve it — this keeps the PHP side free of Vue-specific coupling.
Wrapper pattern. If the package's icon set doesn't cover everything you need, wrap it once inside your own <app-icon> component so you can swap implementations later without hunting through templates:
<!-- resources/js/components/AppIcon.vue -->
<template>
<component :is="resolved" v-bind="$attrs" />
</template>
<script>
export default {
props: ['name'],
computed: {
resolved() {
return this.name ? `nova-icon` : null
},
},
}
</script>
Integration with Nova 3 menus and toolbars. Custom tool menus and card headers are natural fits — the icons are small enough to sit inline without breaking the text-sm / h-5 w-5 spacing that Nova's layout assumes. Match Nova's existing sizing conventions by adding h-5 w-5 (or w-4 h-4 for tight toolbars) to the icon component's class list.
Build pipeline. If you're consuming the icons in your own compiled asset, add a peer-style import at the top of your entry file:
import 'reedware/nova-icons' // or the appropriate path
…so your build resolves the components rather than relying on whatever order Nova injects scripts.
Vue.component on a different global, etc.). Test on a Nova 3 project first; if you're on Nova 4, expect to either fork the repo or replace it with @heroicons/vue + a small wrapper.resources/js/ before adopting it — the whole package is probably small enough to vendor or reimplement in a single afternoon.Vue.component('nova-icon', ...) manually in your own entry to confirm the name; then check the browser devtools "Vue" panel for the resolved component name — the compiled tag may differ slightly from what the docs suggest.resources/js/ in the package, run npm run prod in the package directory (not in your app) and then php artisan nova:publish --force if you forked. Stale dist/ files are the #1 cause of "my component changes aren't showing up."text-sm, 14px); an unsized SVG will render at whatever intrinsic size the source set. Always pass class="h-4 w-4" or similar.resources/js/, (3) require your fork by VCS in composer.json. That's more reliable than piling wrappers on top.:key="name" to the icon component so that switching icon names during development forces a re-render — the underlying SVG/<i> tag sometimes doesn't update on prop change if it's been memoized.How can I help you explore Laravel packages today?