Installation:
composer require mrdejong/themer
Add to config/app.php under providers:
'providers' => [
// ...
Themer\ThemerServiceProvider::class,
],
Publish Config:
php artisan vendor:publish --provider="Themer\ThemerServiceProvider"
Locate config at config/themer.php.
First Use Case:
Define a theme in config/themer.php:
'themes' => [
'default' => [
'name' => 'Default Theme',
'path' => base_path('resources/themes/default'),
],
'dark' => [
'name' => 'Dark Theme',
'path' => base_path('resources/themes/dark'),
],
],
Load a theme in a controller/middleware:
use Themer\Facades\Themer;
Themer::setTheme('dark');
Theme Switching:
public function handle($request, Closure $next) {
Themer::setTheme('dark');
return $next($request);
}
session or user model):
Themer::setTheme(auth()->user()->preferred_theme ?? 'default');
Asset Overrides:
resources/themes/{theme}/
├── css/
│ └── app.css
├── js/
│ └── app.js
@themer_css('app')
@themer_js('app')
View Overrides:
resources/views structure:
resources/themes/{theme}/
├── layouts/
│ └── app.blade.php
├── partials/
│ └── header.blade.php
@include with theme-aware paths:
@include('themer::layouts.app')
Fallback Logic:
config/themer.php:
'fallback' => ['default', 'light'],
Blade Directives:
Register custom directives in AppServiceProvider for theme-specific logic:
Blade::directive('themer_meta', function ($expression) {
return "<?php echo Themer::metaTag($expression); ?>";
});
Usage:
@themer_meta('theme-color', '#333')
Dynamic Theme Detection:
Detect user preferences (e.g., browser prefers-color-scheme) and set theme:
$theme = request()->header('prefers-color-scheme') === 'dark' ? 'dark' : 'default';
Themer::setTheme($theme);
Theme-Aware Assets: Use Laravel Mix/Vite to compile theme-specific assets:
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
input: {
dark: path.resolve(__dirname, 'resources/themes/dark/js/app.js'),
default: path.resolve(__dirname, 'resources/themes/default/js/app.js'),
},
},
},
});
Caching Issues:
php artisan view:clear
php artisan cache:clear
config/themer.php cache setting is false during development:
'cache' => env('THEMER_CACHE', false),
File Structure Sensitivity:
resources/views. Misplaced files (e.g., resources/themes/default/views/layouts/app.blade.php instead of resources/themes/default/layouts/app.blade.php) will fail silently.Middleware Order:
ShareErrorsFromSession to avoid flash messages breaking theme logic.Asset Paths:
<link href="/css/app.css">) will break. Always use:
@themer_css('app')
Enable Debug Mode:
Set 'debug' => true in config/themer.php to log missing files/fallbacks to Laravel logs.
Check Loaded Theme: Add a temporary Blade directive to debug:
Blade::directive('debugTheme', function () {
return "<?php echo 'Current theme: ' . Themer::getTheme(); ?>";
});
Usage:
@debugTheme
Custom Theme Resolvers:
Override Themer::resolveTheme() in a service provider:
Themer::extend(function ($theme) {
return match ($theme) {
'user_pref' => auth()->user()->theme_preference,
default => $theme,
};
});
Theme Events: Listen for theme changes via events (not natively supported; extend via events):
// In AppServiceProvider
event(new ThemeChanged(Themer::getTheme()));
Theme-Specific Config: Load theme-specific config by extending the package or using Laravel’s config caching:
// config/themer.php
'config' => [
'dark' => 'themes.dark',
'default' => 'themes.default',
],
Then load dynamically:
config(Themer::getThemeConfigKey());
Internationalization (i18n): Override language files per theme by structuring:
resources/lang/{locale}/themes/{theme}/
└── messages.php
Load with:
__('messages.key', [], Themer::getTheme());
How can I help you explore Laravel packages today?