rmsj/nova-hero-icon
Integrates the Heroicons SVG icon set into Laravel Nova, letting you add crisp, ready-made icons to your admin panel resources and custom tools without bundling or managing the assets yourself.
Architecture fit. rmsj/nova-hero-icon is a thin Nova-side convenience layer, not infrastructure. Its actual architectural contribution is a picker UI that persists an icon name as a string column; rendering is the consuming application's responsibility. That is a healthy boundary — it means the package can be contained to a single resource's form fields and swapped out without touching the display layer, provided we deliberately build the read path ourselves (<x-heroicon> Blade component) rather than letting the package own both sides. The description's ambiguity (Nova field vs. Nova resource tool) must be resolved by inspecting vendor/rmsj/nova-hero-icon/src before any design decision is made — the two shapes have different registration contracts (fields() vs. tools()) and different blast radii.
Integration feasibility. Installation is trivial in the abstract — MIT license, one composer require, asset publish. The feasibility gate is not effort, it is the version matrix: Nova major ↔ Vue major ↔ PHP/Laravel. This is a May 2020 release targeting Nova 2.x/3.x, Vue 2, and PHP 7.x. On Nova 4/5 (Vue 3, PHP 8.2+) the component will not mount reliably, and there is no published evidence of anyone running it on a modern stack. Realistically: viable for legacy admin panels we still operate, non-viable for anything greenfield.
Technical risk. Three risks dominate, in order:
Rule::in() whitelist plus a visible fallback icon.Key questions for the spike (~half a day):
composer.json actually constrain (laravel/nova, php)? — this is the go/no-go, answerable in five minutes.Field or Tool, and which fluent methods (->icon(), ->size(), ->color()) actually exist?resources/js/dist/, or does it require resurrecting a 2020 Node toolchain?props match what the PHP side appears to pass?fill="#000", which would make icons vanish in Nova dark mode?Stack fit. Only adopt on a legacy Nova 2/3 install where PHP 7.x and Vue 2 are already the baseline. On Nova 4/5, the correct integration approach is not integration — it is the reference-implementation path: php artisan nova:tool vendor/name and reimplement the ~small Vue side against a current Heroicons release. Half a day, no fork obligation, no stale asset build, no 2020 toolchain.
Migration path. Narrow and deliberate:
vendor/rmsj/nova-hero-icon or fork into packages/nova-hero-icon via a path repository, pinning the commit. Never rely on Packagist for this.$table->string('icon')->nullable()) and $fillable before first save.Compatibility. Treat compatibility as a tested property, not a semver inference — Nova's tool/asset API is effectively an undocumented internal contract. Maintain a committed, scanned list of valid icon names (from the bundled SVGs, not from heroicons.com) and use it as both the UI source and the validator. Add the fork to the Nova-upgrade checklist the day it is committed.
Sequencing. This is a rider on the Nova version decision, never a driver of it. Order: Nova upgrade work → decide icon vocabulary → then, and only then, whether a picker is needed at all. Within a sprint, it goes behind any admin work with a named owner; if no engineer will own the recurring half-day at each Laravel/Nova major, the sequencing answer is "defer," and a select field populated from a static array plus our own <x-heroicon> component delivers the same editor outcome for comparable effort with permanent maintainability.
Containment rule. Scope to one or two resources so the blast radius of a break is one file, not fifteen. Publish assets one tool at a time and commit the result — nova:publish across multiple tools can collide in public/vendor/.
Maintenance. Non-zero and recurring. Budget half a day to spike, an hour to vendor cleanly, and a recurring half-day at every Nova and Laravel major upgrade. That recurring cost is the real price; the license is free and the install is one command. If nobody owns that half-day, the package is disqualified regardless of how well the spike goes.
Support. Effectively none. No issues to search, no Stack Overflow answers, no blog posts, no maintainer response path. Internal support is first-principles debugging only. For a UI nicety on an internal screen that is tolerable; if a stakeholder calls it "broken," we own the fix entirely and cannot escalate.
Scaling. Runtime cost is negligible. Organizational cost is not: with multiple Nova-versioned applications we would inherit duplicate forks across majors, and the package does not scale across that dimension at all. This is a single-app, single-version decision.
Failure modes to design against:
nova.log. Put this in the runbook so nobody burns hours in PHP logs.Rule::in(config('icons.available')) on any user-controlled path (API import, CSV, Nova action) and a visible fallback (question-mark-circle).resolveIcon() helper with a known-name whitelist, rather than at each call site.public/vendor/ after installing alongside other Nova tools; symptom is scrambled admin CSS/JS.Ramp-up. Low for a Laravel-fluent engineer: the surface is one small class plus a Vue component, and the store-and-render pattern is a few lines. The ramp-up cost that matters is institutional — someone must know the fork exists, why it exists, and that it is on the Nova-upgrade checklist. Document the fork, the pinned commit, and the fallback rule at the point of adoption or the knowledge leaves with the engineer.
TPM recommendation. Treat this as an optional convenience affordance for legacy admin screens, not a roadmap item. It moves no customer-facing metric. Approve only with (a) a passed spike on the actual Nova version, (b) vendor/fork with a pinned commit, (c) a named owner for the recurring upgrade tax, and (d) scope limited to one or two resources with an in-house read path. Absent any one of those, the correct outcome is defer — and on Nova 4/5, the correct outcome is build the half-day custom field and keep Heroicons current.
How can I help you explore Laravel packages today?