afatmustafa/blade-hugeicons
Blade Hugeicons provides 6,200 free Hugeicons SVG icons as Laravel Blade components. Install via Composer, then use tags like with classes, inline styles, and standard SVG attributes.
1. Install and pin a sane version. The package is a thin wrapper around blade-ui-kit/blade-icons, so nearly everything you need to know is documented upstream.
composer require afatmustafa/blade-hugeicons:^2.0.1
Pin at least ^2.0.1 — earlier v2 builds shipped SVGs with missing stroke data, so icons like container rendered blank while older ones looked fine. Requirements are PHP 8.1+ and Laravel 10–13.
2. Where to look first.
resources/svg in the vendor package tree is the source of truth for icon names. The component name is <x-hugeicons-{filename-without-.svg}>. If a name isn't a file there, it doesn't exist.svg() helper — this package adds no API of its own beyond the icon set.php artisan vendor:publish --tag=blade-hugeicons-config if you want global defaults (prefix, default class, default attributes).3. First use case: replace a hand-pasted SVG in a button.
<button type="submit" class="inline-flex items-center gap-2 rounded bg-indigo-600 px-3 py-2 text-white">
<x-hugeicons-settings-01 class="h-4 w-4" />
Save changes
</button>
That's the whole loop you'll repeat all day: pick a name, drop the self-closing component, size it with Tailwind, style it with text-* (the icons use currentColor).
4. Sanity check before you build on it. Render one icon in a scratch view. If nothing appears, check that the root <svg> has fill="none" and that you're on ^2.0.1, then clear cached icons (php artisan icons:clear) — stale caches are the usual suspect after an upgrade.
Sizing and color are plain Tailwind. Icons are stroke-based SVGs with a viewBox, so class="h-5 w-5" plus text-gray-500 (or text-current inside a colored parent) covers 95% of use. Keep a size convention in your design system and never let arbitrary w-[13px] values creep in.
<x-hugeicons-bell class="h-5 w-5 text-slate-500 transition hover:text-slate-900" />
Wrap the package behind your own semantic component. This is the single highest-value pattern for a 6,200-icon set from a small package: it makes icon swapping and upstream renames a one-file change.
{{-- resources/views/components/icon.blade.php --}}
@props(['name', 'size' => 'md'])
@php
$sizes = ['sm' => 'h-4 w-4', 'md' => 'h-5 w-5', 'lg' => 'h-6 w-6', 'xl' => 'h-8 w-8'];
@endphp
<x-dynamic-component
:component="'hugeicons-' . $name"
{{ $attributes->class([$sizes[$size] ?? $sizes['md']]) }}
/>
Then @php $map = ['save' => 'floppy-disk', 'delete' => 'delete-02', 'settings' => 'settings-01'] in a config file, and <x-icon name="save" size="sm" /> everywhere. When Hugeicons v5 renames things, you edit the map, not 200 views.
Compose inside your existing components. Buttons, alerts, and empty states should accept an optional icon slot, and the icon inherits color from its parent:
{{-- status badge --}}
<span @class(['inline-flex items-center gap-1.5 rounded-full px-2 py-1 text-xs',
'bg-green-50 text-green-700' => $status === 'paid',
'bg-amber-50 text-amber-700' => $status === 'pending'])>
<x-dynamic-component :component="$status === 'paid' ? 'hugeicons-checkmark-circle-02' : 'hugeicons-clock-01'" class="h-3.5 w-3.5" />
{{ ucfirst($status) }}
</span>
Stroke weight. Three ways work: stroke-width="1.5", the Tailwind class stroke-2, or style="stroke-width: 2px". Pick one project-wide (usually a CSS/Tailwind approach) and document it — mixing attribute and class on the same icon gives confusing results.
Nav and menus. Drive active state off the route, keep the icon name in the nav array rather than the Blade file, and render with x-dynamic-component. Bonus: the same array can power a mobile menu without duplicating names.
Icon pickers / CMS-driven icons. If editors choose icons, persist the Hugeicons slug (floppy-disk) and render dynamically. Two caveats: names coming from the DB won't be found by Tailwind's scanner, so safelist your size classes; and an invalid slug throws SvgNotFound, so validate the slug against the available set on save (read filenames from the package's resources/svg directory or the Blade Icons factory) and render a fallback icon on the read side.
Raw SVGs for non-Blade output (emails, PDFs via DomPDF, <img> tags, favicons):
php artisan vendor:publish --tag=blade-hugeicons --force
That dumps files to public/vendor/blade-hugeicons/*.svg. Reach for this only when you actually need a URL; the component path is better for normal views.
Icon caching is a deploy concern. Blade Icons can cache the resolved set (php artisan icons:cache) which is strongly recommended with 6,200 files. Wire icons:clear && icons:cache into your deploy script after the new release directory is in place, and never rely on a cache built by a previous release.
Testing. Assert the rendered markup, not the component:
$this->get('/dashboard')->assertSee('hugeicons-settings-01', false);
// or render in isolation
$this->assertStringContainsString('<svg', Blade::render('<x-hugeicons-youtube />'));
A cheap smoke test that renders your main layouts catches every typo'd icon name before a user does.
<x-hugeicons-whatevr /> happily; the missing-icon exception fires when the view executes. A typo in a rarely visited admin page ships silently. Guard critical views with tests.resources/svg before deploying. This is the main reason to route every icon through your own x-icon map.php artisan icons:clear first, then view:clear if it's still odd.currentColor; don't hardcode fills. The package added fill="none" on the root specifically so stroke icons don't render as solid blobs. If you need a filled variant, check whether a fill-style icon exists in the set rather than hacking fill onto a stroke icon.stroke-width may not override a path-level attribute. Some v4 exports carry attributes on the child paths. If stroke-width="1.5" on the component appears to do nothing, inspect the published SVG; a CSS rule targeting svg * is the reliable escape hatch.--force on publish overwrites your files. Never hand-edit public/vendor/blade-hugeicons/*.svg — an upgrade republish wipes them, and the component path (which reads from the package, not public/) won't see your edits anyway.<svg>. That's convenient (aria-hidden, data-*, wire:*) but also means id collisions are on you: never put a static id inside a reusable icon component, or gradients/masks will fight across instances.aria-hidden="true"; meaningful ones need role="img" plus aria-label (or a <title>), and the label should come from translation files, not the slug. Bake this into your x-icon wrapper — ideally defaulting to aria-hidden="true" with an explicit label prop to opt out.vendor:publish --tag=blade-hugeicons) so a future upstream break can't take down your UI while you migrate.resources/svg? → does {{ svg('hugeicons-name') }} render in a scratch view? → clear icons:cache → inspect the actual SVG source. That sequence resolves almost every issue with this package.How can I help you explore Laravel packages today?