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

Light Switch Laravel Package

awcodes/light-switch

Filament plugin that adds light, dark, and system theme switching to panel auth pages. Configure the switcher's position with Alignment enums and control which routes display it via enabledOn(). Supports Filament 3, 4, and 5.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. This is a presentation-layer plugin with an unusually small architectural footprint: one registration line in Panel::plugins(), one @source directive in the theme CSS, and two configuration methods. It introduces no middleware, no migrations, no service-provider side effects beyond view registration, no queue workers, and no environment variables. For a TPM, that means integration risk is almost entirely front-end build risk rather than application-architecture risk — and front-end build risk is cheap to contain with a feature flag and a one-line revert.

The value proposition is narrow and honest: Filament panels already handle light/dark for authenticated screens, so this closes a gap on the unauthenticated surface — login, register, password reset, email verification. Judge it accordingly. If Filament is a back-office tool used by a handful of internal staff, the payoff is cosmetic and the answer is probably "no, or not now." If Filament Panels is the customer-facing application, the login page is a daily first impression and the payoff is real, if still small. The package does not attempt theme persistence per user, custom palettes, per-panel token overrides, or translations, and those should be logged as explicit non-goals in the ticket before anyone asks for them mid-sprint.

Integration feasibility. The public API surface is two methods, both documented and both stable across the observed release history: position(Alignment::…) and enabledOn([...]). Route targeting uses Str::contains() against route names, which is a pragmatic choice that enables panel-scoped fragments like admin.auth in multi-panel installs — genuinely useful in a multi-tenant or split admin/customer-panel estate, and worth exploiting rather than treating as an implementation detail.

The one real prerequisite is a custom Filament theme. The @source '../../../../vendor/awcodes/light-switch/resources/**/*.blade.php' line only works if the project already builds its own Tailwind CSS. Teams that have never created a custom theme will find the plugin installs cleanly and then appears to do nothing — this is the classic silent-failure path and the single most important gate to check before committing engineering time. It is also the item most likely to burn a sprint day invisibly, so it belongs in the acceptance criteria, not the "notes" section.

Technical risk. Four categories, in descending order of concern:

  1. Vendor concentration. Single maintainer (Adam Weston, a recognized name in the Filament ecosystem), 48 stars, zero known dependents, MIT license. The low dependent count reflects weak social proof, not code quality. The mitigating factor is decisive: the codebase is small and Blade/CSS-only — if it is abandoned, forking and patching is an hours-scale cost, not a weeks-scale one. A third-party security review process, if your org has one, will likely cost more in process overhead than the feature itself and should be factored into the go/no-go rather than discovered during intake.
  2. Filament version drift. The version matrix (1.x→Filament 3, 2.x→4, 3.x→4 & 5) shows the maintainer tracking three majors, including a combined 4-and-5 line. That is the strongest positive signal in the evidence set and materially lowers abandonment risk in the near term. It also means the next Filament major will almost certainly require a package major bump — plan for a pinning-and-upgrade task on every Filament upgrade, not just this one, and carry it in the upgrade runbook.
  3. Layout and z-index collisions. The v1.0.3 release lowered the switcher's z-index to 40 specifically to stop it overlapping Filament notifications. That class of defect recurs whenever auth layouts are customized (MFA steps, SSO buttons, bespoke Blade shells, embedded legal footers). If your auth pages are close to Filament defaults, risk is low; if they are heavily rewritten, budget for positioning iteration and an explicit visual QA pass on each auth screen at mobile and desktop breakpoints.
  4. Theme-state semantics. The v2.0.2 fix made the switcher read Filament's defaultThemeMode instead of hardcoding a default, which is correct behavior but signals the semantics have shifted under users. Related: the default route list has changed repeatedly (auth.email removed in v1.0.2, profile view removed in v2.0.1). Never rely on the default route list — always set enabledOn() explicitly, because a silent upstream default change is a silent production behavior change. Separately, because the preference is client-side only, verify empirically whether there is a flash of the wrong theme on first paint over a throttled connection; the entire pitch is "no bright flash for dark-mode users," so a flash would undercut the reason for adopting it.

Key questions for engineering before approval:

  • Do we have a custom Filament theme today, and does the @source path resolve correctly in our Vite/Tailwind setup?
  • Which Filament major are we on, and does the pinned package major match it exactly?
  • What is our defaultThemeMode in panel config, and does the switcher's initial state actually match it on first paint?
  • Is there a visible theme flash on first paint under network throttling, and does it differ between cold cache and warm cache?
  • Does the toggle survive our specific auth page customizations without overlapping notifications, MFA prompts, or form controls?
  • Does a user's pre-login theme preference carry into the authenticated panel, or do they see a flip after signing in?
  • Is English-only labeling acceptable for our locales, or do we need a translation pass we would own?
  • Data caveat: the "last release" timestamp reads 2026-10-06, which is future-dated relative to a normal read. Verify actual release cadence on Packagist before citing currency in any stakeholder document or architecture decision record.

Effort and decision frame. Size this as a half-day to one-day engineering task in the happy path (composer require, panel registration, @source line, one build, one visual QA pass per auth screen), plus whatever theme scaffolding costs if no custom theme exists — that can be the dominant term and should be estimated separately, because it is a permanent addition to the project's build surface, not a one-off. Recommend a spike-gated approval: timebox two hours to prove the @source path builds and the toggle renders on the login page, then commit. If the spike fails, the fallback is a handful of Blade + Tailwind in the auth layout, which is also hours-scale but carries no vendor dependency at all.

Integration Approach

Stack fit. Designed for Laravel + Filament Panels, distributed via Composer, rendering Blade views styled with Tailwind. It fits any project already on Filament 3, 4, or 5 with a custom theme compiled through Vite. It does not fit cleanly if: the project relies solely on Filament's stock CSS with no custom theme build; the team is on Filament 2.x or earlier (no compatible line exists); or the front-end is a separate SPA consuming Filament only as a JSON API, in which case the auth surface is not Filament-rendered and the plugin is inert.

Migration path. Effectively non-existent — that is the point. There is no data to migrate, no schema change, no persisted user preference to backfill (the setting is client-side), and no API contract to version. Rollback is: remove the plugins() entry, remove the @source line, rebuild assets, deploy. That reversibility is the single strongest argument for trying it: the cost of being wrong is one deploy cycle.

The one genuine migration consideration is theme provenance. If the project has no custom Filament theme, "installing this plugin" actually means "introducing a custom theme build pipeline." Treat that as a separate, larger decision with its own justification — it changes how CSS is authored, compiled, and cached forever, and every future Filament upgrade now includes a theme rebuild step. Do not let a cosmetic switcher smuggle in a build-system change.

Compatibility. Pin the package major to the Filament major explicitly and record the pairing in the upgrade runbook:

Filament Package Notes
3.x 1.x Legacy line; no longer the head of development
4.x 2.x or 3.x 3.x also covers 5.x — prefer 3.x to minimize future churn
5.x 3.x Current combined line

Two compatibility caveats to carry forward. First, the combined 4-and-5 line in 3.x means a single dependency constraint spans two Filament majors; verify the resolved constraint in composer.lock rather than trusting the README table, and re-verify after every composer update. Second, because the plugin ships raw Blade views consumed by your Tailwind build via @source, its CSS is compiled into your bundle — a bad vendor path or a Tailwind version mismatch surfaces as a build failure or missing utility classes, not as a runtime error. That failure mode is loud at build time (good) but silent if the @source line is omitted entirely (bad).

Sequencing. Five steps, ordered so the cheapest failure happens first:

  1. Precondition check (30 min). Confirm Filament major, confirm a custom theme exists and builds, confirm the @source path resolves from the theme CSS file's location. Stop here if any answer is no.
  2. Spike (≤2 hrs, timeboxed). composer require awcodes/light-switch, register the plugin, add @source, build, load the login page locally. Success criterion is a rendered switcher that actually flips the theme. If the box expires, abandon to the in-house fallback.
  3. Configure (≤1 hr). Set enabledOn() explicitly with the full route list — do not accept defaults — and set position(Alignment::…) to whatever survives the existing auth layout.
  4. Visual QA (per auth screen, mobile + desktop). Login, register, password reset, email verification, plus any MFA or SSO interstitial. Check overlap with notifications, form controls, and footers. Check first-paint flash on throttled network with cold and warm cache.
  5. Ship behind a flag. Merge to a single non-production panel first if the estate is multi-panel, gather feedback for one cycle, then roll to remaining panels.

Scope guardrails to write into the ticket. Explicitly out of scope: per-user server-side theme persistence, custom color palettes, translation/localization of labels, changes to the authenticated panel's theme behavior, and support for Filament < 3. State these up front — every one of them is a plausible mid-sprint request that would convert a one-day task into a multi-week one.

Operational Impact

Maintenance. Near-zero steady-state cost, with three scheduled touchpoints. (1) A pin-and-verify step on every Filament major upgrade — the version matrix guarantees a package bump will eventually be required. (2) A review of the resolved Composer constraint after any dependency update, since the 3.x line spans Filament 4 and 5. (3) A quick read of the changelog before each bump, because this package's defaults have historically changed between minor releases (auth.email dropped in v1.0.2, profile view dropped in v2.0.1). Explicit enabledOn() configuration neutralizes the third almost entirely — which is why it is a requirement, not a recommendation.

Ownership should sit with whoever owns the Filament front-end, not the platform team. The blast radius is a single Blade partial on unauthenticated pages; routing it through a platform review board would cost more than the change.

Support. First-line support burden is low but non-zero and predictable: "the toggle doesn't appear" (almost always a missing @source line or a stale asset build), "the toggle overlaps something" (z-index or alignment), and "my theme choice didn't stick" (client-side storage cleared, or a privacy mode blocking local storage). Document these three in the internal runbook; they cover the large majority of expected tickets. There is no vendor SLA and no paid support tier — escalation path is upstream GitHub issues, with forking as the guaranteed backstop. Because it is MIT and Blade-only, a fork is a realistic contingency rather than a theoretical one; note the fork owner in the runbook so the decision is not relitigated under pressure.

Scaling. The plugin scales trivially in the traffic sense — it is static markup and CSS with no server-side per-request work beyond view resolution, no database reads, no external calls, no caching layer to invalidate. Ten users or ten million, the marginal cost is indistinguishable from zero. The scaling concern that does exist is estate-wide: in a multi-panel installation, each panel's Panel provider needs its own registration and its own enabledOn() list, so N panels means N configuration points to keep consistent. Manage that with a shared config helper or a base panel builder rather than copy-paste, or the panels will drift and only some will show the switcher. There is also a small CDN/edge consideration: because the preference lives in browser storage, users on shared or rotating devices will see the system default rather than their own choice — acceptable for auth pages, but confirm it does not conflict with any accessibility or brand-standardization commitment.

Failure modes. Ranked by likelihood:

  • Silent no-op. Plugin installed, @source line omitted → assets build without the plugin's classes, widget renders unstyled or invisible. Highest-probability failure and the hardest to notice because nothing errors. Mitigation: the spike in step 2 and a rendering assertion in QA.
  • Stale asset cache. @source added but the Tailwind build not re-run, or the browser serving a cached bundle. Mitigation: cache-busting is Vite's default; confirm the deploy pipeline rebuilds on dependency changes.
  • Layout collision. Overlap with notifications, MFA prompts, or custom auth chrome. Mitigation: per-screen visual QA; adjust position() before reaching for CSS overrides.
  • First-paint theme flash. Client-side preference resolution over a slow connection can produce a flash of the wrong theme. This would defeat the stated purpose. Mitigation: measure under throttling; if present, evaluate an inline blocking script — and if that is required, the in-house fallback becomes relatively more attractive.
  • Upstream abandonment. No commits for an extended period. Low impact given fork feasibility; monitor passively via the Filament upgrade cycle rather than any dedicated process.
  • Upstream default drift. The maintainer changes defaults in a minor release. Mitigation: explicit enabledOn(), and read the changelog on every bump.

Every one of these is contained to unauthenticated pages and has a one-commit rollback. Nothing here can take down the authenticated application.

Ramp-up. Negligible. A developer unfamiliar with the package reads the README in five minutes and ships in under an hour, provided the custom theme exists. The real ramp-up cost is the custom theme prerequisite, and it is not the plugin's cost to bear — it is a pre-existing project capability that this change happens to surface. If the team lacks that capability, budget the theme scaffolding as its own justified line item, or take the in-house fallback (a small Blade component plus a few Tailwind classes in the auth layout) which requires no new dependency and no theme pipeline change at all.

Bottom line for the go/no-go. Approve as a low-cost, low-risk, fully reversible enhancement if a custom Filament theme already exists and Filament Panels serves a customer-facing auth surface. Defer if the theme prerequisite is unmet, since the plugin then becomes a pretext for a build-system change that deserves its own decision. The feature is cosmetic, the dependency is small and forkable, and the cost of being wrong is a single revert — but it should be sold to stakeholders as a small polish item, not an accessibility or UX-critical fix, because client-side theme preference is not a substitute for prefers-color-scheme support and does not by itself satisfy any accessibility conformance requirement.

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.
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc