silvanite/novafieldcheckboxes
A Laravel Nova field package that adds checkbox inputs to your resources: a single boolean checkbox or a group of options stored as JSON, with labels, defaults and validation configured in PHP.
Architecture fit. This is a deliberately narrow Laravel Nova form field: a PHP Field subclass (Silvanite\NovaFieldCheckboxes\Checkboxes) paired with a Vue component registered through FieldServiceProvider via Nova.booting. It renders a checkbox group over a static key/value option map and persists the selected keys as an array into a single JSON (or text-with-cast) column. It does not touch application runtime, routing, public APIs, queues, or any customer-facing surface. Its blast radius is confined to Nova admin resources. That containment is the headline for a TPM: the downside is capped at internal tooling, so the evaluation question is correctly scoped to "does this reduce operator mis-selection on a short, known option set?" rather than "does this fit our platform?"
Integration feasibility. High and cheap for a team already on Nova: Composer require, swap the field class into a resource's fields() method, add an array/json cast, confirm the column type. Measured in hours, not days. The real effort is the surrounding hygiene the package does not provide and does not claim to: a single shared option source consumed by both the field and the validation rules (Rule::in(array_keys(config('options.x')))), array-level validation (required|array|min:1 where at least one selection is mandatory), index readability via displayUsing() because a raw JSON array is unreadable in the index table, querying via whereJsonContains, and an explicit normalization decision on whether an all-unchecked form submits [] or null (a mutator is the cleanest home for that). None are blockers; each is a place where a superficial adoption fails six weeks later.
Technical risk. Moderate, and skewed toward lifecycle rather than code quality. The adoption signal is weak — ~67 stars, zero known dependents — so there is little community pressure on the maintainer to track Nova releases, and Nova's field API and frontend build conventions shift across majors. Small field packages are the first casualty of those shifts, and the failure mode is a hard upgrade blocker rather than graceful degradation. Two structural risks compound it: redundancy risk, because Nova's native BooleanGroup stores multiple selections as JSON and may cover the same need at zero dependency cost; and data-shape risk, because a missing or mismatched model cast produces either an Array to string conversion error or a silently stringified value that breaks on read. Read the scoring inputs honestly: an opportunity score in the mid-30s against a ~7.06 composite is "cheap, tactical, low ceiling" — a convenience to size accordingly, not a strategic bet.
Key questions to resolve before committing:
composer.json explicitly constrain, and does that match our release? This is the most common adoption failure for packages in this class.hideFromIndex, displayUsing, standard validation, Nova search/filters, and our version's asset pipeline? Are the Vue assets prebuilt or must they be compiled?BooleanGroup — or a refined multi-select — already satisfy the requirement? If yes, the correct decision is to add no dependency at all.Stack fit. Strongest where the application already runs Nova as an internal admin panel and the package's version constraints match the Nova major. The sweet spot is roughly 5–20 mutually non-exclusive, stable options — role/permission assignment, tags, categories, notification-preference groups, feature flags, region or product-attribute mapping — where making every choice simultaneously visible eliminates the "hidden behind a search box" failure mode that drives misclicks. Beyond roughly 20–25 options the calculus inverts: a checkbox wall is worse than a searchable multi-select, and the package should not be used. On Filament, Livewire, Inertia, or plain Blade it is simply out of scope. Roadmap-wise this belongs under internal ops efficiency or admin UX, not the customer-facing roadmap, and success should be measured in operator error rate and support-ticket volume, not product KPIs.
Migration path. Prototype first, and prototype against the native alternative rather than in isolation.
BooleanGroup or a refined multi-select already satisfies the requirement. If it does, stop — the cheapest dependency is the one not added.array vs. json cast, [] vs. null, and normalize in a mutator so nothing downstream must reason about which Nova version wrote the value.text with a JSON cast) and backfill, with a tested rollback path.config/ or an enum-backed helper consumed by both the field and the form request. Duplicated option maps are the most likely source of stale labels and validation drift.Compatibility. Pin the package version explicitly and record the supported Nova version in the repo alongside the Composer constraint, so an upgrade PR surfaces the coupling. Verify the Vue assets build against the project's actual Nova build rather than assuming prebuilt bundles work. Add a line to the Nova upgrade checklist: re-verify this field. The fallback if compatibility breaks is a small in-house field — a bounded, well-understood half-day-to-a-day piece of work — or a return to native BooleanGroup.
Sequencing dependency worth flagging explicitly: the model cast and column type must land before the field is exposed in the UI, not after. Reversing that order produces an Array to string conversion failure on a live admin screen, which burns credibility for the tooling and distracts from the actual value. Similarly, the shared option map should exist before the field and the form request are wired up, not retrofitted afterwards.
Maintenance. Low in volume, elevated in dependency risk. The field is small and isolated, so routine upkeep is near zero — but it is an unpinned, low-adoption third-party dependency inside the admin layer, and its characteristic failure is a blocked Nova upgrade. Treat it as buy-then-own: adopt cheaply, assume ownership, and vendor or fork the component rather than depend on upstream responsiveness. Hold that option open from day one instead of discovering the need mid-upgrade. Budget roughly half a day to a day for a fork-and-own path. It is not a large commitment, but it should be an acknowledged one with a named owner and a documented location for the vendored copy.
Support. Expectations should be set internally, not externally: this is an internal-tooling widget with no customer-facing SLA. The realistic support load is not the widget itself but the two things around it — option-map drift (a label added in one place and not the other, or a validation rule that no longer matches stored keys) and data-shape confusion ([] vs. null, stringified values from a legacy row). Both are eliminated by the shared option source and the normalization mutator, and both should be documented in the resource's own README rather than in a ticket. Budget no dedicated support capacity; assign the same named owner as the fork.
Scaling. This scales with the number of Nova resources that adopt it, not with traffic — it is a form input on low-volume admin screens, so there is no performance dimension of consequence. The real scaling limits are two: option-count ceiling, where past roughly 20–25 items the UX justification evaporates and a searchable multi-select or relation picker should take over; and team/upgrade coupling, where each additional Nova major raises the re-verification cost. Filtering and querying on the stored values rely on whereJsonContains, so confirm the database engine and version support it before committing to index-level filtering in Nova. There is no relational integrity: deleting an option leaves orphaned keys in stored JSON, so option retirement needs a data-cleanup decision, not just a config edit.
Failure modes and mitigations. (1) Unmaintained against a Nova upgrade — hard blocker; mitigate by pinning, adding an upgrade-checklist line, and pre-approving the in-house fallback. (2) Missing or mismatched cast — Array to string conversion or silently stringified values; mitigate by landing cast and column type before the UI. (3) Inconsistent empty state — [] vs. null breaking downstream checks; mitigate with a mutator and an explicit contract. (4) Option-map drift — field and validation disagreeing; mitigate with one config/enum source. (5) Unreadable index column — mitigate with displayUsing(). (6) Oversized option set — mitigate with a hard rule to switch field type past the ceiling. (7) Orphaned keys — mitigate with a retirement/cleanup note in the runbook. (8) Redundant dependency — mitigate by benchmarking against BooleanGroup as step one, with a documented "we chose not to add this" outcome being a perfectly good result.
Ramp-up. A Nova-proficient developer is productive in a couple of hours and fork-capable in roughly a day; operators need no training, which is the point of the field. The organizational ramp-up is the upgrade checklist entry and the vendor/fork runbook — small, one-time, and the difference between a durable tactical win and a future upgrade incident.
How can I help you explore Laravel packages today?