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

zielu92/filament-image-labeler

Filament Image Labeler adds an interactive image labeling field to Filament forms, letting users draw or place labels directly on uploaded images. Label data is stored with your models for easy editing and display in resources.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and register

composer require zielu92/filament-image-labeler:^0.5
php artisan vendor:publish --tag="filament-image-labeler-config"   # if you need to tweak defaults
php artisan migrate                                               # only if the package ships its own tables

Register the plugin on your panel if the package exposes one (->plugin(FilamentImageLabelerPlugin::make()) in your PanelProvider), otherwise the field works standalone inside any form schema.

Look here first

  1. config/filament-image-labeler.php — storage disk, image sizes, annotation defaults.
  2. The field class itself (usually Zielu92\FilamentImageLabeler\Fields\ImageLabeler or similar) — the fluent API is the real documentation.
  3. resources/boost/ in the package vendor/source tree — v0.5.0 ships a guideline plus the filament-image-labeler-development skill, which is the most accurate description of the field API and syncAnnotations() contract available today.

Opt into Laravel Boost (new in 0.5.0)

php artisan boost:install      # tick filament-image-labeler in the package list
# or, on an existing Boost install:
php artisan boost:update --discover

After that your coding agent gets an always-on guideline plus the on-demand skill. This is the fastest way to get correct boilerplate for the field, so do it before writing your first form.

First use case — annotate an uploaded image and store the resulting labels/bounding boxes:

use Zielu92\FilamentImageLabeler\Fields\ImageLabeler;

ImageLabeler::make('image')
    ->label('Reference image')
    ->annotations('annotations')   // JSON column or relation
    ->syncAnnotations();

Then render the stored annotations back on the edit form and expose them read-only on the view/infolist.

Implementation Patterns

Form + persistence split

Treat the field as two concerns: the widget renders/edits annotations, syncAnnotations() writes them. Keep the field in the schema, and let the sync hook fire in the create/update lifecycle rather than calling it manually from your handleRecordUpdate — the contract is designed for that. If you need custom persistence (separate table, audit log, queued processing), disable the built-in sync and reuse the field's annotation payload in your own afterCreate/afterSave callback.

Relation-backed annotations

The most maintainable pattern for anything you'll query or report on:

  • Image model has annotations() (HasMany) or a JSON annotations column with an array cast.
  • Point the field at that attribute/relation.
  • Let syncAnnotations() reconcile create/update/delete on save, so re-editing an image doesn't duplicate rows.

Use a plain JSON column when annotations are purely presentational; switch to a relation as soon as you need filtering ("all images containing label X") or per-annotation metadata.

Entity links

Entity links let an annotation point at another model (a product, a defect code, a person). Pattern: seed the linkable options from a scoped query in the resource form, not from a global list, so the picker stays small. Persist the morph key/class through the field so links survive renames of the display label.

Automatic annotation

Use automatic annotation for pre-fill: run it on upload to get a first-pass set of boxes, then let the human correct them in the same field. Keep the auto-generated result flagged (e.g. a source column) so downstream consumers can distinguish machine from human labels, and never overwrite human edits on re-run.

Agent-assisted development (0.5.0)

With Boost installed, the skill covers the field API and the syncAnnotations() contract in context. Day-to-day this means:

  • Ask the agent for the field configuration instead of guessing fluent method names.
  • Have the agent read the skill when writing the persistence side, since the contract (what gets created/updated/deleted on save) is the part most likely to be got wrong.
  • Keep the skill in version control via boost.json so the whole team's agents use the same guidance.

Testing

Filament form fields are easiest to test through Livewire component tests (fillForm/call('save')) rather than unit-testing the field directly. Assert on the persisted rows after save, not on the field's internal state — that's the behaviour syncAnnotations() guarantees.

Gotchas and Tips

syncAnnotations() needs a persisted record. On create, the parent model must have an ID before annotations can be attached. Use the after-create hook, or call sync explicitly post-save(); calling it in beforeCreate/mutateFormDataBeforeCreate will fail or silently drop annotations.

Boost version floor. The shipped skill requires Boost 2.x. On Boost 1.x you still get nothing from boost:install — upgrade Boost first, then re-run boost:update --discover. Discovery is not automatic on package update: after bumping this package you must re-run discovery or the agent keeps the old (or no) guideline.

Coordinate normalisation. Annotation boxes are typically stored relative to the rendered image size. If you change the image width/height config or the displayed dimensions between capture and re-render, existing boxes drift. Store normalised coordinates (0–1 or percentages) and pick one convention project-wide; check what the field emits before writing your own renderer.

Disk and visibility. Uploaded images go to whatever disk the field configures. On non-public disks (S3 private, local storage/app/private), make sure your preview/URL generation uses temporary URLs — a mismatch here looks like "the annotator shows a blank canvas".

Array casts. A JSON annotations column needs protected $casts = ['annotations' => 'array'] (or AsArrayObject). Without it you get string payloads into the field on edit and the canvas renders empty even though the DB looks right.

Reordering/replacing the image. If a user swaps the image but keeps annotations, decide explicitly whether annotation sets are cleared, remapped, or preserved. Default to clearing — stale boxes on a new image are worse than redoing the work — and make it a visible confirm in the UI.

Extension points. Prefer the field's fluent configuration and the package config file over subclassing the field. Subclassing ties you to internal method signatures that the 0.x releases still move; if you must extend, isolate it in one custom field class so a future 0.6 bump is a single-file change.

0.x churn. The package is pre-1.0: pin the constraint (^0.5) and read the release notes for each minor. The 0.5.0 release itself is additive only (Boost resources, no API or config changes), so upgrading from 0.4.x is safe.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource