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

anselmokossa/filament-sentinel

Drop-in branded error pages for Filament 500, 403, 404, 419 and 503, built from native Filament UI so they inherit your panel's colours and dark mode. Real exception details, stable SAP-style message numbers, request ids and EN/PT/PT-BR translations.

View on GitHub
Deep Wiki
Context7

Getting Started

Sentinel is a thin, opinionated layer that swaps Laravel's default errors::* Blade views for Filament-styled ones. You are not installing a panel plugin, a theme, or a route package — you are installing five error views. That is worth internalising early, because it sets expectations for how much configuration you should expect to find and where to debug when something looks wrong.

Install and publish. Pull it in, then publish the views so you can actually see and edit them:

composer require anselmokossa/filament-sentinel
php artisan vendor:publish --provider="Anselmokossa\FilamentSentinel\FilamentSentinelServiceProvider"

The README excerpt does not pin the exact provider FQCN or publish tags, so run php artisan vendor:publish interactively first and note the tag names — you will want them again during upgrades.

Look first at three places, in this order:

  1. resources/views/errors/ — after publishing, the package's views should land here (or be resolvable from the vendor path). These five files are the whole product; read 500.blade.php before you trust it in production.
  2. config/sentinel.php (or whatever the published config is named) — check for toggles around the exception-detail panel before you go live.
  3. The service provider in vendor/anselmokossa/filament-sentinel/src/ — confirm whether it registers views globally or only within panel contexts. This single detail determines whether your non-Filament routes (API fallbacks, marketing pages) also pick up the branded pages.

First use case. A Filament panel that is customer-facing or demoed to stakeholders: the stock Laravel 404/500 screens look like a different product than the admin you just built. Set APP_DEBUG=false locally, hit a nonexistent route, and confirm the branded 404 renders with your panel's logo and colours. That is the ten-minute win. Everything past that is customisation.

Prerequisites are strict: PHP 8.2+, Laravel 12, Filament v5. If you are on Filament v3 or v4, this package is not for you yet — do not try to force it.

Implementation Patterns

Treat the published views as your application code. The package's value is the composition (<x-filament::button>, badge, section, icon on a light/dark-aware scaffold), not the package's ability to stay updated. Publish, commit the views, and customise copy, support links, and your logo directly. This also insulates you from vendor churn in a package with nine stars and zero dependents.

Split the 500 from the rest. The 404/403/419 pages are cheap to ship unmodified — they are static-ish and low-risk. The 500 page is the one that deserves review, because it surfaces real exception data (class, file, message) behind a "View more" disclosure. Pattern:

{{-- only ever expose the diagnostic panel when it is genuinely safe --}}
@if (config('app.debug') || auth()->user()?->can('viewExceptionDetails'))
    {{-- View more panel --}}
@endif

Gate it on debug mode or an explicit permission, never on environment name alone, and never on a ?debug=1 query string.

Let the data drive the page. Sentinel's differentiator is that content comes from the exception: the requested path on 404, authorization detail on 403, Retry-After on 503. Lean into this rather than hardcoding generic copy. For 403, that means passing the ability and model through your Handler so the page can say what was denied:

// bootstrap/app.php — enrich the exception before render
->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (AccessDeniedHttpException $e, Request $request) {
        if ($request->expectsJson()) {
            return null; // let Laravel produce the JSON response
        }
    });
})

Respect the panel context in multi-panel apps. If you run /admin (dark, custom accent) alongside /app (light, different logo), a single global error view will brand every 500 as whichever panel it defaults to. Two practical options: keep one neutral branded page derived from Filament's base palette, or publish per-context views and switch the error view path per request in a middleware based on request()->segment(1).

Cover the maintenance case outside the error handler. The 503 page pairs with php artisan down; test it explicitly:

php artisan down --retry=60     # 503 with Retry-After
php artisan up

Confirm the page renders and the Retry-After value reaches the output — that is the one page where the header is part of the content contract.

Test error pages like features. They are the pages you least often look at and most often see. A Pest test hitting a missing route with APP_DEBUG=false and asserting the expected branding string is worth more than manual clicking:

it('renders the branded 404', function () {
    $this->get('/definitely-missing')->assertNotFound()->assertSee('Back to dashboard');
});

i18n: publish and translate the lang files. The package advertises i18n; the diagnostic copy (headings, retry hints) lives in translations. If your app ships non-English locales, publish the lang files and add your locales rather than hardcoding English into the Blade views — otherwise locale switching will look inconsistent between your panel and your error pages.

JSON requests must stay JSON. Sentinel only governs HTML responses. Confirm your Accept: application/json clients still get Laravel's JSON error shape and never a rendered Blade page — an HTML error page returned to a fetch client is a silent debugging nightmare.

Gotchas and Tips

APP_DEBUG=true makes all of this invisible. This is the single most common "it's not working" report. With debug on, Laravel (and Ignition) intercepts 500s before your view renders, and the 404 page still shows the debug trace. Verify in a staging environment with debug off, or set APP_DEBUG=false locally and clear config: php artisan optimize:clear.

The "View more" panel is your biggest liability. You are shipping exception class names, file paths, and messages to end users. Audit that disclosure against your threat model before production, not after. File paths leak directory structure and usernames; messages can leak query fragments or secrets in connection errors. Decide deliberately: permission-gated, debug-gated, or replaced with a correlation ID plus a link to your log viewer.

View caching will hide your edits. After publishing or editing any file under resources/views/errors, run php artisan view:clear. If you use php artisan optimize, remember that config caching can freeze your Sentinel toggles until you re-run php artisan config:clear.

Watch for collisions with other error-page packages. Anything else that registers errors::404 (custom handler packages, Horizon/Telescope overrides, Laravel's own vendor views) can win depending on registration order. If you see the stock Laravel page despite a successful install, check for competing view registrations — php artisan view:cache followed by a grep for errors.404 in bootstrap/cache is a fast way to see who registered what.

Filament v5 is bleeding edge. The README advertises v5, Laravel 12, PHP 8.2+ with 26 passing tests — encouraging, but this is a very new target with a tiny adoption base (9 stars, 0 dependents). Pin the version in composer.json, read the CHANGELOG before bumping, and be prepared for the Filament component API to shift under you. If you cannot tolerate that, copy the views into your app and drop the dependency; you lose update notifications but gain stability.

Do not expect a diagnostic dashboard. Sentinel renders five error pages. It does not capture exceptions, add request IDs, wire up Sentry, or provide a log viewer. Pair it with a real reporter (Sentry, Flare, Bugsnag) — the branded page is the last metre of a pipeline you still have to build.

Non-Filament routes may or may not be covered. Determine this early. If the package registers globally, your public marketing site inherits admin-panel styling, which is usually wrong. If it registers only per-panel, your API 404s and webhook failures get Laravel defaults — also usually fine, but know which you have.

Check 419 separately. CSRF expiry is the error users hit most often and the one developers never test. Open a form, clear cookies, submit, confirm the branded 419 appears with a sensible recovery path back to the login or form page rather than a dead end.

Extension points are limited by design. There is no plugin system here — the extension point is the Blade file. If you want a support-email link, a status-page link, or a request ID, edit the view. Do not fight the package with middleware rewriting responses; it will be more code than the one-line edit you actually needed.

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.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels