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 Fields Laravel Package

ostheneo/nova-fields

A collection of custom fields for Laravel Nova, adding enhanced form inputs and display components to help you build richer admin panels faster with less boilerplate.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. ostheneo/nova-fields is not a platform or a framework extension — it is a thin collection of Laravel Nova field types (a PHP field class plus a Vue component, registered through Nova's standard field API). Architecturally it plugs into a surface we already own and already pay for: Nova is a licensed dependency, and custom fields are a first-class, documented extension point (make(), rules(), withMeta(), resolveUsing(), fillUsing()). That means the integration is low-friction by design. The mismatch is lifecycle, not architecture: a package last released 2022-05-06 with 7 stars, zero dependents, a single maintainer, and no CI sits outside the support envelope of a modern Nova install. The honest framing for a TPM is that this is a source-code acquisition, not a dependency adoption — MIT lets us lift the field class and Vue component into app/Nova/Fields and own roughly one field type's worth of code. Scored opportunity (27.72/100) corroborates the read: admin-panel UX is internal-facing, and this is low-priority unless it unblocks a revenue-adjacent internal workflow (billing ops, support triage, moderation, compliance review).

Integration feasibility. Feasible, with a gate. Three axes decide whether it works at all and must be verified before any sprint commitment:

  1. Nova major — v3 (Vue 2, Mix) vs v4/v5 (Vue 3, Vite). A May 2022 release should be assumed to target Nova 3 until proven otherwise.
  2. php / laravel/framework constraints in the package composer.json — expect composer require --dry-run to fail closed on current Nova/Laravel, which is the normal case, not a surprise.
  3. Build artifacts — whether dist/js/field.js ships or the package is source-only and requires a local Mix/Vite build and nova:publish before anything renders.

If the app is genuinely on Nova 3, a pinned dependency is a short-lived interim. If it is on Nova 4/5 — the likely reality — the vendored fork is the path, and the effort is roughly a day of engineering to port, namespace, register the component, and write the tests.

Technical risk. The dominant failure mode is silent frontend breakage: a 2022-era component can compile cleanly and still fail to hydrate or serialize after a Nova upgrade, writing malformed data with no error surfaced. Secondary risks:

  • Vacuous validation. Nothing has stress-tested nulls, empty arrays, or repeat saves. Every usage must carry explicit ->rules() and ->nullable(); the field does not validate itself.
  • Storage-contract ambiguity. We don't know from the description whether it persists a scalar, JSON, or a cast object. The UI rendering correctly is not the test — the database column value is.
  • Namespace / registration drift when vendoring: $component string vs the Nova.booting() registration name must match, or you get a blank field with no PHP error.
  • Security posture. No upstream patch path, no visible audit trail. A component that round-trips user HTML without escaping is an inherited stored-XSS vector. This package should not touch money, PII, permissions, or audit paths.
  • No one to file against. No SLA, no CVE response, no maintainer capacity. Every adoption implicitly transfers maintenance to us.

Key questions for the engineering owner.

  • Which Nova major are we on today, and what is the committed date for the next major upgrade? (This package enters the upgrade checklist as a line item on day one.)
  • Does composer require --dry-run resolve, or does it fail closed?
  • Does the package ship a prebuilt dist/, or must we build it?
  • What is the persistence contract — scalar, JSON string, or cast object — and does it match an existing column or require a migration?
  • Which specific field type maps to a gap the Nova built-ins genuinely cannot fill? (Force this inventory; most "we need a custom field" requests collapse here at zero cost.)
  • Who is the named owner of the forked copy, and where does it live?

Integration Approach

Stack fit and the recommended pattern. Default to vendored fork, not runtime dependency. composer require only makes sense if we are confirmed on Nova 3 and the need is non-critical; anything else is a fork. Under the fork:

mkdir -p app/Nova/Fields/NovaFields resources/js/nova/fields
cp src/*.php app/Nova/Fields/NovaFields/
cp resources/js/components/*.vue resources/js/nova/fields/

Then rewrite namespaces, update use statements in resources, confirm the PSR-4 "App\\": "app/" mapping (default) so it autoloads without a dump-autoload we forget, and register the component ourselves in NovaServiceProvider::boot() via Nova::script(). Keep exactly one internal copy — per-resource variants of a forked admin utility is how small utilities become unmaintainable.

A third pattern — use it as a reference implementation and write our own — is often the highest-value outcome. It is a small, working example of Nova's field API (withMeta(), resolveUsing(), fillUsing(), FormField-based component). Reading it is cheaper than reading Nova's field-authoring docs cold, and MIT means we can copy the patterns freely. For a TPM, that outcome costs almost nothing and produces domain-appropriate code with no inherited data contract.

Migration path. No data migration should be required for the first use case if we pick a resource with an existing nullable column and normalize at the field boundary. Keep the model's cast as the source of truth and normalize in the field:

->resolveUsing(fn ($v) => is_string($v) ? json_decode($v, true) : $v)
->fillUsing(fn ($request, $model, $attr) => $model->{$attr} = json_encode($request->input($attr) ?? []))
->rules('nullable', 'array')

Do not let a forked component dictate our storage format. Normalization at the boundary is the cheapest insurance against a re-port forcing a backfill.

Compatibility handling. Verify the three axes (Nova major, PHP/Laravel constraints, Vue 2 vs Vue 3 tooling) before code lands, and treat a failure as the expected case. Do not fight Composer resolution with minimum-stability or --ignore-platform-reqs — that is a signal to move to the fork, not an obstacle to route around. onlyOnForms() is the cheapest guard against the most common custom-field failure: a component that renders the form correctly but blows up or renders blank in the index/detail views because the developer never implemented those modes.

Sequencing.

  1. Inventory first (1–2 hours). Enumerate the admin screens that genuinely need a bespoke input versus Nova built-ins plus relationship and formatting config. Close most requests here.
  2. Source read (20 min). Clone, read composer.json, src/*.php, and the .vue component. Answer: $component string, persistence contract, whether dist/ exists.
  3. Resolver check. composer require --dry-run. Fails → fork. Resolves → Nova 3 confirmed, interim pin acceptable.
  4. Single-field, single-resource spike behind a flag. Add rules and nullable(), save a record, dd() the attribute, assert the DB column value.
  5. Test pair. One test asserting jsonSerialize() shape; one feature test posting to the Nova update endpoint and asserting the DB value. That pair is what keeps a forked field honest across Nova upgrades.
  6. Widen one resource at a time. Verify data round-trip and any CSV/export path before broadening.
  7. Write the README and the upgrade-checklist entry at fork time, not after the engineer who ported it has moved on.

Operational Impact

Maintenance. This is the real cost and it is permanent. License and integration cost are near zero; ongoing ownership is not. The package becomes our code the moment we fork it, and each line we change inside the Vue component is a line we re-port at the next Nova major — so keep that surface as small as possible. Preference order for extension: withMeta() for props → resolveUsing()/fillUsing() for the data contract → overriding jsonSerialize() → only then editing the component.

Support. There is no upstream to file against. No SLA, no maintainer capacity, no CVE response path, no visible audit trail on the component. This should be reflected in how we classify it: internal tooling, owned, best-effort — not a dependency we can point at in an incident review.

Scaling. Volume is a non-issue; the field is a form input, not a hot path. The scaling constraint is organizational: every low-adoption Nova package we adopt implicitly transfers its maintenance to us, and that compounds across the admin surface. A standing metric worth tracking is "what percentage of our Nova admin surface is self-supported?" This package is a concrete data point for that number.

Failure modes and detection.

  • Not rendering at all — usually a missing/unbuilt dist/js/field.js or a missing Nova::script() call. Symptom: Vue warn: Unknown custom element: <your-field> in the browser console. Cache-bust Nova::script() with a hash argument if a stale bundle keeps loading.
  • Rendering but persisting wrongly — the dangerous one. No error is surfaced; bad data lands in the DB. Mitigation is the test pair above, plus a dd($field->jsonSerialize()) in the resource.
  • Index/detail view blank or crashing — mitigation is onlyOnForms() until those modes are implemented and tested.
  • Registration-name mismatch — blank field, no PHP error. Mitigation is a deliberate check that $component equals the Nova.booting() name.
  • Composer resolution failure mid-sprint — mitigated by running --dry-run at evaluation time, not during the sprint.

Debugging runbook (in order). Browser console for registration warnings → nova:publish and asset rebuild → dd($field->jsonSerialize()) → the actual DB column value after save → $component string vs JS registration name. That sequence resolves most issues in under ten minutes, which is itself a reason to document it in the fork's README.

Ramp-up. Low for anyone with Nova field experience; the field API is conventional and the package is small enough to read end to end in under half an hour. Budget: ~20 minutes of source reading for evaluation, ~1 day to vendor, namespace, register, build assets, and write the two tests, plus a modest ongoing allowance at each Nova major upgrade. Do not use it on security-adjacent surfaces — money, PII, permissions, audit paths — where the absence of a patch path is disqualifying regardless of how small the code is.

Decision rule to carry forward. Adopt as a runtime dependency only if the app is genuinely on Nova 3 and the need is non-critical; otherwise fork the relevant class into owned code under app/Nova/Fields, name an owner, and log the Nova-upgrade line item at fork time. If a built-in Nova field, an official Laravel package, or a higher-adoption community package covers the same need, take it — switching cost is trivial at this scale, and adoption count is a cheap, reliable tiebreaker.

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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource