proside/file-manager
Reusable file manager for Laravel 10/11/12 built in Livewire v4: directory tree, grid/list views, uploads, drag & drop, trash with restore, previews, search, multi-disk support and a file picker component. No iframe or external service.
.pem key management, an iframe and a postMessage handshake into a Livewire component that runs inside the existing Laravel auth/session. That is an infrastructure deletion decision — fewer deployables, fewer secrets to rotate, one less runtime to patch.<x-file-manager::picker> is the real adoption driver. It emits a plain <input type="hidden" name="...">, so existing FormRequest validation, mass assignment and controller code keep working. Product can greenlight "attach a file to X" features on any entity without a per-screen upload widget.root_resolver returning null, a string, or an array of roots lets one deployment serve users confined to their own subtree ("sees only conteudos/optivisao and below", trash filtered by originalPath, path traversal blocked by PathGuard). That converts a single-tenant admin tool into a plausible multi-client content console without a second codebase.FILE_MANAGER_DISK, media_url = route/storage/auto) rather than a rewrite. Worth citing when someone asks "what happens when the media volume outgrows the box?"Adopt when most of these are true:
content) or you accept publishing the prebuilt stylesheet. Either way, there is a styling step — budget it or the first demo looks broken.file-manager:prune-trash. Without it, trash_retention_days is decorative and files accumulate in apagados forever — a silent storage-cost and data-retention issue.Look elsewhere (or build) when any of these hold:
max_size (default 50 MB) and mimes allowlist. If users routinely push multi-hundred-MB video, you want direct-to-S3 presigned uploads instead.root_resolver answers "which subtree may this user see?"; it does not answer "who may delete, who may restore, who may permanently purge." Keep those rules in your own policies, or the permissions model will drift into config.filter is your only validation. It is a UI affordance, not a boundary — the hidden input is tamperable. If nobody owns server-side validation of the submitted path, do not ship it.Practical sizing: a picker swap into one existing form is a half-day to a day. A full rollout — publish and read the config end to end, Tailwind wiring, scheduler, root_resolver, migrating legacy path conventions, and rewriting ad-hoc upload widgets — is closer to one to two weeks with a proper review of the security surface.
For executives — one paragraph: We can delete a service. Today the file manager runs as a separate Next.js/React application that our Laravel app reaches through an iframe and authenticates with a bespoke JWT scheme: extra deployment, extra secrets to rotate, extra on-call surface, and a UI that cannot reuse our login. This package rebuilds the same functionality as a native component inside the Laravel app — same authentication, same session, no iframe, no tokens, no external host. We also pick up functionality the old tool never had: working search, restore from trash, configurable retention with scheduled cleanup, and storage that can move to S3 by changing a config value. The cost is integration work measured in days, not a licence, and the payoff is one fewer thing to deploy, secure and pay for.
For engineering — the honest short version:
Install is composer require plus package discovery; routes, the Livewire component and the Blade components register themselves. Three things must not be skipped, because all three fail quietly: add ./vendor/proside/file-manager/resources/views/**/*.blade.php to Tailwind's content (or publish the prebuilt CSS); schedule file-manager:prune-trash daily; and publish then actually read config/file-manager.php — disk => public, root => conteudos, trash => apagados are real assumptions about our filesystem, not placeholders. Store relative disk paths on models, never full URLs. Treat <x-file-manager::picker>'s filter as cosmetic and validate the submitted path in the FormRequest with a regex anchored to the configured root. The picker emits file-manager-selected with { paths: [...] } — always an array, even for single selection. root_resolver handles per-user scoping and PathGuard blocks traversal, but authorisation for destructive actions (delete, purge, restore) stays in our policies.
The caveats to state up front, not discover later: Livewire v4 is a hard requirement — that is an application-level upgrade decision, and it gates the whole conversation. The dependency itself is at zero stars, zero dependents, one maintainer, no advertised test suite: for planning purposes this is a first-party component we happen to consume, so we should assign an internal owner, wrap it behind a thin adapter, and accept that Livewire version bumps are coupled. No metadata/DAM features, no image derivatives, no virus scanning, no API — if any of those land on the roadmap within the year, they are our work, not the package's.
How can I help you explore Laravel packages today?