liberusoftware/files-media-livewire
A Livewire UI layer for Liberu Files Media, providing reactive upload, browsing, preview, and management components for files and media in Laravel. Drop into Blade views, connect to existing storage and models, and handle validation and file operations without custom JavaScript.
This package is a presentation adapter: module-files-media-livewire almost certainly wraps the domain layer (liberusoftware/module-files-media) in Livewire components rather than providing storage/media logic itself. Install both, not just this one.
Install the parent module first.
composer require liberusoftware/module-files-media
composer require liberusoftware/files-media-livewire
If Composer complains about a missing dependency, check the package's composer.json on GitHub — the parent requirement will be listed there and tells you which version of the module to pin.
Confirm service-provider discovery. Laravel will auto-register the provider if extra.laravel.providers is set. If routes or views 404/blank, manually register the provider in bootstrap/providers.php (Laravel 11+) or config/app.php.
Publish anything that ships. Run, in order, and read what each one exposes:
php artisan vendor:publish --provider="LiberuSoftware\FilesMediaLivewire\FilessMediaLivewireServiceProvider"
Look specifically for config/files-media-livewire.php, resources/views/vendor/..., and any public assets. If the provider name doesn't match, run php artisan vendor:publish interactively and pick the package from the list.
Read the source before the README. With 0 stars and no dependents, docs are unlikely to be complete. Spend 15 minutes on src/, in this order:
src/Livewire/ — the actual components you'll mount.src/Http/ / routes/ — any registered routes and their middleware.Concerns/ or Traits/ — usually where model coupling lives.composer.json — the exact parent-module version, PHP, and Livewire constraints.First use case. The realistic day-one use is embedding a file/media browser or uploader into an existing Livewire screen. In a Blade view:
@livewire('files-media::browser', ['model' => $post])
The exact component alias will be in the provider's Livewire::component(...) or #[Component] annotation — copy it from there rather than guessing.
Treat it as a UI layer, not a storage layer. Keep all persistence, disk, and conversions in the parent module-files-media package or your own model code. The Livewire component should only orchestrate UI state and dispatch events.
Mount on a model, not a global singleton. The cleanest integration is one component per parent model (e.g., Post, Product) using the parent module's media relationship/trait. Pass the model as a mount parameter rather than a global $mediaId, so multiple components on the same page don't collide.
Compose, don't fork. If you need a different toolbar or upload zone, extend the package component and override render() / a view rather than copying it into resources/views — you lose upstream fixes otherwise. Use @include of the vendor view inside your own wrapper if you just want layout changes.
Event-driven wiring between components. A common pattern is a picker component plus a separate preview/detail component. Have the picker dispatch a namespaced event (e.g., files-media.selected) and listen in the consumer:
#[On('files-media.selected')]
public function onSelected(int $mediaId): void { /* ... */ }
Check the package for existing events before inventing your own — adapters usually emit select/create/delete events already.
Form + upload flow. Bind the Livewire component to a form object (Livewire v3 Form) or a $this->validate() call in the component, and let the package handle the actual temporary upload. Validate at the component boundary (mimes, max) rather than relying on the package defaults, which are often permissive.
Authorization. Don't assume the package enforces policies. Add a Gate check in your wrapper view or a middleware on the containing route:
@can('update', $post)
@livewire('files-media::browser', ['model' => $post])
@endcan
The package has no dependents and low usage, so treat authorization as your responsibility.
Integration tips.
readonly/canUpload property; otherwise hide the toolbar in CSS and remove the upload action in a subclass.Testing. Use Livewire::test() against the component to lock down behavior before you depend on it:
Livewire::test(Browser::class, ['model' => $post])
->assertSee('Upload')
->call('delete', $media->id)
->assertDispatched('files-media.deleted');
This is your safety net given the maturity of the package.
module-files-media version. If you composer update the parent, the adapter's expected methods/events can drift and you get BadMethodCallException or silently missing media. Lock both together in composer.json and run the parent's migrations before mounting the component.composer.json for the Livewire constraint. v2 components use $listeners, emit, and mount()-only lifecycle; v3 uses attributes (#[On]), dispatch(), and closures. Copying patterns from one into the other is the most common source of "event never fires."@livewire('files-media::browser') throws "component not found," grep the provider for Livewire::component( or #[Component] — the alias is defined there, not in the README.WithFileUploads writes to livewire-tmp on the local disk first. If storage:link isn't run or FILESYSTEM_DISK points at S3 without a configured temporary bucket, uploads "succeed" and then 404. Reproduce with php artisan storage:link and config/filesystems.php before blaming the package.mimes:/max: at the call site.resources/views/vendor/ stops receiving upstream fixes. Keep a short list in your repo of what you've overridden so you can diff on upgrade.failed_jobs first.php artisan vendor:publish --tag=...)? The --tag names are in the provider's publishes() array.register() and boot() — routes, Livewire components, Blade directives, and config merges are all there and are usually the intended customization hooks. Overriding a component class via Livewire::component('files-media::browser', MyBrowser::class) in your AppServiceProvider::boot() is often cleaner than a hard fork.NOASSERTION license, treat this as internal-grade code: pin the exact version, wrap it behind your own thin component so you can swap it out, and write Livewire::test() coverage around the flows you depend on. If the upstream module is abandoned, you should be able to replace the adapter without touching your controllers or views.How can I help you explore Laravel packages today?