devonab/filament-easy-footer
Filament EasyFooter adds a flexible, customizable footer to FilamentPHP admin panels (v3–v5). Seamlessly integrate a polished footer and configure enable/disable, position, custom sentence, GitHub/installed versions, load time, logo links, and custom themes via simple options.
Architecture fit
This is a pure presentation-layer Filament plugin: one Blade view plus a fluent configuration object registered in a panel provider (->plugins([EasyFooterPlugin::make()])). It carries no migrations, models, routes, middleware, jobs, or storage — it attaches to existing Filament render hooks (panels::footer, panels::sidebar.nav.end, panels::sidebar.footer). Architectural fit is high for a Filament admin panel and effectively zero outside one; it is not a general Laravel package.
Two fit considerations a TPM should surface early:
admin, ops, vendor) must register the plugin in every provider where the footer is wanted, and the fluent configuration is duplicated per provider unless you extract a shared config object. Decide up front whether that duplication is acceptable or whether you factor a small helper.Integration feasibility
Effort is small but not zero. The README's happy path is: composer require, publish config (filament-easy-footer-config), one line in the panel provider. The non-obvious cost is the custom theme requirement: the footer's Tailwind classes only compile if you add @source '../../../../vendor/devonab/filament-easy-footer/resources/views/**/*'; to your theme CSS and rebuild. Teams without an existing custom Filament theme must create one first — that is a real project task (theme scaffolding, build pipeline, CI asset step), not a footnote. Realistic estimate: 0.5 day for a team that already owns a custom theme; 1.5–2 days otherwise, including QA across panels and the auth pages.
Technical risk Overall: low-to-moderate, and almost entirely cosmetic and lifecycle risk rather than security or data risk. Ranked:
@source line, or adding a new panel/theme that lacks it, produces a silently unstyled footer rather than an error. Also note @source is Tailwind 4 syntax; if the application's theme is still on Tailwind 3, the documented instruction will not work as written and content globs are required instead. Verify the app's Tailwind major before committing.admin/login, admin/forgot-password, and admin/register by default. Combining that default with withShowInstalledVersion() and withGithub() displays exact installed package versions and update status to unauthenticated visitors — a low-grade reconnaissance aid. This is a deliberate opt-out (hiddenFromPagesEnabled()), so it must be a conscious decision, not an inherited default.withGithub() calls the GitHub API on cache miss (cache_ttl default 3600). Unauthenticated calls are limited to ~60/hour per IP; a token raises that to ~5000/hour but introduces a credential in application config. The failure semantics are undocumented: does a rate-limit or timeout degrade to "no version shown" or throw inside the panel render?withSentence() accepts HtmlString with a documented allowlist (strong, img, a, em, span, b, i, small). Content is developer-supplied today, so severity is low — but if the sentence ever becomes config- or database-driven (a very plausible "let marketing edit the footer" request), this becomes an XSS path unless sanitisation is enforced in code rather than merely documented.hiddenFromPages() override semantics. The README states anything passed to hiddenFromPages() overrides the default list entirely. A maintainer adding two custom pages can silently re-enable the footer on the auth pages. Footgun worth a code comment.Key questions
withGithub() fail closed (footer renders without the version) or throw on HTTP error / rate limit?cache_ttl, and is it shared across app servers (Redis) or per-node (array/file)? At fleet scale a per-node cache multiplies GitHub calls.HtmlString content sanitised at render time, or is the allowlist documentation-only?withLoadTime() measure server-side render duration or client-side page load? This changes whether the number is user-facing truth or a misleading vanity metric.versioning.local_fallback_config_key set in every environment?Stack fit Composer-only; no npm package, no asset publishing step beyond the host theme build. Requires a Laravel + Filament v3/v4/v5 application with PHP 8.1+. It introduces no runtime services, no queue, no database surface. The only external dependency is the optional GitHub REST API for release-tag lookups.
Migration path
There is no data migration and nothing to backfill — the change is strictly additive to the panel render. Removal is equally clean: composer remove, delete the plugin line, delete the published config, remove the @source line, rebuild assets. Full reversibility in well under an hour is the single strongest argument for trying it, and worth stating explicitly in the decision record.
Compatibility
Version mapping is a hard constraint and must be pinned deliberately: Filament v3 → package v1.x (filament-v3 branch); Filament v4 and v5 → package v2.x (main, releases tagged v2.*). A Filament major upgrade therefore forces a parallel package major upgrade — treat the two as one change ticket. Verify Tailwind major (see @source above) before assuming the documented theme instruction applies. Multi-panel apps require per-provider registration; confirm behaviour is consistent across all panels rather than assuming global application.
Sequencing
app_name explicitly rather than relying on the APP_NAME fallback, so the footer is reproducible across environments.@source directive to the theme, rebuild, and confirm the compiled CSS is produced in CI (not just locally).hiddenFromPagesEnabled() with an explicit list covering the three auth pages.withGithub, withShowInstalledVersion, withLoadTime) one at a time, each with a rollback, so a failing feature is isolated.Maintenance
Ongoing code churn is minimal — the package surface is small and releases appear active (latest 2026-07-15). The genuine recurring cost is Filament major-version tracking, which is shared with the application anyway. Avoid publishing the views (filament-easy-footer-views) unless you must customise; a vendored view creates silent drift against upstream fixes. Pin to ^2.0 and fold the package into the existing quarterly dependency review rather than treating it as a set-and-forget.
Support GitHub issues with a single maintainer and no SLA. Acceptable for a footer; not acceptable as a load-bearing component. Because the footprint is one Blade view plus a config object, the mitigation is cheap and should be pre-agreed: if the package goes stale, fork or inline the partial. Decide the trigger (e.g. no release within 60 days of a Filament major) rather than deciding reactively.
Scaling
Effectively free at any realistic scale — it is markup rendering with no I/O by default. The only scaling-sensitive configuration is withGithub(): with a shared cache and a 3600s TTL, GitHub calls are ~1/hour per cache key, comfortably within limits. With a per-node cache store in a large autoscaling fleet, calls scale with instance count and can approach the unauthenticated 60/hour ceiling during rolling deploys. If GitHub version display is required in production, use a shared cache store and a read-only token scoped to Contents.
Failure modes
versioning.local_fallback_config_key).@source was omitted in a new theme or panel → unstyled but present footer, no error raised.hiddenFromPages() set explicitly without the auth pages → footer silently returns to login.sidebar / sidebar.footer positions with sticky elements or fixed-height nav.Ramp-up Under an hour for any Laravel developer who has seen a Filament plugin before; roughly half a day if you include the custom theme build and the QA matrix. No specialised knowledge required, which keeps the support burden low and makes the package easy to hand to a junior owner.
TPM recommendation
Approve conditionally: adopt only if a concrete requirement exists (legal/compliance links, internal version transparency for ops). If the requirement is merely "a copyright line," a ~15-line Blade partial in the panel render hook is cheaper than the dependency once theme work and version tracking are counted. If adopted, gate it behind the content policy in step 2, pin ^2.0, and pre-commit the fork contingency.
How can I help you explore Laravel packages today?