drpshtiwan/livewire-media-selector
A lightweight WordPress-style media selector for Laravel and Livewire. Browse, search, paginate, and upload files from your disks, with single or multi-select, drag-to-reorder, collections, soft deletes, and trait helpers for quick model integration.
Architecture fit. This is a leaf UI component, not infrastructure — a Livewire modal that browses, uploads, and selects files off your Laravel disks. That keeps blast radius small: it sits at the edge of the admin surface and does not intercept requests, jobs, or the container. The important architectural detail is that it ships its own migration and Media model, so it does not read your existing media library — it wants to become the system of record. Everything downstream (trait helpers attachMedia / syncMedia / getMediaUrl, collections, trash/soft-delete) assumes that table is authoritative. Confirm that intent before you plan around it; retrofitting an adapter onto Spatie Medialibrary or an in-house assets table is not a documented path.
Integration feasibility. Low effort, well within a single sprint. composer require, four publish tags (config, migrations, views, assets), storage:link, and one Blade tag with wire:model. The honest cost is not installation — it is the config review (disk, directory, allowed_extensions, maxUploadKb, can_upload, table, model, show_thumbnails) and the fact that the CSS is not auto-injected, which is exactly the kind of step that works locally and silently breaks a deploy pipeline.
Technical risk.
| Risk | Severity | Notes |
|---|---|---|
| Bus factor = 1 (20 stars, 0 dependents) | High | No third-party validation anywhere in the ecosystem. MIT + small, publishable codebase means forking is viable, but you are the maintainer of last resort. |
| Version churn | Medium–High | Three majors (1.x → 3.0.0 → 4.0.0) with documented breaking changes and config key renames in a short window. |
| Pre-4.x security posture | Critical if on old lines | 4.0.0 #[Locked]-ed all permission and storage/validation properties. Earlier versions allowed a crafted Livewire request to flip canDelete, empty allowed_extensions to smuggle an executable upload, or repoint the disk. Never run anything but 4.x. |
| Upload serving model | Medium | Files are served from a public disk by URL; SVG is disabled by default for good documented reasons. Re-enabling it without sanitisation is a stored-XSS decision you own. |
| Tailwind-only UI | Medium | Views are publishable, so restyle is feasible, but if your design system is not Tailwind you are buying a rewrite of the markup, not a theming exercise. |
Credit where due: the 4.0.0 write-up reads like a real threat model — server-resolved locked props, server-side re-validation of selections and deletions against the scoped query, explicit SVG guidance. That is more security rigour than most packages at this star count.
Key questions.
Stack fit. Hard gate first: PHP 8.3+, Laravel 12–13, Livewire 3.5+ or 4.x. Run composer show laravel/framework livewire/livewire before you write anything into a plan. On Laravel 11 or earlier you are pinned to 1.x, which predates the #[Locked] work — treat that as a no-go rather than a fallback.
Compatibility checklist before sequencing work:
php artisan storage:link in the deploy provisioning step, not a README footnoteconfig/media-selector.php reviewed line by line and committed under version controlMigration path. Two branches, pick one explicitly:
HasMediaSelector. Fastest, and the trait helpers earn their keep. Accept that you inherit its schema and its majors.model/table keys help but are not a general-purpose abstraction.Sequencing.
allowed_extensions, upload ceiling, can_upload/canDelete flags derived from your own Gates/Policies — the README is explicit that the package will not grant an action you did not enable, so derive, don't default.avatars).Maintenance. Budget a recurring line item, not a one-off. The pattern here is frequent majors with config key renames — pin the exact minor, read the changelog for every bump, and re-diff config/media-selector.php after each upgrade. Changelog and release discipline are genuinely good (that is what earns the maturity signal), so the maintenance is predictable rather than archaeological. The unpriced risk is the day the maintainer stops: plan for a fork, and prefer a shallow integration so the fork stays cheap.
Support. No SLA, single maintainer, docs site plus video demo. Fine for an internal admin tool; not fine for anything customer-facing on a critical path. Escalation path is a GitHub issue, then your own engineer.
Scaling. Three things bend first:
show_thumbnails toggles rendering, it does not resize. Large originals in a paginated grid will cost bandwidth and layout time. Either enforce upload dimension/size limits via config or add a resizing step of your own.maxUploadKb and your PHP upload_max_filesize/post_max_size/memory limits are the real ceiling. Size the app server for concurrent uploads, not steady-state reads.Failure modes to pre-write runbooks for:
| Failure | Symptom | Mitigation |
|---|---|---|
storage:link missing after deploy |
Broken previews, 404s on selected media | Provisioning step + smoke test on deploy |
| CSS not published | Unstyled modal, invisible or overlapping controls | Build-pipeline asset publish + visual smoke test |
| Permission flags left at permissive defaults | Users see delete/trash they should not | Derive every flag from Gates/Policies; test as a low-privilege user |
| File deleted off disk while record remains | Preview exceptions | Largely handled in 4.x by safe URL/MIME helpers — verify with a deliberate deleted-file test |
| Config drift after a major bump | Renamed keys silently ignored, limits reset | Version-controlled config + diff on every upgrade |
| SVG re-enabled without sanitisation | Stored XSS from public disk | Keep SVG in the deny list; if unavoidable, sanitise server-side |
| Running a pre-4.0 line | Client-side permission/type tampering | Pin ^4.0; add a CI assertion on the locked version |
Ramp-up. One engineer, roughly half a day to a working picker and a further half-day for the config and permission review. Team-wide adoption is closer to a day once you add the design/brand pass and the first set of collection conventions. Documentation quality is above average for this tier, so the ramp is dominated by your decisions — table ownership, permission derivation, upload limits — rather than by learning the package. Front-load those three decisions and the component itself is close to turnkey.
How can I help you explore Laravel packages today?