leek/filament-dicebear
DiceBear avatar provider for Filament panels, supporting all 31 DiceBear styles with caching, per-model customization, and self-hosted instances. Just register the plugin and provider to give users without custom avatars a generated DiceBear avatar.
Architecture fit. This is a narrow, well-scoped adapter, not a framework. It plugs into two extension points Filament already exposes — AvatarProvider (a first-party contract) and the panel plugin registry — so it composes with the existing panel lifecycle rather than fighting it. Our exposure surface is a handful of classes: DiceBearPlugin, DiceBearProvider, the DiceBearStyle enum, and the HasDiceBearAvatar trait. That is a favorable shape: if we abandon the package, we reimplement one HasAvatar contract method and keep our styling configuration. Lock-in is low. The v2 renderer choice (native PHP vs. ->driver('http')) is the one genuinely architectural decision, because it determines whether avatar generation is a CPU cost inside our request cycle or a network dependency on a third party.
Integration feasibility. High. composer require, one line in the panel provider, and every model without a custom avatar inherits generated images. The HasDiceBearAvatar trait has a getCustomAvatarUrl() seam specifically for "check uploaded photo first, fall back to DiceBear," which is the exact pattern our existing user model needs — we do not have to migrate or backfill avatar data. Filament already caches avatars per-user in its own UI, so the blast radius on existing screens is small.
Technical risk. The dominant risk is adoption, not code: 6 stars, 0 dependents, single maintainer, no external production references. Secondary risks, in order:
dicebear/core + dicebear/styles. That implies either a bundled PHP port, a JS runtime bridge, or a Node subprocess. Each has very different container-image, cold-start, and latency implications. Do not accept the README at face value — read the dependency tree in composer.json before we commit.initials (CC0) or thumbs/identicon is safe; adventurer, micah, personas, and most of the character set are not, without an attribution surface. This is a product/legal decision, not a dev decision.public disk are served from our domain and can carry embedded scripts; format('png'|'webp') or a separate asset host mitigates this.id (fine), but seedUsing(fn ($record) => $record->email) is documented and attractive — under the HTTP driver that puts user emails in query strings to a third-party endpoint, and into cache path derivation.scale() semantics flipped, getters were removed, and a deprecation list is already published for removal in 3.0. This package moves.Key questions.
Stack fit. Assumes Filament v3–v5 and a Laravel app with a configured filesystem disk. Our stack is compatible on paper; the open variable is Filament major-version drift, since the package tracks three majors and the provider contract has changed across them. Pin both Filament and this package in composer.json and treat upgrades as paired events.
Migration path. There is no data migration. Existing uploaded avatars remain untouched behind getCustomAvatarUrl(); only users with no avatar gain a generated one. That makes rollout reversible by deleting one plugin registration. The real "migration" is the v1→v2 configuration surface — the package ships an UPGRADE.md and the v2 changelog lists scale() semantics, removed getters, and the radius/backgroundType deprecations. We are greenfield on it, so skip v1 entirely and start at v2 to avoid inheriting the deprecated keys the package will remove in 3.0.
Compatibility. Verify three things before writing code: the PHP version constraint against our runtime, whether native rendering pulls a non-PHP dependency into the container build, and whether Filament's defaultAvatarProvider() in our installed version accepts a class string versus a resolved instance. Also confirm behavior when a model implements HasAvatar but does not use the trait — the README does not state whether that falls back to Filament's default or errors.
Sequencing.
->driver('http') documented as the escape hatch.initials, allow per-model overrides only within the CC0/MIT set unless we add an attribution page.cachePath, and confirm the storage symlink or bucket policy.getCustomAvatarUrl() on the user model before enabling the provider globally.Maintenance. Low ongoing code burden, high attention burden. The repo's hygiene signals are genuinely good — SHA-pinned Actions, Pint CI, Dependabot with a cooldown, a security policy, tests on every release — which is a better predictor of maintenance than the star count. But 0 dependents and one maintainer means we are, functionally, the largest consumer of this package. Budget for the possibility that we pin a version and never upgrade again, and confirm that pinned version still works when Filament releases its next major.
Support. No commercial support, no SLA. Escalation path is a GitHub issue. Treat the codebase as readable-but-ours: someone on the team should be able to fork and patch the provider in an afternoon. That is realistic given the surface area.
Scaling. Two distinct costs:
disk() option pointed at S3 or a CDN-mounted volume, and treat the local public default as dev-only.Cache keys now hash options plus the DiceBear core/styles (or API) version, so upgrades never serve stale art — good — but there is no eviction story. Old style directories accumulate forever; we own a scheduled prune (deleteDirectory) keyed off the configured cachePath, and it must be an explicit ops task, not an afterthought.
Failure modes.
report() and falls back to the HTTP API URL, meaning a config typo silently reintroduces a network dependency and a third-party call we thought we had removed. Watch the exception channel after any config change.api.dicebear.com → rate limits and latency are outside our control; treat public API usage as acceptable for dev and unacceptable for production user-facing panels.radius(), backgroundType(), and unsuffixed style options. If we pin and forget, this is a non-event; if we chase latest, it is a config rewrite.Ramp-up. Half a day to a working panel, one to two days to a production-ready configuration including license review, cache host, pre-warm job, and prune task. The cost is not learning the package — the README is clear and the fluent API is self-documenting — it is the diligence on rendering runtime, style licensing, and cache topology. Recommend a 3-day spike with a written go/no-go against those three, and a fallback plan of calling the DiceBear HTTP API directly from a single getFilamentAvatarUrl() method if the package does not survive diligence.
How can I help you explore Laravel packages today?