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

Tomato Browser Module Laravel Package

tomatophp/tomato-browser-module

A Tomato PHP admin module that adds a browser for exploring and managing files and media inside your Laravel application, integrating with the Tomato admin panel to give developers a simple built-in file browsing interface.

View on GitHub
Deep Wiki
Context7

Getting Started

tomatophp/tomato-browser-module v1.0.0 is the first tagged release, so treat it as a greenfield integration rather than an upgrade — there is no migration path to worry about, but also no battle-tested upgrade history to lean on.

composer require tomatophp/tomato-browser-module
php artisan vendor:publish --tag=tomato-browser-module-config
php artisan vendor:publish --tag=tomato-browser-module-assets
php artisan storage:link

Where to look first, in this order:

  1. config/tomato-browser.php — the published config is the real API surface. Note the disk name, root path, allowed extensions/mimes, and any middleware/permission keys before writing a single line of code.
  2. src/TomatoBrowserModule.php (or the package's Filament plugin class) — confirms whether this is a Filament plugin, a plain service provider, or both, and which Filament major version it targets.
  3. The package service provider — shows what gets registered (routes, gates, Livewire components, Blade views) and where the extension points actually are.
  4. README.md — for a v1.0.0 the README is the spec; the changelog link carries no migration detail.

Register it on your panel:

public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(\TomatoPHP\TomatoBrowserModule\TomatoBrowserModulePlugin::make());
}

First use case: point it at storage/app/public on the public disk, open the panel, upload a file, confirm it previews and downloads. That single loop exercises the disk resolution, the mime whitelist, the asset pipeline, and the authorization gate all at once — if any of those four are misconfigured, this is where you'll see it.

Implementation Patterns

Scope the browser per panel, not per app. If you run an admin panel and a tenant panel, register the plugin on each with a different root via the config or a ->root() / ->disk() fluent call if exposed. Sharing one global root between panels is the fastest route to cross-tenant file leakage.

Per-user directory isolation via closure. Rather than a static root, resolve the root dynamically so each user only ever sees their own subtree:

// config/tomato-browser.php
'root' => fn () => 'users/' . auth()->id(),

Anything that resolves paths at request time (not at config-cache time) is your friend here; anything baked into a cached config array is not.

Use it as a picker, not just a manager. The highest-value day-to-day pattern is embedding the browser as a file-selection field on an existing Filament resource — a FilePicker form component or a modal action that returns a path string you store on the model. That turns the module from "a file manager I visit" into "the file layer of every resource I build."

Pair with your own model layer. Keep a Media/Attachment Eloquent model that records path, disk, mime, size, and owner, and write to it from a browser event or a small action. Files on disk with no database row become unmanageable within a month; the reverse (rows with no cleanup on delete) leaves orphans.

Authorization belongs in a gate, not in the UI. Define a browse-files / manage-files gate in a service provider and reference it from the config. Hiding toolbar buttons is presentation; the gate is the control. Do this before the first deploy, not after.

Deployment. Add the asset-publish and filament:assets steps to your deploy script alongside storage:link. These are the two steps most often forgotten on a fresh environment, and both fail silently-ish (broken styling, 404s on download).

Testing. Storage::fake('public') plus a Livewire/HTTP test against the browser route is enough to cover upload, delete, and the traversal guard. Worth writing early, because the traversal guard is the one thing you genuinely cannot afford to regress on a v1.0.0 with no security history.

Gotchas and Tips

  • Config cache. The published config is read at boot. After editing roots or disks, php artisan config:clear — otherwise you'll debug a phantom for twenty minutes.
  • Path traversal is your problem too. The module should reject .. and absolute paths, but verify it yourself with a Storage::fake test before trusting it in production. Never set the root to local disk's base or to your app root.
  • Symlinks. storage:link is mandatory for the public disk to serve files. On Windows/Homestead, symlink creation can fail silently under some permission setups.
  • Upload limits are PHP, not Laravel. upload_max_filesize and post_max_size in php.ini will bite you before any package config does. Livewire's temporary upload disk is a separate setting again — check livewire.temporary_file_upload.disk.
  • S3-compatible disks break the "file manager" mental model. chmod, in-place rename, and server-side zip are not available; rename becomes copy+delete, and large-directory listing gets slow and expensive. If you're on S3, expect to disable or hide several toolbar actions.
  • Large directories. A folder with 10k entries will either paginate (fine) or hang (not fine). If you expect big dirs, test one early and check whether the listing is paginated or eager.
  • Filament version drift. Confirm the supported Filament major in composer.json. Custom Blade views also need their paths added to your Tailwind content array, or your overrides will render unstyled in production builds.
  • Default-open permissions. Many admin modules ship permissive defaults for local development. Grep the config and service provider for Gate::before / authorize and confirm what happens in production.
  • Pin the version. "tomatophp/tomato-browser-module": "^1.0" — a v1.0.0 with no prior release history gives you no signal about how the maintainer handles breaking changes. Read the changelog before every minor bump for the first few releases.
  • Debugging levers: php artisan about for the resolved environment, the Laravel log for storage exceptions (they surface as generic 500s in the UI), and filament:optimize-clear when cached components or views go stale after an update.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle