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

Filemanager Laravel Package

mwguerra/filemanager

A full-featured file manager for Laravel and Filament v5 with database or storage browsing, S3/MinIO support, drag-and-drop uploads, file previews, multi-selection, and configurable security permissions.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Filament 5 / Laravel 12 / Livewire 4 plugin, so the first real decision is whether your panel is already on that stack. If you're on Filament 4 / Laravel 11, you're pinned to the ^1.0 line and will hit API differences (notably ->actions() → ->recordActions() and ->bulkActions() → ->toolbarActions() on tables) when you eventually upgrade. Confirm composer show filament/filament and livewire/livewire before installing; a mismatch here is the most common reason people bounce off this package.

Minimal install:

composer require mwguerra/filemanager:"^2.0"
php artisan vendor:publish --tag=filemanager-config
php artisan migrate
php artisan filemanager:install

Then register the plugin — nothing renders without this step, and it's easy to forget because the pages appear "missing" rather than erroring:

use MWGuerra\FileManager\FileManagerPlugin;

public function panel(Panel $panel): Panel
{
    return $panel->plugins([
        FileManagerPlugin::make(),
    ]);
}

Where to look first: the publishable config/filemanager.php after vendor:publish — it holds the disk, upload limits, MIME allowlist, blocked extensions, and mode defaults. Read it before writing any panel code; half the "it doesn't work" cases are a wrong disk or a too-tight MIME list there. Second, visit /admin/file-manager (database mode, full CRUD) and /admin/file-system (storage mode, read-only browsing) to see the two modes side by side.

First use case: point storage mode at an S3/MinIO bucket and use it as an ops-facing file browser before you ever touch database mode. It requires no schema, no policies, no metadata model — just ->disk('s3')->target('uploads') — so it's the fastest way to validate credentials, signing, and preview rendering in your environment.

Implementation Patterns

Pick the mode deliberately. Storage mode reads the filesystem directly and is read-only; database mode tracks files as Eloquent rows (FileSystemItem) with metadata, thumbnails, and full CRUD. A useful day-to-day split: database mode for user-uploaded assets that need metadata, relationships, and policy checks; storage mode for admin/devops browsing of bucket contents you don't want to index.

Expose only what you need. The default plugin registers all four components (FileManager page, FileSystem page, FileSystemItemResource, and a SchemaExample demo page). Ship-with-demo-pages is a footgun in production:

FileManagerPlugin::make()
    ->only([
        \MWGuerra\FileManager\Filament\Pages\FileManager::class,
        \MWGuerra\FileManager\Filament\Pages\FileSystem::class,
    ])
    ->withoutSchemaExample();

Embed in forms rather than linking out. This is where the package earns its keep in real apps — a product edit form that lets the user manage its gallery:

FileManagerEmbed::make()
    ->height('400px')
    ->disk('s3')
    ->target("products/{$this->record->id}")
    ->defaultViewMode('grid')
    ->compact(),

Both FileManagerEmbed and FileSystemEmbed accept closures on every setter, so tenant- or user-scoped paths are natural:

FileSystemEmbed::make()
    ->disk(fn () => filament()->getTenant()->storage_disk)
    ->target(fn () => "tenants/{$tenant->id}/media")
    ->sidebarRootLabel(fn () => $tenant->name . ' Files')

Centralize configuration in the panel provider. The fluent API beats the config file for anything panel-specific, and precedence is fluent > config > defaults. Use the panel-level sidebar labels as defaults and override per page:

FileManagerPlugin::make()
    ->panelSidebarRootLabel('Root')
    ->fileManagerSidebarRootLabel('Assets')
    ->fileManagerNavigation(icon: 'heroicon-o-folder', group: 'Content', sort: 1)
    ->fileSystemNavigation(icon: 'heroicon-o-server-stack', group: 'Content', sort: 2)

Authorize via policies, not config. Wrap the pages in your own canAccessPanel() / Gate checks on the panel and let Laravel Policies cover the FileSystemItem model. Since the package ships a FileSystemItemResource, model policies apply to it directly — that's cleaner than trying to gate through package config.

Treat FileSystemItemResource as the escape hatch. When you need bulk metadata editing, custom columns, or scoped queries over tracked files, subclass or reconfigure that resource rather than building your own CRUD over the same table.

Gotchas and Tips

  • Filament 5 is bleeding edge. The v2 line tracks Filament 5 / Livewire 4 / Laravel 12 — a narrow slice of the ecosystem right now. If you publish views for customization, remember Livewire 4 requires $wire.entangle('...') instead of @entangle('...'); stale published views are a silent-breakage source after the v1→v2 upgrade.
  • Signed URLs + non-local disks. Previews on S3/MinIO depend on signed URL generation. Temporarily-generated URLs expire — if thumbnails go blank after a few minutes on a long-lived page, check the URL TTL on the disk config, not the package.
  • MIME allowlist bites silently. Uploads that "just don't appear" are usually rejected by MIME validation or a blocked extension. Log or temporarily widen the allowlist in config/filemanager.php while diagnosing, then tighten it back — the security posture here (MIME checks, sanitization, blocked extensions) is a feature, so don't disable it permanently.
  • Filename sanitization changes names. If downstream code expects the exact uploaded filename, capture the stored name from the returned FileSystemItem, not the request. Users will notice accented characters and spaces being rewritten.
  • Icons and the heroicons dependency. The package ships fallback SVGs so it works without blade-icons/blade-heroicons, but if you're mixing icon sets, override explicitly with ->icons([...]) or ->icon(FileManagerIcon::Folder, 'tabler-folder'). ->noIcons() is handy for a minimal compact embed.
  • Debugging order that actually works: (1) is the plugin registered on the panel, (2) is the config's disk correct and reachable (Storage::disk('s3')->files() from tinker), (3) does the user pass the policy, (4) is the file passing MIME/extension rules. Almost every issue lands in one of those four buckets.
  • Maturity caveat: 84 stars, zero dependents, README + changelog only. There's no large community corpus of answers to fall back on, so budget time to read the source under vendor/mwguerra/filemanager/src — it's small enough to skim, and the Schemas/Components and Filament/Pages directories answer most customization questions faster than searching.
  • Extension points to prefer: the fluent plugin API, the embed component setters, icon overrides, and Eloquent policies on FileSystemItem. Avoid forking published views unless you have to — that's the piece most likely to break on the next Filament minor.
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.
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator