Product Decisions This Supports
- Closing a visible gap on the unauthenticated surface. Filament already handles light/dark for logged-in screens; the login, register, password-reset, and email-verification pages are the one place a dark-mode user gets a full-brightness flash at the start of every session. If your Filament panel is customer-facing, this is a first-impression defect, not a preference nicety.
- Build vs. buy, decided cheaply. The alternative is hand-rolling a Blade component, wiring it into each auth view, and maintaining it across Filament majors. This package is one Composer line, one
@source CSS line, and two configuration methods. Unless you need per-user theme persistence or custom palettes, buying (at zero license cost) wins on effort alone.
- Roadmap slotting. This is a polish-sprint item, not a roadmap item. It should be triaged as a fast-follow to any auth-page redesign, SSO/MFA rollout, or brand refresh — the moments when the auth surface is already being touched and visual QA is already budgeted.
- Scoping decisions you can actually configure.
position(Alignment::…) settles the "where does it go" debate without a design cycle. enabledOn([...]) lets you decide per-route whether the switcher appears — useful for a split estate with a customer panel and an internal admin panel, where you may want it on one and not the other.
- Signals a theme investment. Adoption presupposes a custom Filament theme. That prerequisite is a forcing function: if the answer is "we don't have one," the honest product decision is usually "build the theme first, revisit the switcher after" — the theme has far more leverage on brand and consistency than this plugin does.
- Explicit non-goals to log now. No per-user server-side persistence, no custom palettes, no per-panel token overrides, no translations. Write these into the ticket before a stakeholder asks for them mid-sprint, because the package won't grow into them cheaply.
When to Consider This Package
Consider it when all of these are true:
- You're on Filament 3, 4, or 5 and can pin the matching package major (1.x, 2.x, or 3.x respectively).
- You already have a custom Filament theme and a working Tailwind build — the
@source directive has somewhere to live.
- The auth pages are customer-facing, or your user base is large enough that dark-mode preference is a real segment rather than an edge case.
- You have a multi-panel install where route-fragment targeting like
admin.auth earns its keep.
- Your auth pages are reasonably close to Filament defaults, so positioning won't require iteration.
Look elsewhere — or say no — when:
- Filament is an internal back-office tool for a handful of staff. The payoff is cosmetic; defer it.
- You have no custom theme and no appetite to build one. The plugin will install cleanly and appear to do nothing — the classic silent-failure path.
- You need the preference to persist per user across devices and sessions. This is client-side only.
- You need translated labels, custom palettes, or full theme-token control.
- Your auth pages are heavily rewritten (bespoke Blade shells, MFA steps, SSO button stacks, embedded legal footers). Budget a visual QA pass at mobile and desktop on every auth screen, and expect z-index and overlap iteration.
- Your org's third-party review process costs more than the feature. A security intake on a 48-star, single-maintainer, Blade/CSS-only package will plausibly consume more calendar time than the integration itself. Decide that trade explicitly rather than discovering it at intake.
Two operational cautions to bake into adoption:
- Always set
enabledOn() explicitly; never rely on the defaults. The default route list has changed repeatedly upstream (auth.email removed in v1.0.2, the profile view removed in v2.0.1). An upstream default change is a silent production behavior change you didn't ask for.
- Verify the release cadence on Packagist before citing currency in any stakeholder doc — the supplied "last release" timestamp is future-dated relative to a normal read.
How to Pitch It (Stakeholders)
To executives: A one-line, MIT-licensed plugin that gives dark-mode users a proper light/dark/system toggle on our login and account-recovery pages — the last screen in the product where they still get a full-brightness flash. Cost is measured in hours, not sprints. It's a presentation-layer addition with no backend, no database, and no data exposure; if the maintainer ever walks away, the code is small enough to fork and patch in hours. It's a small, honest polish win on the surface every user sees first.
To engineering: Add LightSwitchPlugin::make() to the panel's plugins() array, add the vendor @source glob to the theme CSS, done. Configuration is two methods — position() and enabledOn(). Pin the package major to the Filament major (1.x→3, 2.x→4, 3.x→4 & 5) and add a re-pin check to the Filament upgrade runbook. Two things to validate before we call it shipped: the @source path resolves in our Vite/Tailwind setup, and there's no flash of the wrong theme on first paint over a throttled connection — the whole point is eliminating the flash, so a flash would undercut the reason for adopting it. Also confirm a pre-login theme choice doesn't visibly flip after sign-in.
What we are explicitly not buying: user-level theme persistence, custom palettes, localized labels, or theme control outside the auth pages. If those become requirements, that's a different, larger conversation — this package is the cheap 80% and should be scoped and staffed as such.