Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Tag Input Laravel Package

superlatif/nova-tag-input

A Laravel Nova field that adds a clean, interactive tag input to your resource forms. Users can easily add, remove, and manage multiple tags, making it simple to organize and categorize models directly within Nova.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is not a library that touches the application domain — it is a single Nova form field: a PHP Field subclass that registers one Vue component. The blast radius is confined to the admin surface, which makes it unusually easy to justify as a contained dependency. The data model it implies (nullable JSON column + array cast on the Eloquent model) is idiomatic Laravel and does not force a schema or persistence pattern on the rest of the system. Tags persist as a plain attribute; nothing else in the app has to know the package exists. That isolation is the package's strongest architectural property and the main reason a TPM should feel comfortable piloting it.

The counterweight: it is built against Nova's private Vue/frontend conventions, not a public contract. That means the real architecture-dependency is not on superlatif/nova-tag-input — it's on Nova itself. Adopting this field is an implicit vote to keep Nova as the internal admin layer. Surface that explicitly rather than letting it happen as a side effect of a one-line composer require.

Integration feasibility. High, with caveats. The work is well-understood and bounded:

  • composer require plus php artisan nova:publish for asset registration.
  • Confirm the actual FQCN in src/ — the docs call it Tag, but the import path is an assumption until verified.
  • One migration (JSON column), one cast, one field registration, one round trip.

Realistically a one-day spike to a working field on a single resource, plus a second day for validation rules, normalization, and a feature test. There is no autocomplete, no tag library, no suggestion engine, no merge/rename workflow. If a stakeholder has seen a chip UI and inferred "typeahead against our existing taxonomy," that misconception must be corrected before the demo — it is a materially larger project.

Technical risk. Dominant risk is Nova major-version drift: a Nova upgrade can make the component throw or silently fail to render, with no Vue-level error surfacing in PHP logs (it appears in the browser console, if at all). With 13 stars, zero dependents, a single maintainer, and a release cadence of roughly one (2024-12-30), we are almost certainly the largest consumer of this package. There is no downstream ecosystem to absorb a regression on our behalf.

Secondary risks, all manageable but real:

  • Storage-format ambiguity — the package supports JSON array and delimited string. Undocumented choice here becomes a reporting and validation bug six months later.
  • Empty-state disagreement — null, [], and "" mean three different things to the field, the cast, and validation. This is the source of most "why is there a blank chip" tickets.
  • Authorization gaps — custom components occasionally render editable despite readonly / canSee. Needs verification with a non-admin user.
  • Unbounded input — no natural ceiling on pasted tags; without a max rule it degrades both data quality and form render performance.

Key questions for engineering (answers gate the go/no-go):

  1. What does composer.json actually constrain for nova, laravel/framework, and php — pinned, or floating? Floating constraints on a low-adoption package are a red flag.
  2. Which Nova major are we on, and does the package declare support for it explicitly?
  3. Does the package ship a compiled dist/, or does it require us to run a Node build step?
  4. Does the field respect canSee / readonly under a non-admin role?
  5. What breaks first when we upgrade Nova — and what is our stated fallback (subclass, fork, or in-house field)?
  6. Do tags need to be queryable by admins, or only editable? That single answer determines whether a JSON column is sufficient or whether we need a taggables join table and a generated column.

Integration Approach

Stack fit. Strong, conditional on Nova version alignment. Laravel + Nova + JSON column + array cast is the canonical shape the package was designed around. The recommended registration is minimal:

Tag::make('Tags')
    ->placeholder('Add a keyword and press enter…')
    ->rules(['array', 'max:10'])
    ->help('Max 10 tags, 40 characters each.');

Wrap this in a static factory (Fields::tags()) rather than copy-pasting chained calls across resources — when the package needs patching or replacing, there is exactly one place to change.

Migration path. Two distinct scenarios, and they should not be conflated:

Greenfield tagging. Add a json('tags')->nullable() column, cast to array (or AsArrayObject), register the field on one resource. Lowest-risk path; pilot here.

Replacing an existing comma-separated text column. This is a data migration, not a UI change, and it carries reporting/export/analytics impact — a PM-level call, not a field-swap. Sequence: add the JSON column alongside the old one → backfill with an idempotent command that splits, trims, de-dupes and re-encodes → verify against a production-like snapshot → cut the field over → dual-read for one release cycle → retire the old column only after confirmed parity. Do not repoint the field at the text column and hope.

Either way, write the persisted shape down as an internal contract next to the field registration. Future-you will not remember whether it is ["a","b"] or "a,b". Pick JSON array; it keeps tags queryable and removes parsing ambiguity from validation and exports.

Compatibility. The make-or-break axis is Nova 4 vs Nova 5. Validate on the exact pinned staging Nova version, not "latest." Pin the package version explicitly in composer.lock and add it to the dependency-review list — floating constraints here are how a silent storage-format change ships into production.

Also reconcile the three validation surfaces up front. Nova field rules() apply to the attribute as a whole; per-element constraints need dotted keys or a closure, and dotted-rule binding through Nova is not guaranteed across majors. If it doesn't bind reliably, move the constraint into a FormRequest or a model guard. Three rules are non-negotiable on day one: max total tags, max length per tag, non-empty after trimming.

Sequencing. Recommend a four-stage rollout:

  1. Spike (1 day). Read src/ — the Field subclass, its component() method, and the service provider. Do not trust the README for the FQCN. Confirm asset registration mechanism and whether dist/ ships.
  2. Pilot (1 resource, feature-flagged). Smallest viable use case — free-form keywords on Post, Article, or Customer. Create a record with 2–3 tags, save, reload detail, re-open edit, confirm chips return. That single round trip validates component registration, cast, storage format, and read path simultaneously.
  3. Harden. Add validation rules, model-level normalization (trim/lowercase/de-dupe on the way in, so seeders, imports, tinker and artisan commands all produce the same shape), a feature test that posts a tag array to the Nova endpoint and asserts persisted JSON, and a test that eleven tags fails validation.
  4. Expand or hold. Only after a full release cycle at stage 3 does a second resource make sense. Keep the previous representation available behind a one-line switch.

Operational Impact

Maintenance. The recurring cost is modest but must be owned, not assumed away. Budget roughly one to two days per year for Nova-upgrade revalidation, plus the pinning and dependency-review overhead. The package is a few hundred lines — small enough to fork if needed, which is the key property that makes the maintenance burden acceptable. Name a specific owner for this dependency before adoption, and record the trigger conditions for each escape hatch: (a) subclass the field and override component() to point at our own Vue component; (b) fork the package; (c) replace with an in-house Nova field. Deciding now, in writing, is the difference between a pragmatic dependency and a future incident.

Support. Effectively community-supported with a single maintainer and a small user base. Treat upstream as "best effort, may go quiet." Practical consequence: any bug that blocks us becomes our bug. That is tolerable for a field on an internal admin screen with a one-line fallback to a plain textarea; it would not be tolerable for anything customer-facing or revenue-adjacent. Scope the adoption accordingly.

Scaling. Backend cost is one column read and write — negligible. Rendering is client-side and bounded by tag count per record. The only realistic scaling concern is someone pasting 300 tags into a single record and making the edit form sluggish; the max:10-style rule is a performance guardrail, not just hygiene. Query-side is the more interesting question: a JSON column does not behave like text, and LIKE against it will be wrong or slow. Use whereJsonContains on MySQL/Postgres. If admin tag filtering becomes a first-class need, plan for a generated column or a proper taggables join table — the field is an input widget, not a query layer, and should not be mistaken for one.

Failure modes. Ranked by likelihood and impact:

Failure Symptom Detection Mitigation
Nova upgrade breaks component Field blank, no PHP exception Browser console, not storage/logs Keep textarea fallback behind a switch
Empty-state ambiguity Stray empty chip Feature test on null/[]/"" Normalize to one value at model layer
Dotted validation doesn't bind Over-limit tags persist Test posting 11 tags Move rules to FormRequest
Read-only bypass Non-admin can edit tags Manual test with restricted role Verify canSee/readonly pre-rollout
Silent upstream change Storage shape shifts composer.lock diff review Exact version pin
Long/special-char tags Broken layout, injection surface Test <script>, quotes, emoji, RTL Max-length rule; verify escaping

When the field renders blank, work the diagnostic ladder in order: did nova:publish run and is the compiled asset in public/vendor/; does component() match a registered Vue component; what does the browser console say; does the package ship dist/ at all. That ordered checklist belongs in the runbook, because the failure presents as silence.

Ramp-up. Low for engineers already fluent in Nova — the field registration is a few lines and the model-side pattern is standard Laravel. The genuine ramp-up cost is organizational: getting the team to treat the persisted shape as an internal contract, to normalize at the model boundary rather than in the form, and to resist the assumption that "tagging" means taxonomy. Set stakeholder expectations explicitly on deferred scope — autocomplete against large tag libraries, hierarchical taxonomies, merge/rename workflows, per-role permissions, audit trails, bulk operations — and write that deferred list down at the same time as the ship decision.

Bottom line for the TPM. Adopt as a constrained pilot, not a strategic dependency: one resource, feature-flagged, version-pinned, with a named owner and a documented exit path. The value is converting a small custom-field project into a bounded dependency-management decision. The accepted cost is ownership of a low-adoption package inside a platform (Nova) that is itself the real long-term commitment being made.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route