outl1ne/nova-input-filter
A Laravel Nova filter that adds a free-text input field to the filters panel, letting users type a value to filter resource listings without building a custom filter class each time.
Architecture fit. The package is a presentation-layer primitive, not a search feature. It contributes a base Filter class and a compiled Vue input component that mounts inside Nova's filter panel; all query semantics live in your apply() method. For a TPM, the important consequence is that this does not introduce a new architectural layer, service, or data path — it is a thin extension of Nova's existing filter contract, which your team already owns. The decision it supports is narrow: buy a text-input filter control versus roughly one sprint-day of bespoke Nova component work. That is a low-stakes, fast-cycle decision that should be delegated to the owning engineer with PM visibility, not escalated.
Integration feasibility. Installation is one composer require, no service provider, no publish, no asset build. The realistic floor is PHP 8.1+ / Laravel 10–12 on Nova 4 or 5. The only non-obvious cost is mandatory source review: the class is small enough to read in five minutes, and that time is what lets you own the dependency rather than rent it. Filter classes are plain PHP with a single apply() method, so they are unit- and feature-testable without booting the Nova frontend — a genuine feasibility win for a team with thin frontend capacity.
Technical risk. Risk is concentrated in three places, only one of which is the vendor's:
where('name', 'like', "%{$value}%") is an injection path from an authenticated admin surface, and an ungrouped orWhere silently escapes sibling filters. This is the highest-severity failure mode in the evaluation and it sits inside your review boundary. Budget review time and a written binding/grouping rule as adoption cost, not follow-up.Key questions. (1) Which Nova major version are we on, and does anything on the roadmap force an upgrade inside twelve months? (2) Which two or more resources will this land on — if only one, build in-house instead? (3) Who is the named owner of the fork contingency? (4) Is case-sensitive vs. case-insensitive LIKE behaviour consistent across our environments (MySQL default collation vs. Postgres)? (5) Does the compiled component debounce keystrokes, or does each one hit the index endpoint?
Stack fit. This is a native fit for any licensed Nova installation already using Nova's filter contract. It composes cleanly with built-in filters and requires no frontend toolchain, which means it can be delivered by a backend engineer without design or frontend coordination — a material scheduling advantage for a small admin-UX request.
Migration path. There is nothing to migrate: no schema, no data, no customer-facing surface, no state. Adoption is additive per resource and reversible per resource by removing one line from filters() and one class file. The realistic "migration" is retiring the clunky exact-match checkbox filters that accumulate in mature Nova installs, which can be done resource by resource with no cutover.
Compatibility. Confirm the Nova major version in composer.json before anything else — it is the hard ceiling. Then inspect the package's own constraints post-install, since there is no published support matrix. Pin the Composer constraint to 1.x or an exact tag and treat version bumps as deliberate decisions.
Sequencing. Run a two-resource spike rather than a rollout:
User, Order, Shipment — and a column users currently ask engineering to look up (email, order number, tracking code, SKU).Filter contract in the installed Nova version.blank($value) no-op guard and grouped orWhere closure in place from the first commit.DB::listen() or ->toSql().EXPLAIN against production-like row counts before the second resource, not after.ContainsFilter base class if a third resource appears.Reuse threshold. Adopt if two or more resources are in scope with a plausible path to more. One resource only, and an in-house class is cheaper than the dependency.
Maintenance. Ongoing cost is near zero — the package is a base class plus a component. Ownership cost lives in your apply() implementations, which need the same code review as any query touching a large table. Nova major upgrades are the maintenance trigger: add "open every input filter on staging" to the upgrade checklist, because failures are silent. Agree the fork-into-app/Nova/Filters path now, while it is an afternoon task, so an abandoned upstream is routine rather than an incident.
Support. Support load should trend down: self-serve admin lookups replace ad-hoc SQL requests to engineering. The counter-risk is user trust — ambiguous empty-input behaviour makes "filter applied, no matches" indistinguishable from "filter didn't apply," which erodes confidence in the admin panel faster than a missing feature. Encode the no-op vs. zero-rows decision explicitly and test it.
Scaling. The package does not scale; the query does. Leading-wildcard LIKE cannot use a B-tree index and becomes a sequential scan past low-hundreds-of-thousands of rows. Pair free-text inputs with a narrowing filter (date range, status, tenant) so the LIKE runs over a pre-narrowed set, or use prefix matching, or add a trigram/fulltext index on Postgres. whereHas relationship filters become a subquery on every page load, sort, and pagination click — measure before shipping those to a large index.
Failure modes. Ranked by severity and likelihood:
apply() — high severity, entirely preventable by bound parameters and grouped orWhere. This is the one to resource.EXPLAIN in the spike.key() — one filter silently clobbers another's URL state. Mitigated by a convention set at the base class.Ramp-up. Roughly half a day per engineer: five minutes to install and read the class, the rest to internalise the four query shapes and the orWhere grouping rule. Documentation is not the onboarding path — the source read is. The genuinely cheap operational win is the metrics: capture time-to-find for internal users, engineering interrupts avoided, and ad-hoc SQL requests displaced during the pilot. Those are the numbers that justify the next admin-tooling decision, and this pilot is where they are cheapest to collect.
How can I help you explore Laravel packages today?