nevadskiy/nova-icon-picker
A Laravel Nova field that adds an icon picker to your admin panel, letting you search and select icons from supported icon sets and store the chosen icon name on your models. Simple to install and configure for Nova resources.
Architecture fit. This is a Laravel Nova form field, not a general-purpose Laravel library. It only delivers value inside an existing Nova admin panel. That narrowness is the point: it plugs into Nova's existing field pipeline alongside Text, Select, and BelongsTo, persists a single plain string on the Eloquent model, and introduces no new services, queues, storage, or public API surface. The blast radius is a form control, not a revenue path — a failure here degrades an admin screen, not the customer experience. For a TPM, that is the strongest argument in its favour: it is cheap to adopt and cheap to remove.
Integration feasibility. High for a spike, unproven for production. The mechanics are three steps: composer require, a migration adding a nullable string column, and one field declaration on a Nova resource. Everything difficult about this package is unknown rather than complex:
composer.json constraints are read directly. If we are on Nova 5, this becomes a compatibility spike, not an install.fa-solid fa-user) or a slug (user). This is not documented reliably and fails silently: no exception, no validation error, just blank glyphs in production.Technical risk. The headline risk is dependency health, not code quality. Three stars, zero dependents, a 2023 release, and no vendor backing mean this is effectively vendored code from day one. Secondary risks: the stored value originates in an admin form and flows into Blade, so unescaped output is a genuine XSS vector; and because Nova requires a commercial licence, most teams get zero CI coverage of the field itself. The offsetting factor is that a Nova field is roughly one PHP class plus one Vue component — forking into packages/ is genuinely cheap, which is the main reason adoption is defensible at all.
Key questions to resolve before committing:
Select field is unusable? If not, this package has no advantage over a ten-line built-in alternative.Stack fit. Requires Laravel plus Laravel Nova. It is not a candidate for applications evaluating Nova alternatives, and introducing Nova solely to use this field is not justified. Best fit is an admin-heavy application that already standardises on Nova and has repeated icon-selection needs: navigation builders, categories, taxonomies, dashboard tiles, status badges.
Migration path. Adding a nullable string column is non-destructive and reversible, which makes rollout low-risk. Backfill is manual: existing hard-coded icons need converting into whatever format the picker emits. Because the field is nullable and rendering is null-safe, partial adoption is fine — resources without icons simply render nothing.
Compatibility. Pin the exact version rather than accepting a floating constraint. With three stars and zero dependents, a silent patch bump is not something we want arriving unannounced. Add the package to the Nova-upgrade checklist explicitly, since Nova majors are the most likely breakage vector.
Sequencing. Run this as a time-boxed, staged delivery rather than a single rollout:
Rule::in(...)) from a config file or enum, because the payload is editable regardless of what the component restricts.canSee callback so a broken picker degrades to a hidden field rather than a broken admin, then extend to menus, badges, and dashboards.Fallback position. If the spike fails on Nova compatibility, or the icon set is small (a few dozen), the correct answer is Nova's built-in Select plus a small preview Text field. That is a zero-dependency alternative that survives every Nova upgrade. The package earns its place only when the set is large enough that a flat dropdown becomes unusable.
Maintenance. Assume internal ownership from day one. MIT licensing means inspection, patching, and forking are all permitted and practical — but nobody upstream is obligated to fix anything. Budget a small recurring cost: an entry on the Nova-upgrade checklist, an exact version pin, and a standing fork contingency. If the feature becomes load-bearing, pre-approve the fork rather than negotiating it during an incident.
Support. There is no vendor SLA and effectively no community to lean on at this adoption level. Support is self-support: developers read src/ and resources/js/ in vendor/ directly, and the package is small enough that the source genuinely is the documentation. Plan for a named owner, not a shared assumption.
Scaling. Runtime cost is negligible — one string column, no additional queries, no external calls. The scaling concerns are operational, not load-related: assets must be republished (nova:publish) after install and after every Nova upgrade, and each additional resource using the field multiplies the surface where a misconfigured icon set produces blank glyphs. If a curated icon set is required, the Vue bundle itself becomes the scaling unit and implies a fork plus a JS build step in our release pipeline.
Failure modes to plan for. All of these are silent, which is why they matter:
user where the picker writes fa-solid fa-user. Nothing errors; production icons are blank and the bug is diagnosed days later. After one manual save, treat the database value as canonical and use it in every seeder and fixture.nova:publish / view:clear / config:clear, not code.{!! !!} an admin-supplied value.Ramp-up. Developer ramp-up is short — half a day of reading source plus the spike. Editor ramp-up is a short written guide: what icons exist, what the picker affects, and why the preview in the form is the source of truth. The main organisational ramp-up is a documented decision on icon format, so future work doesn't reopen the class-string-versus-slug question.
Recommendation. Run the time-boxed spike in a non-critical admin screen. If it works with the current Nova stack, adopt it with an exact version pin and a fork contingency; if not, build the minimal internal replacement or use the built-in Select. Either way, treat this as a small internal UX utility — scope it to admin efficiency, keep it off the strategic dependency list, and don't let its output become a data contract for the public API or mobile clients.
How can I help you explore Laravel packages today?