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

Livewire Media Uploader Laravel Package

codebyray/livewire-media-uploader

A reusable Livewire v3/v4 component for Spatie Media Library with publishable Tailwind or Bootstrap views, drag-and-drop uploads, inline caption/description/order editing, reordering, conflict strategies, SHA-256 duplicate detection, and optional authorization hooks.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit

This package is a UI-layer adapter, not a platform. It wraps Spatie Media Library in a reusable Livewire component and ships a publishable Blade view, which means its architectural fit is entirely determined by two pre-existing decisions: (1) is the app a Laravel + Livewire monolith, and (2) is Spatie Media Library already the media abstraction of record?

  • Strong fit if we are on Laravel 12/13, Livewire 3/4, PHP 8.2+, and Spatie Media Library is already installed with HasMedia models, configured disks, and conversions. In that case this package eliminates a recurring piece of bespoke work — drag-and-drop, progress, metadata editing, reorder, delete confirmation — that otherwise gets rebuilt (inconsistently) on every model that needs uploads.
  • Weak fit if we are on Inertia/React/Vue, or on Laravel 10/11. The Livewire requirement is hard, and the maintainer explicitly dropped Laravel 10/11 at v0.5.0 on security grounds (Composer audit blocks fresh installs on those lines). Being stuck on v0.4.x means immediately inheriting an unsupported branch — that is a disqualifying condition, not a trade-off.
  • Adoption cost shifts, does not disappear. If Spatie is not already in the stack, this package drags in spatie/laravel-medialibrary, its migrations, disk conventions, conversion pipeline, and queue configuration. That is a substantial platform decision being made implicitly by a 7-star UI component.

The correct mental model for the TPM: we are not evaluating a component, we are evaluating whether to standardize the upload surface of the application on Spatie's data model with a thin, third-party Livewire skin on top.

Integration feasibility

High on the happy path, with a small number of sharp edges that only surface in production.

  • Install is a single composer require with auto-discovery; two component aliases are registered (media-uploader, media.media-uploader), so both naming conventions work.
  • Props are well-documented and cover the practical surface: model targeting (instance, string+id, FQCN, morph alias, dotted path, per-instance alias map), collection, preset, multiple, showList, accept, allowedTypes, allowedMimes, maxSizeKb, onNameConflict, skipExactDuplicates, authorizeAbility.
  • Config and views are publishable under discrete tags (media-uploader-config, media-uploader-views), which is the right escape hatch for a package this young.
  • The deferred "create flow" (pick files before the model exists, attach after save via a parent-held pendingPostId) is the single most complex integration path and the one most likely to need a spike. It introduces a pending-media state machine the parent component must own.

Feasibility gaps to verify before committing:

  • Metadata storage. Caption/description/order editing implies a persistence location. order_column is native Spatie; caption/description are almost certainly custom_properties or added columns. We need to know which, because a schema change on the media table is a different risk class than a JSON blob.
  • Tailwind version. The README does not state Tailwind 3 vs 4. The default view depends on utility classes and a class-based dark strategy, so an app on Tailwind 4 or on a non-standard dark-mode config will need view edits on day one.
  • Alpine provenance. Overlays, progress, and delete confirmation are Alpine-driven. Livewire 3 bundles Alpine; Livewire 4's Alpine packaging must be confirmed, otherwise the component renders but the confirm/delete interactions silently do nothing.

Technical risk

Rated medium-high, concentrated almost entirely in supply chain and versioning rather than in code quality.

  • Pre-1.0 semver. At 0.x, minor bumps may carry breaking changes. Every composer update is a potential deploy-time break with no deprecation window.
  • Bus factor of one. 7 stars, 0 dependents, single maintainer, no ecosystem validation. We would be among the first production consumers. The GitHub Actions test matrix across PHP/Laravel/Livewire combinations is a genuine credibility signal — it indicates the maintainer tests the support matrix rather than asserting it — but it does not substitute for production usage.
  • Transitive constraint risk. The spatie/laravel-medialibrary ^10.12|^11 ceiling means a Spatie v12 release blocks us until the author updates, and Spatie is the dependency we actually care about.
  • Publishing the view creates a fork. Customizing Blade is the intended workflow, but it means upstream fixes stop reaching that file. Over time our published view drifts and reconciliation becomes manual work.
  • Authorization is opt-in. The authorizeAbility hook delegates to our Gate/Policy, which is the right design (no bundled auth package), but the default posture must be confirmed. An uploader mounted without ability wiring is an unauthenticated write path to our media collections.
  • Large-file path is the weakest link. The shipped videos preset allows 102,400 KB. Livewire's temporary upload rules, upload_max_filesize, post_max_size, Nginx client_max_body_size, and PHP-FPM timeouts all sit between the browser and Spatie. Files traverse the web tier twice (browser → PHP temp → storage) rather than going direct-to-S3. This is a known, architectural limitation of Livewire uploads, not a defect in this package — but the package's generous default preset will hit it.
  • Private disk previews. On S3/private disks, preview overlays depend on generated (possibly signed, expiring) URLs and correct CORS. Untested until we test it.
  • Accessibility and i18n. No language files are documented, so UI strings live in the Blade and are English-only. Drag-and-drop plus Alpine modals raise keyboard-navigation and screen-reader questions. Both are fixable in a published view — at our cost.

Key questions

  1. Which Laravel/Livewire/PHP versions are we actually on, and does that land us on the supported v0.5.x line or the EOL-adjacent v0.4.x pin?
  2. Is Spatie Media Library already in production, with HasMedia models and conversions? If not, is this package the trigger for adopting it?
  3. Where do caption/description persist — custom_properties or media table columns? Does adoption require a migration?
  4. Does authorizeAbility fail closed or fail open when omitted? Can we demonstrate a denied upload?
  5. What Tailwind version and dark-mode strategy does the shipped view assume?
  6. Under Livewire 4, what is the Alpine dependency story for overlays and confirmation modals?
  7. What are the exact Livewire temporary-upload rules and disk configuration required to support the 100 MB video preset, and what does the failure look like to the user when exceeded?
  8. Is SHA-256 duplicate detection atomic under concurrent uploads of the same file, or a check-then-insert race?
  9. How does the deferred create flow clean up pending uploads when the user abandons the form?
  10. What is the maintainer's stated support/response posture, and what is our internal fork trigger — six months without a release?

Build-vs-buy signal: the component surface is small. If the answer to Q1 or Q2 is unfavorable, or if the maintainer goes quiet, vendoring the component into our own namespace is a low-cost exit rather than a rewrite. That exit option materially de-risks adoption and should be stated up front as the contingency.

Integration Approach

Stack fit

Adopt only if the following all hold: Laravel 12 or 13, PHP 8.2+, Livewire 3 or 4, Spatie Media Library already present, and a Blade-rendered front end with Tailwind (or Bootstrap, if that is our design system). Any one of these failing downgrades the assessment from "adopt" to "reference implementation" — read the source, copy the patterns, do not take the dependency.

Where it fits, the value is standardization: one uploader UX across every model with media, one config file for presets and limits, one place to fix an accessibility bug, instead of N bespoke implementations.

Migration path

Three distinct paths, in ascending risk:

  1. Greenfield collection (lowest risk). A new feature with a new Spatie collection and no legacy media. This is the correct pilot — no data migration, no user-facing regression surface, and it exercises the full component (upload, metadata, reorder, delete) against real requirements.
  2. Replacing a bespoke upload UI on an existing collection (medium). Existing media rows are untouched because the component attaches through the Spatie API, not through its own tables. The real work is behavioral parity: which conflict strategy our current UI used, whether singleFile() semantics match, whether existing order_column values survive reordering. Confirm that our caption/description storage matches what the component reads and writes before swapping any UI.
  3. Deferred create flow (highest). Parent component owns a pendingPostId-style handoff. Build this last, behind the pilot, and only if the create-with-attachments UX is a genuine product requirement — it is the most failure-prone path and the least exercised by the package's examples.

The migration that must not be overlooked: there is no automated path back. Once uploads flow through this component, the published Blade view becomes part of our codebase. Reverting means restoring our prior UI, not just removing the dependency.

Compatibility

Pin to a narrow range (0.5.*) and treat every minor bump as a potential breaking change requiring review. Add the package to dependabot/renovate but explicitly disable auto-merge. Verify the Spatie constraint (^10.12|^11) against our installed version before install — a v12 in the lockfile makes the package uninstallable.

Confirm in a spike, not in a document: Tailwind version compatibility, dark-mode class strategy against our layout, Alpine availability under our exact Livewire version, and the behavior of the two component aliases under Livewire 4's component resolution.

Sequencing

  1. Spike (1–2 days). Install on a throwaway branch. Wire one collection. Explicitly test: a file at the preset's size ceiling, a private/S3 disk preview, singleFile + multiple combination, a denied authorizeAbility call, keyboard-only upload and delete, and the page with Alpine deliberately broken (to see the degradation mode). This spike answers most of the key questions above.
  2. Publish and own. Immediately publish config and the theme view into the repo rather than referencing vendor paths. This makes drift visible in diffs and gives us a place to fix i18n and a11y without fighting upstream. Publish the Tailwind theme only; do not carry the Bootstrap theme as dead code.
  3. Pilot. One greenfield collection on a low-traffic internal or admin surface. Instrument upload failures and validation rejects — those are the signals that tell us whether our limit configuration matches reality.
  4. Harden. Lock the version, add feature tests covering attach/edit-meta/reorder/delete/conflict-strategy, add the authorization policy to the checklist for every mount point, and write the runbook entry (below).
  5. Roll out collection by collection, each with an explicit policy and limit review. Never roll out "everywhere" in one release.
  6. Standing contingency. Keep the vendoring escape hatch documented and estimated. If upstream stalls or a 0.x break lands during a release window, we copy the component into App\Livewire and move on. Budget: small.

Operational Impact

Maintenance

Recurring, modest, and non-zero — this is not a fire-and-forget dependency.

  • Version pinning discipline. Narrow constraint, no auto-merge, manual review of each 0.x bump. Read the changelog on every update; at 0.x it is the only warning we get.
  • Fork reconciliation. Published Blade means upstream view fixes are ours to port. Allocate roughly one to two developer-days per quarter for upgrades plus drift reconciliation, and more in any quarter where a breaking 0.x change lands.
  • Upstream monitoring. Track release cadence and issue responsiveness. Define the fork trigger now — e.g., no release in six months, or an unanswered security issue — so the decision does not get made in the middle of an incident under pressure.
  • Configuration sprawl. Presets are driven by MEDIA_* environment variables that map into config/media-uploader.php. Every environment change requires php artisan config:clear, which must be in the deploy script. Config cached in production and stale env values is a classic silent-failure pairing here.

Support

There is effectively no external support channel. 7 stars and zero dependents means questions go unanswered publicly and there is no community knowledge base to search. Internal ownership is the only realistic model: a named maintainer, a runbook, and a documented list of mount points (which model, which collection, which policy, which preset) so that an on-call engineer can diagnose an upload failure without reading the package source.

The one thing that helps: the GitHub Actions test matrix across PHP/Laravel/Livewire combinations means the supported matrix is empirically verified, so "does it work on our version combination" is answerable by reading CI rather than by trial.

Scaling

  • Byte path is doubled. Uploads stream browser → PHP temp storage → final disk. Both the web tier and the temp disk must be sized for peak concurrent upload volume, not just the final storage cost. If the temp disk is local and the app runs on ephemeral containers, an upload can outlive the container's storage headroom.
  • PHP-FPM workers are the real ceiling. Each in-flight upload occupies a worker for the duration of the transfer. multiple uploads multiply this. Concurrency planning should be done against worker count, not against request rate.
  • No direct-to-storage option. There is no presigned-URL path. For genuinely large video or bulk document workloads, this component is the wrong tool and the requirement should be redirected to a direct-to-S3 flow rather than worked around.
  • Conversion cost. The README's own example uses nonQueued() conversions. In production, queued conversions are usually correct, but then the UI shows originals until the queue drains — a UX and support consequence that must be decided deliberately, not inherited from the example.

Failure modes

Ranked by likelihood × user impact:

  1. Size-limit mismatch. Component maxSizeKb disagrees with Livewire temp-upload rules, upload_max_filesize, or Nginx limits. User sees a generic or silent failure. Mitigation: align all four, document the effective ceiling per preset in the UI.
  2. singleFile() + multiple silent data loss. Documented by the author, but a genuine footgun: every file processes, only the last survives, and the user believes they uploaded a set. Mitigation: never set multiple on a single-file collection; enforce in code review and a feature test.
  3. Alpine failure = no destructive actions. If Alpine is absent or broken, overlays and confirmation modals fail. Degradation may be a dead delete button or, worse, an unconfirmed delete. Verify the degradation mode in the spike.
  4. Authorization omitted at a mount point. A new page mounts the uploader without policy wiring, opening a write path. Mitigation: treat policy wiring as part of the component's definition of done.
  5. Abandoned-form orphaned uploads. In the deferred create flow, files uploaded before save have no owning model. Confirm cleanup behavior; otherwise temp storage grows unbounded.
  6. Dedupe race. Concurrent identical uploads can both pass the SHA-256 check. Acceptable for most products, unacceptable if storage cost or uniqueness is a hard requirement.
  7. Private-disk preview breakage. Signed URL expiry or CORS misconfiguration yields broken thumbnails with no obvious error.
  8. Dark-mode text collapse. Class-based dark mode not enabled in our Tailwind config produces invisible or unreadable text — cosmetic, but the kind of cosmetic that reads as a broken product.
  9. Deploy-time break from a 0.x bump. A composer update during a routine release surfaces a BC break at the worst moment. Mitigation: pinned versions and a staging deploy that exercises an upload.

Ramp-up

Low for a Laravel-fluent team: half a day to a working upload in a dev environment, two to three days to production-hardened (limits, policy, theming polish, i18n, accessibility pass). The README is above average for a package this size — copy-paste examples for every targeting mode, a clear warning about singleFile(), and an honest note about why Laravel 10/11 support was dropped, which reads as a maintainer who understands that security posture is a feature.

The non-trivial ramp is not the package — it is Spatie Media Library itself. Disk strategy, conversions, responsive images, queued processing, and custom_properties are where the learning curve actually lives. Teams already running Spatie will onboard this in an afternoon. Teams adopting Spatie because of this package should treat the Spatie evaluation as the primary decision and the uploader as a downstream convenience.

Bottom line. Adopt on the supported matrix with a narrow pin and published views, pilot on a greenfield collection, and keep vendoring as a funded contingency. Decline — or copy the patterns without the dependency — if we are outside the supported Laravel/Livewire/PHP matrix, if Spatie is not already the media layer, or if large-file/video handling is a core requirement rather than an edge case.

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.
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk