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

Theme Support Laravel Package

liberusoftware/theme-support

Theme support for Laravel applications: register, switch, and organize themes, resolve theme views and assets, and keep theme configuration centralized. A lightweight foundation for building multi-theme PHP apps.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and confirm discovery. composer require liberusoftware/theme-support. Liberu modules ship as Laravel packages, so the service provider should be auto-discovered via extra.laravel.providers — after install, run php artisan about (or php artisan package:discover) and confirm the provider is listed. If it is a submodule of a Liberu app rather than a standalone package, it may already be pulled in by the module-theme-support metapackage; check composer show liberusoftware/theme-support for the actual installed version before reading source that may not match.

Publish and read the config first. php artisan vendor:publish --tag=theme-support-config (also try --tag=theme-support if the tag differs). This config is the single most important file in the package: it typically holds the theme search paths, the active/default theme key, the asset manifest or cache-busting settings, the preference store driver, and any panel→palette mappings. Everything else in the package is downstream of those values.

Where to look in the source, in this order:

  1. The service provider — it reveals the container bindings (ThemeManager, a resolver/finder interface, a preference repository) and the Blade directive registration. Bind these interfaces, not the concretes.
  2. The discovery class — look for the directory-scanning convention and any theme manifest (theme.json/composer.json block) that declares the theme name, parent theme, and view namespace.
  3. The directive registrar — one file usually maps every @theme* Blade directive to a class method. That's your de facto API reference if docs are thin.

First use case. Create themes/<name>/views/ with a single Blade file that shadows a view you already render, register the theme name in config (or via whatever Theme::activate()-style API the manager exposes), and load a page. Then delete the override file and confirm the original view returns. That two-minute round trip validates discovery, resolution order, and the view cache all at once — and it's the exact failure mode you'll debug most often later.

Implementation Patterns

Theme resolution as a middleware/request concern. The active theme is usually request-scoped state (per panel, per tenant, per user preference). Set it early — a middleware or a panel boot callback — and never mutate it mid-request after views have been resolved. If the package exposes a ThemeManager singleton, treat it as mutable global state and keep the "which theme is active" decision in one place.

View overrides via namespaces, not file copying. The healthy pattern is View::prependNamespace()/addLocation() so the theme's views/ directory wins the lookup chain while Laravel's normal resolution still handles fallbacks. Concretely: a theme with no layouts/app.blade.php should transparently fall back to the package's path — verify that, because a finder that replaces instead of prepends will break any partial you haven't overridden. Parent/child themes (if supported) should chain the same way.

Safe asset directives for anything user- or theme-authored. The "safe asset" angle matters when theme names or asset paths come from config or preference values rather than source code. Use the package's directive (something like @themeAsset('css/app.css')) instead of hand-building asset($theme . '/' . $path), and never interpolate a theme name into a URL with {!! !!}. The directive's job is to constrain the path to the theme root — that's the entire value proposition, so don't route around it. For versioned assets, prefer the manifest/mix/vite integration the package provides over appending ?v= manually.

Preferences with a clear precedence chain. Whatever backend the package uses (database, cache, config), define and document the resolution order explicitly — typically user → session → panel → config default. Resolve once per request and cache the result; a preference repository that hits the DB on every preference() call in a loop is a common performance trap. Write through a single service, not by touching the storage table directly, or cache invalidation will diverge.

Panel palettes as CSS custom properties. The palette feature is most useful when it emits CSS variables (--panel-primary, --panel-surface) scoped to a panel wrapper class rather than generating per-panel stylesheets. That gives you runtime theme switching for free: swap a class or data-palette attribute on <html>/<body> and let CSS do the rest. Keep palette definitions in config as data, and render them from a single Blade partial so dark mode and per-tenant palettes don't fork the layout.

Integration points worth wiring deliberately:

  • Filament/Livewire panels: bind a palette per panel in the panel provider rather than in the base layout.
  • Inertia/API: theme and palette are just props — resolve them server-side and share them via HandleInertiaRequests so the client doesn't reimplement resolution.
  • Tests: assert override behavior with $this->view() / assertViewIs() so a theme change that breaks a page fails CI, not production.

Gotchas and Tips

Treat this as alpha-grade until you've read the source. Zero stars, zero dependents, and a release date in the future (2026-10-27) all point to a package that has not been battle-tested in the wild. Pin an exact version in composer.json, and budget an hour to read the provider, finder, and directive files before designing around them. Do not assume the README matches the installed tag.

View cache is the #1 source of "my override isn't working." Laravel compiles views; adding or renaming a theme view file doesn't always invalidate the right entries. php artisan view:clear after adding overrides, and php artisan optimize:clear when changing theme config. If discovery results are cached separately by this package (common), there will be a dedicated theme:clear/theme:cache command or a config toggle — find it before you spend an hour on a stale-cache ghost.

Production cache vs. local dev. Directory-scanning discovery is slow and almost certainly cached in production. Make sure your deploy pipeline runs the cache-warm step after the theme directories are in place, and that a fresh theme added in prod actually gets picked up (some implementations only scan at boot with a long TTL).

Path safety is only as good as the directive. If any code path builds asset URLs or view paths from a preference or user-supplied theme name, verify the package normalizes and rejects .. and absolute paths. Test it explicitly — that's the one feature where a bug is a security issue, not a cosmetic one.

Namespace and directive collisions. @theme, @themeAsset, @palette are generic names. If you already have Blade directives or macros with similar names, registration order decides the winner and the failure is silent. Grep your app's directive registrations before enabling.

Extension points to prefer over forks. Look for interfaces (resolver, finder, preference repository) bound in the provider and rebind them in your own provider — that's the intended customization seam. Forking the package for a behavior tweak is a maintenance dead end given the release cadence.

Version compatibility. Confirm the Laravel and PHP constraints in the package's composer.json against your app before install; an unpinned, low-traffic package is exactly where an unstated ^10 vs ^11 mismatch bites.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource