inspheric/nova-url-field
A URL field for Laravel Nova that displays URLs as clickable, copyable links in index, detail, and form views. Customize link text, target, and styling while storing values as plain strings, keeping long URLs readable and letting users open or copy them with one click.
Architecture fit. inspheric/nova-url-field is a single Nova field class, not a subsystem. It ships no models, migrations, routes, service providers, queues, config files, or compiled assets, and it never enters the request path that serves end users. Its entire integration surface is the fields() method of a Nova resource. That is the defining property for a TPM: an admin-presentation accelerator with a genuinely small blast radius — easy to approve, easy to discount, and easy to over-adopt. It fits only where Laravel Nova is already in place. It is out of scope for Filament, Livewire, or hand-rolled admin panels, and it is the wrong tool for customer-facing link management, redirects, previews, metadata enrichment, click analytics, or approval workflows. If the requirement grows past "store, validate, display, click through a URL," the answer is a custom field or a separate service, not a config flag on this one.
Integration feasibility. High and cheap, conditional on three gates. (1) The application runs Laravel Nova under a valid commercial license, including in CI — Nova is closed-source, so a pipeline composer install fails before any test runs if license credentials are missing. (2) The Nova major matches the package major: v3.x for Nova 5, v2.0.2 for Nova 4. (3) The PHP floor declared in the v3.0 composer.json is satisfied by the runtime. Given those, the work is one composer require, one import, and one field declaration per resource — realistically well under a day including review, install, and a staged single-resource validation. This is scoped as a task inside existing Nova admin work, not as a project.
Technical risk. Low severity, non-zero, and weighted toward governance rather than engineering.
composer.json diff directly, because the notes are an information gap, not a specification.javascript: or data: schemes, or rel="noopener noreferrer" on target="_blank". If any URL column accepts untrusted input, this is a security review item, not hygiene.->nullable() on both field and column, an empty submit stores '' and renders a link back to the current page. A 255-char column can truncate or throw on long query-string URLs, which reads as a rendering bug and isn't. Sorting is lexicographic on the raw string, so https://a.com and www.a.com sort far apart.Key questions to resolve before approval.
rel policy applies?Stack fit. Laravel + Laravel Nova + Composer. v3.x targets Nova 5; v2.x targets Nova 4. No service provider registration, no config publishing, no migrations, no asset compilation — installation is the composer require and nothing else. The one non-obvious environment dependency is Nova license credentials in CI; without them the pipeline breaks before the package is even exercised.
Migration path. This is not a data migration. The package stores the same value in the same column as the Text::make('Website') or Text::make(...)->displayUsing(...) closure it replaces. Rollback is a one-line git revert per field. The real migration is dependency governance: pin explicitly (^3.0 on Nova 5, ^2.0.2 on Nova 4), commit the lockfile, and annotate the internal dependency allowlist with "Nova 5+ only" so nobody pins v3 on an older panel. Critically, do not treat v3.0 as a drop-in upgrade from v2.0.2 — confirm the PHP constraint and any dropped Nova majors against your runtime first.
Compatibility. Three boundaries to hold: Nova major (hard coupling, breaks loudly), PHP floor (declared in composer.json, verify rather than assume), and Nova's own field API (the package uses standard field methods, so ->nullable(), ->rules('url'), ->onlyOnIndex(), ->hideFromIndex(), and ->canSee() all behave as expected). Where you need scheme sanitizing or custom anchor markup, the extension point is your own subclass of Url — document that path, because it converts an upstream stall or a future Nova break into a two-hour task instead of a rewrite.
Sequencing.
composer.json diff.target="_blank" semantics if untrusted input reaches the column.Maintenance. Plan to own the package in all but name. The maintenance load is not code churn — the surface is one class — it is tracking Nova majors, re-verifying compatibility on each Nova release, and keeping the version pin and allowlist annotation current. If the field becomes load-bearing across several resources, vendor or fork the class and record that decision. Keep it strictly in admin tooling; never let it reach a request path serving end users.
Support. MIT license, no SLA, no vendor, no security certification, no meaningful community. Escalation is internal — a named owner plus a documented fallback to Nova's native text field or a small custom field. That fallback document is the support plan; write it at adoption time, not at incident time. Stakeholders should hear this framed as a small, time-boxed OSS add-on that speeds internal tooling, not a strategic platform choice.
Scaling. Operationally negligible. There is no runtime cost in user-facing traffic, no queue, no storage, no background work, no third-party API. Cost scales with the number of admin resources using it and with the frequency of Nova upgrades — both small and predictable. The scaling risk is organizational, not infrastructural: if ten resources depend on it and upstream goes quiet, the fork becomes a real backlog item.
Failure modes and mitigations.
javascript:, data:) if untrusted input reaches the column: mitigate with starts_with:http,https or an explicit scheme allowlist, plus rel="noopener noreferrer" on target="_blank" anchors.->nullable(): set nullability on both the field and the column.->sortable() where admins expect domain grouping.Ramp-up. Hours, not days, for any developer already writing Nova fields: the API is one class with standard field methods, and the documentation is a handful of paragraphs. The real onboarding content is the governance policy — which Nova major maps to which package major, why the pin is explicit, where the fallback is documented, and who owns the fork decision. Capture that in the dependency allowlist and the pilot ticket so the knowledge does not live with one engineer.
How can I help you explore Laravel packages today?