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 Link Field Laravel Package

carlson/nova-link-field

A Laravel Nova field that renders a clickable link directly in your resource index and detail views. Pair a display label with a target URL, optionally open in a new tab, and skip raw HTML or custom components for simple link display.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. carlson/nova-link-field is a presentational Nova field and nothing more: it takes an existing string column and renders it as an <a href> in index and detail views. There is no migration, no storage layer, no model concern, no service contract. Architecturally that is the cheapest possible footprint — one attribute in, one anchor out — which means the decision to adopt it is not an architecture decision at all. It is a UI polish decision scoped to the admin panel, and it should be funded and tracked as internal tooling (DevEx/maintenance), not as a product capability. Roadmap weight is effectively zero: no customer-facing surface, no revenue impact, no differentiation.

Integration feasibility. This is conditional and the condition is binary. The last release was 2020-02-26, placing it in the Nova 2/3, Vue 2, Laravel Mix era. On Nova 3 or earlier it is plausibly a drop-in. On Nova 4/5 the frontend is Vue 3 and a 2020-era compiled field bundle will not mount — the dangerous variant is a clean Composer install followed by a silently blank column, not a hard failure. Feasibility therefore reduces to one question that must be answered from the lockfile, not from the README: which Nova major are we on? If it is 4+, the package is a specification, not a dependency — roughly 60–120 lines to reimplement first-party.

Technical risk.

Risk Severity Note
Unmaintained (5-year gap, 22 stars, 0 dependents) High Nobody has validated this against a real Nova upgrade; we would be first
Silent failure mode (blank column) Medium Component-name mismatch or missing dist/js/field.js looks identical to "no data"
Stored XSS via href High A link field is the textbook admin-panel XSS surface; 2020-era components routinely omit rel="noopener noreferrer"
Auto-discovery assumptions Low Packages of this vintage predate universal Nova asset discovery
Setter API drift Low text() / target() / openInNewTab() spellings vary; grep src/Link.php before writing twenty fields

Key questions. (1) What Nova version is actually pinned in composer.lock? (2) Can the value ever be written by a non-superadmin, an import, or an upstream API — i.e., is href hostile input in our context? (3) Do we need validation, link-health checks, redirect resolution, or multiple links per record? If yes to any, this is the wrong tool. (4) Who owns the forked code in our repo, and is that person named before we start?

Integration Approach

Stack fit. Clean and narrow: PHP Field subclass plus a small Vue component. The idiomatic usage is a display/editor pair on the same attribute — Text::make('…')->onlyOnForms()->rules('nullable','url') for editing, Link::make('…')->text('Open asset')->target('_blank')->exceptOnForms() for display. That split sidesteps the question of whether the field even supports editing and keeps a plain input box for operators pasting new URLs.

Recommended path: fork-and-vendor, not composer require. With zero dependents and no release in five years, the honest model is copy, not depend. Two routes, both under a day: clone the source into app/Nova/Fields/Link, or scaffold with php artisan nova:field acme/link and port the behaviour. Either way the field lands under our CI, our code review, and our composer audit, and it never appears in the manifest as an unmaintained transitive dependency that surfaces during a dependency audit at the worst possible moment.

Compatibility gate before any work. Run composer why-not carlson/nova-link-field to see what in the lockfile blocks it. Then read three files in order — src/Link.php (the entire API surface), resources/js/components/IndexField.vue and DetailField.vue (component name and href binding), and dist/js/field.js (is the compiled asset actually committed, or are we rebuilding JS from a 2020 Node toolchain?). Under 30 minutes, and it is the cheapest insurance in the engagement.

Sequencing.

  1. Compatibility spike (half day): confirm Nova major, read the three files, decide depend-vs-port. Exit criterion: a written yes/no on Nova 4/5.
  2. Harden while porting (half day): scheme allowlist (http, https, mailto) enforced on save, rel="noopener noreferrer" on any target="_blank", :href attribute binding rather than v-html or string concatenation, plus a feature test asserting escaping of javascript: and quote-breaking payloads.
  3. One resource, one internal admin screen (hours): click through index → detail → edit in staging. Exit criterion: all three render and a hostile value is neutralised.
  4. Widen deliberately: enable on additional resources one at a time, never fifteen in one PR — the failure mode is silent, so breadth multiplies blind spots.

Where to put logic. Keep the field dumb. If a URL is computed (storefront, DAM, ticketing system), build it in a model accessor where it is testable in PHP, and leave Link::make('Column') as the whole field definition. This also documents the integration seam: the Nova resource mirrors an object owned elsewhere, and the link makes that ownership visible without building a sync.

Operational Impact

Maintenance. The real cost is ownership transfer, and it is small but permanent: a forked Nova field is code we carry across Nova upgrades. A first-party field of 60–120 lines is a one-place fix at upgrade time; a vendored 2020 bundle is the same fix plus the archaeology. If we take the dependency route instead, we inherit an unmaintained package with no upstream and no CVE feed — acceptable only inside an internal admin panel, and only with the scheme allowlist and rel hardening applied.

Support. There is no vendor to escalate to. Support means whoever forked it. That is a named-owner requirement, not a hope. Set expectations accordingly: bug reports route to the platform team, not GitHub.

Scaling. Effectively free. It is a presentational field over a string column — no queries, no background work, no storage growth, no per-record runtime cost. The only scaling surface is the number of resources carrying it, which is a review-discipline question, not a capacity one.

Failure modes and detection. The dominant risk is silent breakage. A blank index column almost always means a component-name mismatch or that dist/js/field.js never loaded — check the component name, then DevTools Network on a Nova index page, then the console for an "unknown custom element" warning. Works locally but blank in staging points at asset path, Nova::script(), or the package discovery cache (bootstrap/cache/packages.php, then package:discover). Console errors immediately after a Nova upgrade are expected — field bundles are the most common Nova upgrade breakage. The second failure mode is security: a javascript: or data: value saved into the column and rendered unescaped. Both are cheap to test for and expensive to discover in production.

Ramp-up. Under a day end to end for a mid-level Laravel engineer: the source is a few dozen lines of PHP and two small Vue components. The knowledge is not portable or scarce, which is itself a reason not to over-invest in the dependency.

Recommendation. Timebox the compatibility spike. On Nova 3 or earlier with a genuinely internal blast radius, vendor the field, harden it, ship it to one resource, and widen slowly. On Nova 4/5, skip the package entirely and build the field first-party from the source as a spec — same behaviour, no dead dependency, and Nova upgrades stay a one-place fix. Do not let it drift into composer.json as a casual or transitive dependency. Both endings are fine; the ambiguous middle is not.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
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
cgv/localized-resource