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

Filament Browser Laravel Package

tomatophp/filament-browser

A Filament plugin that adds a full file and folder browser with a built-in code and markdown editor, plus previews for images, video, audio, PDF, and Excel files. It supports creating, renaming, and deleting files, and is intended for super-admins only.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. A working Filament panel (v5 on Laravel 12/13 for the current line; the v3 branch if you are still on Filament v3). There are no required migrations and no data model — the install cost is configuration and policy, not code.

Install and register.

composer require tomatophp/filament-browser
php artisan filament-browser:install

Then register the plugin in app/Providers/Filament/AdminPanelProvider.php:

->plugin(
    \TomatoPHP\FilamentBrowser\FilamentBrowserPlugin::make()
        ->basePath(base_path())
        ->hiddenFolders([base_path('vendor'), base_path('node_modules')])
        ->hiddenFiles([base_path('.env')])
        ->allowPreview()
)

Where to look first.

  1. .env — set DEVELOPER_GATE_PASSWORD before you open the page. The fallback is literally password; treat an unset value as an open door on any reachable panel.
  2. config/filament-browser.php — publish it with php artisan vendor:publish --tag="filament-browser-config" so defaults are reviewed in code rather than implicit.
  3. The page itself, under the panel's Settings group.

First use case. Point basePath() at a narrow directory and use the browser as a read-only inspector for one afternoon: read storage/logs/laravel.log, confirm what is in storage/app/public, open a customer's uploaded PDF/Excel to see what they actually sent. That single loop — "I need to see a file on the server without SSH" — is the whole value proposition, and it is worth validating before you enable a single write flag.

Implementation Patterns

Split configuration by environment, not by feature flag. The most common mistake is one plugin config for all environments. Register it conditionally so production is read-only-by-construction:

->plugin(
    \TomatoPHP\FilamentBrowser\FilamentBrowserPlugin::make()
        ->basePath(base_path())
        ->allowPreview()
        ->allowCode()
        // writes only outside production
        ->allowEditFile(! app()->isProduction())
        ->allowCreateNewFile(! app()->isProduction())
        ->allowCreateFolder(! app()->isProduction())
        ->allowRenameFile(! app()->isProduction())
        ->allowDeleteFile(! app()->isProduction())
        ->authorize(fn ($user) => $user->hasRole('super-admin')
            && (app()->isProduction() ? false : true))
)

Use authorize() as the real control plane. The gate password is a shared secret in .env; it is not identity. The authorize() callback is re-evaluated on every Livewire request in v5, which makes it the right place for "SSO group + environment + time window + ticket reference" logic:

->authorize(fn ($user) =>
    $user->email_verified_at !== null
    && $user->hasRole('super-admin')
    && in_array($user->email, config('ops.browser_allowlist'))
)

Keep the password too — defence in depth, not the primary control.

Scope the root to the use case, not to the app. basePath(base_path()) gives the whole tree. For media triage, basePath(storage_path('app/public')) is enough and eliminates every accidental .env/app/ edit. If you genuinely need multi-root access, that is a signal to add a dedicated ops panel rather than to widen the main one.

Daily workflows that pay for the install:

  • Upload triage — a customer says "the invoice won't open"; open storage/app/public/invoices/..., preview it, done. No SSH, no download-then-open.
  • Content edits — Markdown support means non-developers on the team can fix a policy or help page in resources/content/ without a deploy. Keep that directory's ownership clear.
  • Staging hotfixes — edit a Blade view or a config value in staging to prove a fix, then port it to the repo. Treat the browser edit as a diagnostic, and immediately mirror it into a commit.
  • Log archaeology — scroll storage/logs/, open the relevant day, grep with the code editor's find. Faster than tail -f for a single incident when you are already in the admin panel.
  • Orphan detection — walk storage/app/public and spot files with no DB row.

Pair every edit with the artisan step the browser cannot run. Editing config/*.php or .env does nothing while bootstrap/cache/config.php exists. The moment you save the file, run php artisan config:clear (or optimize:clear) in your terminal. Same for routes and views. Bake this into your own habit or a documented runbook — the browser will not do it for you.

Harden the deny list deliberately. hiddenFolders, hiddenFiles, and hiddenExtensions are deny lists, so they only help if you enumerate the dangerous things: vendor/, node_modules/, .git/, storage/framework/views/ (compiled Blade — editing it is always wrong), plus .env, *.pem, *.key, auth.json. Test that hiding works with the casing you actually have on disk.

Branding and trimming via published views. If you want the page to feel like part of your ops tooling rather than a third-party panel, publish --tag="filament-browser-views" and change headings/wrappers only. Do not fork the page logic — that is where upgrade drift starts.

Gotchas and Tips

The default password is password. If DEVELOPER_GATE_PASSWORD is unset in .env and config:cache has run, you get the fallback. Set it in .env and verify it after every config:cache.

v5 confines every operation with realpath checks. .., absolute paths, null bytes, and symlinks that escape the root are rejected — including public/storage if you narrow basePath to, say, public/. Expect "file not found" instead of a traversal attempt, and don't file it as a bug: it is the hardening working. If a legitimate path is a symlink out of the root, move the real directory instead.

hiddenExtensions(["php"]) hides .blade.php too. The README example hides PHP — which also removes your ability to edit Blade templates and config files. That is usually the right default for a read-focused install; just don't turn it on and then wonder why the editor is empty on resources/views/*.blade.php. Also verify case-sensitivity (.PHP, .Blade.php) on your filesystem.

.env is hidden by default in v5. hideEnvFiles(false) is an explicit security exception — require a reason and a reviewer, not a convenience toggle.

Nothing you edit takes effect until the caches are cleared. PHP edits additionally need an opcache reset (systemctl reload php8.x-fpm or opcache_reset()); the browser cannot do this. Editing cached config or compiled views produces the classic "I changed it and nothing happened."

The web server user must own the files you write. www-data needs write permission on the configured root. Root-owned files produce silent save failures. On SELinux hosts, check contexts too.

Large previews stream through the request. v5 embeds previews instead of copying to public storage, so a 200 MB video preview is a Livewire request. Bump upload_max_filesize/post_max_size/max_execution_time in php.ini (not just php artisan serve's defaults) or previews of big files will fail with an opaque error.

There is no undo, no recycle bin, and no audit trail. Before enabling delete, make sure the root is covered by backups and — if it is in the repo — that git status is clean enough to recover from. The cheapest habit: cp file file.bak before a risky edit, and check git status after every session.

Never edit vendor/, node_modules/, .git/, or storage/framework/views/. Composer/npm/Blade will overwrite them and you will have produced a change that vanishes on the next deploy. Hide them.

v5 removed the legacy JSON route, controller, and JS bundle, and swapped creagia/filament-code-field for Filament's built-in CodeEditor. If you upgraded from v2, grep for the old route in your code, and re-check any published view overrides that referenced the removed JS.

The gate is checked on every Livewire request, so it lives in the session. Rotating APP_KEY or switching session driver mid-session kicks users back to the gate — expected, but surprising during an incident.

Register per panel. The plugin must be added to each PanelProvider you want it in; the gate password, however, is global. A dedicated ops panel with a stricter authorize() is the clean way to separate "day-to-day super-admins" from "people allowed to touch the filesystem."

Pin the version. 43 stars, 0 dependents, one maintainer. Put an exact constraint in composer.json, subscribe to releases, and know your exit path (fork or replace with remote-SSH) before you depend on it in a shared environment.

Debugging checklist when the page misbehaves: php artisan route:list | grep -i browser (is it registered?), storage/logs/laravel.log (permission or realpath rejection?), confirm basePath() resolves to what you think (realpath(base_path())), and confirm the gate password matches after a config:clear.

Do not use it as a user-facing upload manager. Filament's FileUpload with a disk and policy is the right tool for customer content. The browser is an operator console; mixing the two puts a privileged filesystem surface behind a feature that non-admins use.

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.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
adachsoft/php-code-style