Weave Code
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

Laravel Themer Laravel Package

qirolab/laravel-themer

View on GitHub
Deep Wiki
Context7

Getting Started

First Steps

  1. Installation

    composer require qirolab/laravel-themer
    php artisan themer:install
    
    • The themer:install command publishes config, migrations, and assets.
  2. Publish Config & Migrations

    php artisan vendor:publish --provider="Qirolab\Themer\ThemerServiceProvider"
    
    • Review config/themer.php for theme settings (default theme, storage paths, etc.).
    • Run migrations:
      php artisan migrate
      
  3. Basic Theme Switching

    • For a single user session:
      use Qirolab\Themer\Facades\Themer;
      
      Themer::setTheme('dark'); // Switch to 'dark' theme
      
    • For all users (via middleware):
      // In App\Http\Kernel.php
      'web' => [
          \Qirolab\Themer\Http\Middleware\ThemeMiddleware::class,
      ],
      
      Configure middleware in config/themer.php:
      'middleware' => [
          'web' => 'dark', // Default theme for web
      ],
      
  4. First Use Case: Dynamic Theme Selection

    • Add a theme selector to your layout (e.g., Blade):
      <select id="theme-selector">
          @foreach(Themer::getAvailableThemes() as $theme)
              <option value="{{ $theme }}" {{ Themer::getCurrentTheme() === $theme ? 'selected' : '' }}>
                  {{ ucfirst($theme) }}
              </option>
          @endforeach
      </select>
      
    • Use JavaScript to update the theme dynamically:
      document.getElementById('theme-selector').addEventListener('change', (e) => {
          fetch('/themer/set-theme', {
              method: 'POST',
              headers: { 'X-CSRF-TOKEN': '{{ csrf_token() }}' },
              body: JSON.stringify({ theme: e.target.value })
          });
      });
      

Implementation Patterns

1. Theme Storage & Persistence

  • User-Specific Themes Store themes per user in the database (default table: themer_themes):

    // Set theme for current user
    Themer::setTheme('light', auth()->id());
    
    // Get user's theme
    $userTheme = Themer::getTheme(auth()->id());
    
  • Cookie-Based Themes (Session-Wide) Useful for anonymous users:

    Themer::setTheme('system', null, 'cookie'); // 'system' theme via cookie
    
  • URL-Based Themes (Query Parameter) Enable in config/themer.php:

    'url' => [
        'enabled' => true,
        'param' => 'theme',
    ],
    

    Access via /dashboard?theme=dark.

2. Theme Assets & Compilation

  • Asset Organization Structure themes in resources/themes/:

    resources/
        themes/
            dark/
                css/
                    app.css
                js/
                    app.js
            light/
                css/
                    app.css
    
    • Reference assets in Blade:
      <link href="{{ Themer::asset('css/app.css') }}" rel="stylesheet">
      
  • Vite/Laravel Mix Integration Configure vite.config.js to handle theme-specific assets:

    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    import { Themer } from 'qirolab/laravel-themer';
    
    export default defineConfig({
        plugins: [
            laravel({
                input: Object.fromEntries(
                    Themer.themes().map(theme => [`./resources/themes/${theme}/js/app.js`, `public/themes/${theme}/js/app.js`])
                ),
            }),
        ],
    });
    

3. Dynamic Theme Switching

  • Middleware-Based Routing Override themes per route:

    Route::middleware(['theme:admin'])->group(function () {
        // Admin dashboard with 'admin' theme
    });
    

    Register in config/themer.php:

    'middleware' => [
        'admin' => 'admin',
    ],
    
  • Event-Based Theme Changes Listen for theme changes:

    use Qirolab\Themer\Events\ThemeChanged;
    
    ThemeChanged::listen(function (ThemeChanged $event) {
        \Log::info("Theme switched to {$event->theme} for user {$event->userId}");
    });
    

4. Theme Fallbacks & Defaults

  • Fallback Chain Define fallbacks in config/themer.php:

    'fallbacks' => [
        'dark' => ['dark', 'system'],
        'light' => ['light', 'system'],
    ],
    
    • If dark theme fails, it falls back to system (OS preference).
  • System Theme Detection Use system theme to respect OS preferences:

    Themer::setTheme('system');
    

    Requires JavaScript detection (e.g., prefers-color-scheme).

5. Multi-Tenant Themes

  • Tenant-Specific Themes Extend the ThemerTheme model to support tenants:
    use Qirolab\Themer\Models\ThemerTheme;
    
    $tenantTheme = ThemerTheme::where('tenant_id', $tenant->id)->first();
    Themer::setTheme($tenantTheme->name);
    

Gotchas and Tips

Pitfalls

  1. Asset Path Caching

    • Issue: Hardcoded asset paths (e.g., /css/app.css) break when switching themes.
    • Fix: Always use Themer::asset():
      <link href="{{ Themer::asset('css/app.css') }}" rel="stylesheet">
      
  2. Middleware Order Matters

    • Issue: Theme middleware must run before other middleware that relies on the theme (e.g., ShareButtons).
    • Fix: Place ThemeMiddleware early in $middlewareGroups['web'].
  3. Database Locking

    • Issue: Concurrent theme updates can cause race conditions.
    • Fix: Use transactions for critical operations:
      DB::transaction(function () {
          Themer::setTheme('dark', $user->id);
      });
      
  4. Theme Asset Compilation

    • Issue: Vite/Laravel Mix may not recompile theme-specific assets.
    • Fix: Explicitly include all themes in your build:
      // vite.config.js
      input: {
          'dark': './resources/themes/dark/js/app.js',
          'light': './resources/themes/light/js/app.js',
      }
      
  5. CORS with Dynamic Themes

    • Issue: API requests may not respect theme changes if CORS headers are static.
    • Fix: Use middleware to set X-Theme header:
      public function handle($request, Closure $next) {
          return $next($request)->header('X-Theme', Themer::getCurrentTheme());
      }
      

Debugging Tips

  1. Log Theme Changes Enable debug mode in config/themer.php:

    'debug' => env('THEMER_DEBUG', false),
    

    Logs theme switches to storage/logs/laravel.log.

  2. Check Active Theme Add a debug Blade component:

    @component('themer::debug')
    @endcomponent
    

    Displays current theme, fallbacks, and assets.

  3. Verify Asset Paths Use Artisan command to list available assets:

    php artisan themer:list-assets
    
  4. Clear Cached Themes If themes aren’t updating:

    php artisan cache:clear
    php artisan view:clear
    

Extension Points

  1. Custom Theme Providers Extend theme resolution logic by creating a custom provider:

    use Qirolab\Themer\Contracts\ThemeProvider;
    
    class CustomThemeProvider implements ThemeProvider {
        public function getTheme(): string {
            return request()->input('custom_theme') ?: 'default';
        }
    }
    

    Register in config/themer.php:

    'providers' => [
        \App\Providers\CustomThemeProvider::class,
    ],
    
  2. Theme Events Extend core events for custom logic:

    // Listen for theme resolution
    Themer::resolving(function ($theme) {
        if (auth()->check() && auth()->user()->isAdmin()) {
            return 'admin';
        }
        return $theme;
    });
    
  3. Dynamic Theme Assets Override asset resolution:

    Themer::extend(function ($themer) {
        $the
    
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.
directorytree/privacy-filter-classifier
directorytree/privacy-filter
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php
agtp/mod-php
splash/sonata-admin
splash/metadata
splash/openapi
splash/scopes
splash/toolkit
testo/output-teamcity
testo/bridge-symfony
spatie/flare-daemon-runtime