genealabs/nova-file-upload-field
A Laravel Nova field that adds a flexible file upload input to your resources, with support for multiple files, storage disks, and customizable validation. Drop it into any Nova resource to replace the default file field.
Architecture fit. This is a Laravel Nova custom field: a PHP Field subclass plus a compiled Vue component registered through Nova's asset pipeline, backed by upload/destroy routes. The integration surface is narrow and well-bounded — no queue workers, no daemons, no schema ownership beyond the columns it writes (typically a disk-relative path, optionally an original filename). For a standard Composer-managed Laravel + Nova monolith the shape is correct and the footprint is small. Critically, the package delegates filesystem policy to the host application via Laravel disks rather than owning storage configuration — the right boundary, and the thing that makes it swappable later. The real fit risk is not architectural, it is lifecycle: the repo is archived and frozen at the May 2024 release line (0.6.0, Laravel 11 compatibility). That is a point-in-time property which decays with every Nova and Laravel major.
Integration feasibility. The nominal path is composer require, add the field to a Nova resource, then configure disk(), path(), storeOriginalName(), acceptedTypes(), maxSize(), and optionally prunable(). Two friction points a TPM should budget for rather than discover: first, the package depends on the private, license-gated laravel/nova package, so Composer resolution only works where the Nova repository is already configured — a ticket problem, not a code problem, but it lands on whoever owns Nova licensing. Second, there is no validated compatibility matrix and effectively zero downstream consumers (0 dependents, 53 stars), so nobody has published evidence it works on the current Nova/Laravel line. With versions aligned, a Nova-experienced engineer is in the half-day to one-day range. Treat that estimate as a timeboxed spike with a written exit criterion, not a checklist.
Technical risk. High, concentrated in three areas.
The supplied signals agree: a low composite score (0.3875) against a high opportunity score (4.46) says the capability is in demand while this implementation is not healthy. That argues for building or forking the capability, not adopting this artifact unmodified.
Key questions.
post_max_size, upload_max_filesize, and reverse-proxy body limits) or direct-to-storage via presigned URLs?prunable() reliably cover this at volume?public disk with a custom prefix — or would Nova's built-in File field suffice after all?Stack fit. Fits standard Composer-managed Laravel + Nova shops with no exotic runtime requirements. If the requirement is "a file field on a Nova resource that targets a private disk and a custom storage path," this is architecturally appropriate and fills a genuine gap — Nova's built-in File field historically assumed the public disk and the nova/ prefix. If the requirement is a media/DAM pipeline — variants, transforms, rich metadata, virus scanning, accessibility, i18n — this is the wrong tool category and a maintained media library is the better fit. The PM decision this package informs is build vs. buy for admin upload UX, and for most teams the native fields are simply sufficient.
Migration path. The data migration is cheap, which is the single best thing about this dependency. The field persists a path (and optionally an original name) in ordinary string columns, so moving to a different field, a maintained alternative, or a media library is a column re-point plus a storage mapping exercise — not a schema rewrite. Make the path decision explicitly and write the cost of each into the ticket:
Compatibility. Unverified beyond Laravel 11 in the 0.6.0 release note. No Nova 5 claim, no PHP 8.3/8.4 evidence, no community signal to lean on. Before any sequencing decision, run a spike on the exact Nova/Laravel/PHP triple in staging and confirm the field renders, uploads, validates, and deletes. The spike's exit criterion should be explicit and binary — a working round-trip on a private disk — because the failure mode is a silent browser-side break, not a failing build.
Sequencing. If adopted at all, sequence it as a bounded stopgap, and place it before any Nova major upgrade, not after:
Maintenance. This is the dominant cost and it is entirely ours. Upstream is archived: no patches, no releases, no one to escalate to. Committing to it means committing to a fork with a repository, CI, a release cadence, and a named owner — an ongoing tax on a low-differentiation admin feature. It also sets a dependency-policy precedent: whether "archived but MIT" is an acceptable category in the admin tier at all. Making that call once, explicitly, in the policy saves the same debate on the next package that appears.
Support. Zero community safety net — 53 stars, 0 dependents means nobody else is running this in production and no ecosystem pressure exists to fix defects. Support load lands on our own engineers, and diagnosis is expensive because the failure mode is silent: a broken Vue component shows up as a blank or non-reactive admin field that looks like a config error. Expect an operator to discover it, not CI.
Scaling. Uploads are server-proxied through the PHP application, so volume scales against post_max_size, upload_max_filesize, PHP worker occupancy, and reverse-proxy body limits — not against storage throughput. That is fine for internal, low-traffic admin use and inappropriate for anything consumer-facing or high-volume. There are no S3 presigned direct-to-storage uploads, no signed URLs, no virus scanning, no image transformations. If any of those appear on a roadmap, this package is already the wrong answer and a media library is the correct one.
Failure modes. Name these in the risk register with owners:
prunable() actually covers cleanup; storage cost accrues quietly at volume and is a real line item, not theoretical.Ramp-up. Low for a Nova-experienced engineer: half a day to integrate, plus the spike, plus the fork setup. The knowledge that matters is not how to use the field — it is the runbook covering disk configuration, upload limits, ACL expectations, and cleanup behavior, which no upstream documentation will maintain for us. Write it once, assign it to the owner, and attach it to the replacement ticket so removal is a documented procedure rather than an archaeology project.
Bottom line. Low cost, low adoption, no support. Default to Nova's native fields. Adopt this only as a short-lived, explicitly owned and vendored stopgap in a legacy internal admin where private-disk storage is a hard, written requirement — and approve the removal plan on the same day you approve the adoption.
How can I help you explore Laravel packages today?