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

outerweb/filament-image-library

Filament Image Library adds a reusable image library to your Filament panel, letting you upload, organize, and pick images from a central media pool in forms and tables. Browse, search, and reuse images instead of re-uploading them.

View on GitHub
Deep Wiki
Context7

Getting Started

The package gives Filament a shared image pool: instead of every resource re-uploading a hero image, authors pick from a library that is managed once and reused across resources.

Minimal install:

composer require outerweb/filament-image-library
php artisan vendor:publish --tag="filament-image-library-migrations"
php artisan vendor:publish --tag="filament-image-library-config"
php artisan migrate
php artisan storage:link

Register the plugin on the panel you actually want the library page on:

// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        ->plugin(\Outerweb\FilamentImageLibraryPlugin::make())
        // ...
}

Where to look first, in this order:

  1. config/filament-image-library.php — disk, directory, and any model/view overrides. This is the file you will touch most.
  2. The published migration and the package's Image model (src/Models/) — decide early whether you will reference images by ID (relationship) or by path (string column), because it drives every migration you write afterwards.
  3. The picker field class in src/ — copy its namespace/name from the README rather than guessing; the API surface is small and stable, but the exact class name is the one thing people get wrong on day one.

First use case to validate the install end to end: a Post resource with a single "cover image" field. Upload two images through the library page in the panel, then edit a post and confirm the modal picker lists them, that selecting one persists, and that the image renders on the front end via Storage::disk(config('filament-image-library.disk'))->url($post->cover).

Implementation Patterns

Single image on a resource. Add the picker to the form schema next to your other fields, store the returned value in a dedicated column, and expose a URL accessor on the model so views never touch storage internals:

protected function coverUrl(): Attribute
{
    return Attribute::get(fn () => $this->cover
        ? Storage::disk(config('filament-image-library.disk'))->url($this->cover)
        : null);
}

Multiple images. For galleries, either a multiple() variant of the field backed by a JSON column, or a proper pivot/hasMany if images need ordering, captions, or per-usage alt text. Choose the pivot as soon as you need anything beyond "which images are attached" — JSON columns are a one-way door for ordering and translations.

Repeatable contexts. In Repeater and Builder blocks the picker works like any other field, but make sure the stored value is relative to the configured disk. Absolute URLs written into block data break the day you move to S3 or add a CDN.

Table previews. Pair it with Filament's ImageColumn pointed at the same disk/directory config, not at a hard-coded storage/ path. Keep disk and directory in config and read them in one place (a small ImageUrl helper or model accessor) so a disk change is one edit.

Managing the library itself. Treat the library page as an admin-only surface: gate it with a policy or canAccess() on the page and hide it from the navigation for roles that only consume images. Editors picking images and editors deleting images are usually different people.

Bridging existing uploads. If you already have FileUpload fields producing paths, a one-off command that walks those paths and inserts missing library records lets you migrate incrementally. Don't rewrite existing columns in the same release; add the library field, backfill, then deprecate the old one.

Seeding and tests. Use Storage::fake() in tests and create library records through the package model in factories rather than hitting the upload endpoint. Assert on the stored identifier, not the rendered URL.

Gotchas and Tips

  • Publish before you migrate. Running migrate before vendor:publish --tag=...-migrations silently gives you no table and a confusing "relation does not exist" on the library page.
  • storage:link is not optional with the default public disk, and APP_URL leaking into generated URLs is the usual cause of "images work in the panel, broken in email/API".
  • Deleting a library image is a destructive, cross-resource action. Check the migration's foreign-key behaviour; if it cascades, a delete can silently blank hero images across hundreds of records. Prefer nullOnDelete or a "detach/archive" flow, and add a withCount on the library table so admins see usage before deleting.
  • N+1 on listing pages. If your table column resolves a related image record, eager load it in getTableQuery(); the picker's convenience makes it easy to attach images to a dozen resources and then wonder why the index page got slow.
  • Pin the version. This is a single-maintainer package with essentially no downstream dependents — treat it as a moving target. "outerweb/filament-image-library": "0.x.*" plus a review of the changelog on upgrade is cheap insurance, and the codebase is small enough to read in an afternoon.
  • Check Filament major compatibility explicitly. Filament's v3 → v4 form/table APIs changed; verify the constraint in composer.json rather than assuming, and don't mix this plugin with a panel on a different major.
  • Config cache. After editing the config, run php artisan config:clear locally and remember config:cache in deploy — published config that isn't cached is a classic "works on my machine".
  • Extension points worth knowing: the config-level model and disk overrides let you swap in a model with your own scopes/alt-text columns without forking, and the picker's view is publishable if you need a different modal layout. Prefer a published view or a thin subclass over editing vendor/.
  • Missing pieces you will likely add yourself: alt text and focal point/cropping are not the package's job. If accessibility or art direction matters, plan for a wrapper model or a companion field now rather than retrofitting later.
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