digital-creative/nova-range-input-filter
A Laravel Nova filter that adds a numeric range input to resource indexes, letting users filter records by minimum and maximum values. Easy to configure, it provides a clean range UI for prices, quantities, scores, and other numeric fields, with no custom filter code required.
Architecture fit. The package is a thin, single-purpose Nova filter: a PHP filter class that declares a $component plus a precompiled Vue range-input control, wired through Nova's existing filters() contract. It introduces no service provider of consequence, no database footprint, no queue or event surface, and no coupling to application domain code. From an architecture standpoint it is about as contained as a dependency gets — it touches one resource method (filters()) and the query builder inside apply(), and nothing else. The fit is therefore binary: if we are on Nova 4, it fits cleanly and is trivially removable; if we are not on Nova, it has zero value and should not be evaluated further.
Integration feasibility. Feasible in hours, not days, for a Nova-fluent engineer. The realistic path is: pin ^1.1, read the vendor source to confirm the namespace, the $value payload shape, and whether a default apply() ships, then either instantiate the filter directly with config setters (the common case) or subclass it and override apply() with explicit min-only / max-only / both / neither branches. That's one filter class per resource, registered in filters(). The two real unknowns are documentation-thin territory — payload shape on partial/cleared submissions, and whether the package coerces blank min/max to zero or leaves them null — and both are resolved by reading ~a few hundred lines of source in an afternoon.
Technical risk. The dominant risk is not integration, it is lifecycle. The package has one meaningful tag (v1.1.0, 2023-10-02) whose changelog is a single line: "Upgrade Nova 4 / Fix various issues." That phrasing is a red flag for a filter, because "various issues" is precisely where bound inclusivity, null handling, and half-open semantics silently change. Nova 5 is entirely unaddressed by any release — no declared support, no upstream roadmap signal. Supporting facts compound the picture: single maintainer, one outside contributor, 17 stars, zero dependents, and a nine-month-plus gap before the last release. This is not abandonment, but it is not health either. The mitigating factor is that the surface area is tiny and MIT-licensed, so forking or vendoring is roughly a day of work — which converts an upstream risk into a known internal cost rather than an open-ended one.
Secondary technical risks are semantic, not operational:
whereBetween is inclusive on both ends and drops NULL rows. Correct for "price between $50 and $200"; wrong if NULL means "unknown, show anyway." Product must make this explicit, not inherit it.Key questions. Answer these before adoption:
laravel/nova minor are we on, and does the package's constraint accept it? Smoke-test against our minor, not just "Nova 4."apply() ship, and what are its null/inclusivity semantics? Enumerate the v1.0 → v1.1.0 diff.Stack fit. We are targeting Laravel Nova 4 with this package pinned to ^1.1 as a fixed dependency — no floating constraints, because there is effectively one meaningful tag and its changelog provides no signal about what changed in behavior. The filter is presentational in the panel and semantic in apply(); all correctness lives in the latter. No build step, no compiled asset pipeline integration beyond what Nova already serves, no changes to application models or migrations.
Migration path. Greenfield on new resources: subclass or instantiate, register, done. For existing resources, there is no migration in the data sense — no schema change, no backfill, no config file. The only "migration" is retiring any prior hand-rolled range filter, and the sequencing there is additive-then-subtractive: add the new filter, verify filtered result sets match expectations on a realistic dataset, then remove the old one in a separate change so a regression is attributable. If a v1.0 pin exists anywhere, retire it in the same pass — v1.1.0 is the Nova 4 compatibility release and there is no reason to carry the older tag.
Compatibility. Nova 4 only, and only the specific minors we test. Nova 5 is out of scope; do not force the install with --ignore-platform-reqs — that trades a visible constraint error for an invisible runtime failure in the filter panel. PHP version compatibility should be confirmed against our runtime as a formality; the package is small enough that this is a non-issue in practice. Composes cleanly with other Nova filters: Nova runs every active filter's apply() sequentially against the same builder, and this package does not touch the builder outside apply(), so stacking with search, status, or a second range filter on a distinct column is conflict-free. The one rule is that each filter targets a distinct column.
Sequencing. A defensible order:
apply(). Enumerate the v1.0 → v1.1.0 diff.whereBetween for fully bounded ranges and paired >=/<= for half-open, and apply it consistently across every resource — mixed idioms produce inconsistent null and inclusivity behavior that surfaces later as "why did this filter hide that row?"EXPLAIN once on a realistic dataset; this is non-negotiable on large tables.Decision on build vs. buy. Hand-rolling this is 1–2 engineer-days. The due diligence and review overhead above is not free either. The break-even is close enough that the tiebreaker should be ownership appetite, not raw effort: if we are content to own the code via fork, adopt; if we want a supported dependency with an upgrade path, write a small internal filter and control it outright. Either is defensible; leaving it ambiguous is not.
Maintenance. Low volume, but non-zero and non-delegable. There is no active upstream cadence to ride — one meaningful release, one outside contributor, no Nova 5 signal. Practically this means we own the Nova-version compatibility question ourselves regardless of whether we formally fork. The maintenance burden is therefore: periodic smoke tests against our Nova minor, re-verification of inclusivity and NULL semantics whenever we bump, and a standing fork estimate (roughly a day) kept current so the fallback is always priced. Budget it as a small recurring line item, not a one-time integration cost.
Support. No SLA, no vendor, no security review process. Internal support is us. For an internal admin filter with no customer-facing surface and no data exposure beyond what the Nova resource already shows, the support burden is proportionate — but it does mean incidents route to whoever integrated it, and there is no upstream to escalate to. This is acceptable for ops-facing screens; it would not be acceptable for anything customer-visible or revenue-critical without the fork.
Scaling. Query scaling is the real operational concern and it is entirely ours, not the package's. A range filter on an unindexed column degrades to a table scan; on a large or revenue-adjacent table that is a self-inflicted incident the package will never flag. Index every filtered column, validate with EXPLAIN on realistic data volumes, and treat "add a range filter to a new resource" as a change that requires an index review. Filter-panel scaling is a non-issue — it is one control per resource.
Failure modes. Enumerated, because several are silent:
whereBetween drops NULL rows. If product expects NULLs to appear as "unknown," users silently don't see records and conclude the data is missing. Explicit product decision required.apply() a null or partial value. Guard with data_get() and defaults everywhere; an unguarded array access here is a 500 on a cleared filter.Ramp-up. Essentially zero for a Nova-fluent engineer — the integration is one class and one registration. The real ramp-up is contextual: understanding Nova's filter contract, our product's definition of "in range" for nullable columns, and which columns are indexed. A non-Nova engineer would spend more time on Nova fundamentals than on this package, which is the correct ratio for a dependency of this size. Documentation is thin by design; the source is the specification, and onboarding should say so explicitly rather than pointing at the README.
Bottom line for the TPM. Adopt as a tactical internal-tooling utility on Nova 4, pinned to ^1.1, gated on a source read and one pilot resource with a feature test. Do not let it factor into any Nova platform decision. Carry three items in the risk log: Nova 5 is unowned, NULL and inclusivity semantics require explicit product sign-off, and filtered columns must be indexed. Keep the one-day fork estimate on file — the code is small enough that ownership is always a priced option rather than a cliff.
How can I help you explore Laravel packages today?