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 Library Laravel Package

tapp/filament-library

Tapp Filament Library gives your Filament admin a centralized asset library for uploading, organizing, searching, and reusing files and images. Browse and select media directly from forms and resources through a clean, native interface, keeping content consistent across your Laravel app.

View on GitHub
Deep Wiki
Context7

Getting Started

The package is a Filament plugin that adds a shared media/file library (folders, uploads, picker field) to a panel. Treat it as infrastructure, not a resource you write yourself — most of your work is wiring an existing model to it.

  1. Install and publish.

    composer require tappnetwork/filament-library
    php artisan vendor:publish --tag="filament-library-migrations"
    php artisan vendor:publish --tag="filament-library-config"
    php artisan migrate
    

    Publish config even if you change nothing — you will almost certainly need to change the storage disk.

  2. Register the plugin in your PanelProvider, alongside Filament's own plugins:

    ->plugins([
        FilamentLibraryPlugin::make(),
    ])
    
  3. Look first at: the published config file (disk, folder settings, model bindings), then the plugin's Media/library model and its resource. Those two files answer 90% of "where do I change X" questions. Read the plugin source under vendor/tappnetwork/filament-library/src before filing an issue — it is small and readable.

  4. First use case: give an existing resource a file attachment. Add the relation/migration, include the library's picker field in the resource form, and render the stored file in the table. Once that loop works you understand the whole package: upload into the library → reference the media record from your model → resolve a URL for display.

Start the smoke test on a non-production panel — the library writes to a real disk and creates real rows.

Implementation Patterns

Attach the library to a domain model. The common shape is a polymorphic relation so one model can own many library assets, plus an accessor for the "primary" file. Keep the relation name consistent across models; you will reference it in forms, tables, and URL resolution.

Pick files in forms, don't re-implement uploads. Embed the library's picker field in your resource form and let the plugin handle upload UX, folder navigation, and validation. This is the single biggest win — resist building a second FileUpload beside it.

Store the reference, not the path. Persist the media/library ID (or the pivot) and resolve URLs at render time via the media model's url()/getUrl(). Storing absolute URLs breaks the moment you switch disk, add a CDN, or move to S3.

Scope per panel/tenant. If you run multiple panels, register the plugin only where the library belongs. For multi-tenant apps, add a tenant key to the media table and a global scope — the library page and picker must not leak files across tenants.

Customise resources by extension, not by editing vendor. Subclass the plugin's resource/page classes (or bind your own via config) when you need extra columns, filters, or a custom table. This keeps upgrades cheap.

Version discipline around Filament minors. v1.4.1 is a compatibility fix for Filament 5.7.8 — a column searchable() callback on the User column was being misread by Filament as isSearchable. That tells you the package tracks Filament internals closely. Pin the plugin to a patch range, and after any Filament minor bump run a quick smoke test on the library table (especially search and relationship columns) before shipping.

Test the boundary. Feature-test your own resource (form saves the media ID, table renders the URL). Livewire-test the library table's search/filter only if you have customised it — that's the surface most sensitive to Filament upgrades.

Gotchas and Tips

  • searchable() on computed/relationship columns. Filament's searchable() signature puts the boolean $condition first; a closure passed positionally is treated as "is this column searchable" rather than "how to search". Always pass custom search logic as the named argument:

    TextColumn::make('user.name')
        ->searchable(query: fn (Builder $query, string $search) => $query
            ->whereHas('user', fn ($q) => $q->where('name', 'like', "%{$search}%"))),
    

    This is exactly what v1.4.1 fixed upstream. If you maintain overrides of the library's table, apply the same pattern or your customisation will silently break on Filament 5.7.8+.

  • Storage disk surprises. Default is usually public; on S3/private disks url() may return a temporary signed URL — fine for display, useless if you cache rendered HTML. Check config/filesystems.php and remember php artisan storage:link for the public disk.

  • Migrations after upgrade. New package versions can add migrations. vendor:publish with --force will overwrite your edits; publish by tag and diff instead. Keep your own migrations for the tenant/owner columns you added.

  • Orphaned files. Deleting a model does not necessarily delete the underlying file. Add a deleting hook or a scheduled prune, and be deliberate about whether library media is shared (referenced by several models) before cascading deletes.

  • N+1 on the library table. Relationship columns (user.name, folder name) need ->modifyQueryUsing(fn ($q) => $q->with(...)) or $with on the resource. Noticeable once the library passes a few hundred rows.

  • Authorization. The plugin exposes its pages via standard Filament policies/Gates. If you gate the library page but forget the picker field, users can still attach files they shouldn't browse. Audit both entry points.

  • Extension points worth knowing: config-based model/resource bindings (swap the media model for your own subclass), the plugin's page classes for menu/label overrides, and macros/configureUsing on the picker field to set defaults (accept types, max size, default folder) globally rather than per-form.

  • Debugging tip. When something renders blank in the library table, check storage/logs/laravel.log for a Column/searchable type error first — most failures here are Filament API mismatches from a version skew, not your data.

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.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package