anaseqal/nova-sidebar-icons
Anaseqal Nova Sidebar Icons lets you add custom icons to Laravel Nova sidebar menu items, making admin navigation easier to scan and more visually polished. Simple configuration helps tailor Nova’s sidebar to your application.
Check your Nova major before anything else. This package was last released 2019-08-29, which puts it in the Nova 2.x / early 3.x era. Nova 4+ ships MenuItem::icon() natively, so on a modern Nova the correct action is to close this tab and use the framework method. Confirm with:
php artisan nova:version
If you're on Nova 2.x or early 3.x and you want icons on the sidebar, continue below.
1. Install with a hard-pinned constraint. There will never be a new release, so never float it:
composer require "anaseqal/nova-sidebar-icons:^1.0"
Check the actual tag list in the upstream composer.json before writing that string — don't guess the version from the README.
2. Register the tool. Nova 2 does not auto-discover tools, so add it to app/Providers/NovaServiceProvider.php:
public function tools()
{
return [
new \Anaseqal\NovaSidebarIcons\NovaSidebarIcons,
// existing tools...
];
}
Verify the FQCN against src/ — namespaces on dormant packages routinely drift from what the README shows.
3. Publish anything the service provider ships:
php artisan vendor:publish --provider="Anaseqal\NovaSidebarIcons\ToolServiceProvider"
Read src/ToolServiceProvider.php first to know what it publishes. A config file is safe. A Blade view override is fragile and will break on Nova patches. A plain CSS asset is essentially free to fork.
4. Clear caches after every mapping edit:
php artisan config:clear && php artisan view:clear
Where to look first, in this order:
README.md — the label→icon mapping syntax is the only thing you use day-to-day. Skim the rest.src/ — usually a provider plus one small decorator class, a few dozen lines. Read it end-to-end. It tells you how the package hooks into Nova's menu (menu API? view composer? CSS injection?), which is what determines how fragile it is.config/nova-sidebar-icons.php (if published) — this is your map. If it's absent, the map likely lives in NovaServiceProvider::mainMenu() or per-resource static properties.resources/ — a view or CSS asset. Fork the CSS; do not edit a published view in place.First use case: a single-item spike. Pick one tool or one resource, give it an icon, load /nova, and confirm it renders. Twenty minutes. That's your go/no-go on this Nova version before you invest in a full icon vocabulary across the sidebar.
One central map, not scattered per-resource edits. The maintainable shape is a single label => icon array in config (or in NovaServiceProvider), not public static $icon sprinkled across twenty resource classes. When a menu label changes, you edit one line:
// config/nova-sidebar-icons.php (verify exact key names against README)
'icons' => [
// Ops
'Users' => 'users',
'Teams' => 'user-group',
// Billing
'Orders' => 'shopping-cart',
'Invoices' => 'document-text',
// Reporting
'Reports' => 'chart-bar',
],
Group and comment by domain so the map itself documents the sidebar.
Pick one icon set and stay inside it. Heroicons ship with the package. Mixing Heroicons, Font Awesome, and hand-rolled SVGs produces visibly inconsistent stroke weights in a list only ~12 items tall, and the inconsistency is the first thing a stakeholder notices. For a custom SVG: square viewBox (0 0 24 24), fill/stroke set to currentColor, no width/height attributes so CSS controls sizing.
Match on the rendered label, exactly. Whatever the package keys off — MenuItem label, resource label(), or tool class — the key must equal the displayed string: case, pluralization, and whitespace included. If you localize a resource label, key the map off the same localized value. If a resource's label() differs from its class name, you'll chase a phantom bug. Dump the string before writing the key:
// quick tinker sanity check
dump(\App\Nova\User::label());
Custom sidebar items go through Nova::mainMenu(). Section headers and standalone links live in NovaServiceProvider::mainMenu(); wire their icons through the package's API, or add a small helper method yourself if none exists. Keep custom items few — each one is another label to keep in sync with the map and they don't get resource tooling for free.
Environment-gate the tool. Icons are cosmetic; you want a one-flag kill switch on production:
public function tools()
{
return array_filter([
config('nova.sidebar_icons') ? new \Anaseqal\NovaSidebarIcons\NovaSidebarIcons : null,
// ...other tools
]);
}
That single config flag is your rollback if a Nova patch breaks menu rendering on a live admin panel.
Compose, don't collide. If another Nova tool already mutates the sidebar (grouping, role-based visibility, badges), do a dry run with both enabled before shipping. Two tools touching the menu is the most common cause of "my icons vanished."
Fork when the scope outgrows it. Grouping, collapsibles, role-aware menus — this package will not grow to cover those. When you hit that wall, copy the mapping logic into a first-party MenuItem subclass under app/Nova (typically 20–40 lines), drop the dependency, and carry it forward with your Nova upgrade.
Add a smoke test that asserts the panel boots. With no maintainer, CI is your only early warning after a Nova bump:
public function test_nova_dashboard_renders()
{
$admin = User::factory()->create(['is_admin' => true]);
$this->actingAs($admin)->get('/nova')->assertOk();
}
If you can, also assert a known icon class or data- attribute is present in the HTML. That converts a cosmetic QA miss into a hard CI failure.
MenuItem::icon() exists in the framework. Layering a 2019 tool on top of native icon support is pure downside — no upside, extra supply-chain surface./nova entirely, not just icons. Validate on staging; keep the kill switch armed in production.config:clear and view:clear after every mapping edit. If assets are published, vendor:publish --force when the package version changes — and note that --force clobbers local edits, which is exactly why you fork instead of editing published files.LICENSE before copying source into a private namespace. Vendoring is otherwise the recommended path over a live dependency.MenuItem subclass or a mainMenu() decorator under app/Nova, and add a one-page ADR: why you forked, what you changed, what to re-check on the next Nova major. That document turns "abandoned dependency" into a non-issue.config:clear + view:clear; (2) confirm the tool is registered and not filtered out by your env gate; (3) dump the actual label and diff against the map; (4) disable other menu-mutating tools to isolate a collision; (5) grep the rendered /nova HTML for the expected icon class to see where it's being stripped.How can I help you explore Laravel packages today?