# Stylist Module Tenant-aware styling module for Laravel 13 / nwidart Laravel Modules. ## Theme layout Each theme is self-contained: ```text resources/themes/{theme}/ ├── theme.json ├── css/theme.css └── views/ ├── layouts/app.blade.php ├── components/page-hero.blade.php └── livewire/theme-preview.blade.php ``` The active tenant/company resolves to a theme key such as `default`, `mpba`, or `abbott`. ## Rendering themed views Use the helper from controllers, Blade components, and Livewire components: ```php return stylist_view('layouts.app'); ``` It checks views in this order: ```text stylist-theme-{active-theme}::{view} stylist-theme-{default-theme}::{view} stylist::{view} ``` ## Livewire Keep the PHP component class shared and put the template in each theme: ```text Livewire/ThemePreview.php resources/themes/default/views/livewire/theme-preview.blade.php resources/themes/mpba/views/livewire/theme-preview.blade.php ``` The component renders with: ```php return stylist_view('livewire.theme-preview', ['stats' => $this->stats]); ``` ## Tenant assignment Add or use these fields on `companies`: ```text theme_key brand_primary brand_secondary brand_accent logo_path favicon_path theme_settings ``` Then assign: ```php $company->update(['theme_key' => 'mpba']); ``` ## Publishing ```bash php artisan vendor:publish --tag=stylist-config # or php artisan stylist:publish-assets Themes are not published from or stored inside the module. Install them directly under `resources/themes`. ``` ## Blade helpers ```blade @themeVariables @themeStylesheet ``` ## Self-contained application themes Application themes live in `resources/themes/{theme}` and own their runtime assets: ```text resources/themes/example/ ├── theme.json ├── css/theme.css ├── js/app.js └── views/home.blade.php ``` Use `@themeStylesheet('css/theme.css')`, `@themeScript('js/app.js')`, or `theme_asset('images/example.svg')`. Assets are served from the selected theme directory by the `stylist.theme.asset` route; they do not need to be copied into `public/themes` or added to the global Vite inputs. ## Appearance and colour variants Themes may declare `appearances` (`light`, `dark`, `auto`) and named `accents` in `theme.json`. Include `@themeVariables` in the document `` before the theme stylesheet to prevent a flash of the wrong appearance. Add `@themeSwitcher` anywhere in a Blade layout for a ready-made runtime selector. User choices are stored in localStorage and are applied without rebuilding assets or reloading the page. ## Theme manifest compatibility Stylist accepts versioned manifests while remaining compatible with older themes. New manifests should declare: ```json { "manifest_version": 1, "key": "design-gallery", "name": "Design Gallery" } ``` `manifest_version` defaults to `1` when omitted. Unknown manifest fields are preserved and ignored by Stylist unless the current version explicitly uses them, allowing Theme Builder to add future metadata without preventing theme discovery. Appearance and accent features are optional. Stylist derives the internal capability flags only when the corresponding definitions exist: ```json { "appearances": ["light", "dark", "system"], "accents": ["blue", "neutral"], "default_appearance": "system", "default_accent": "neutral" } ``` Legacy themes with none of these fields continue to load unchanged and do not receive appearance or accent controls. Additional boolean capabilities may be declared explicitly: ```json { "capabilities": { "marketplace": true } } ``` ## Validate a theme Validate an installed theme key, unpacked theme directory, or ZIP package: ```bash php artisan stylist:validate design-gallery php artisan stylist:validate resources/themes/design-gallery php artisan stylist:validate ~/Downloads/design-gallery.zip ``` The command checks the manifest, required entry view, stylesheet, script, declared assets, preview and accessibility issues. It exits with a failure status when errors are found. ## Theme inheritance and diagnostics Shared application views belong to the `common` theme. Child themes declare inheritance without copying those views: ```json { "name": "Dashboard", "slug": "admin", "extends": "common" } ``` Resolution order is the active theme, each declared parent, the configured fallback, the common theme, module defaults, then Laravel's normal views. Use these maintenance commands: ```bash php artisan stylist:inspect php artisan stylist:duplicates php artisan stylist:doctor php artisan stylist:create-theme customer --parent=common --name="Customer Portal" ``` `stylist:duplicates` fails when the same relative Blade task path exists in more than one theme. Add a child view only when it is a deliberate replacement; this application enforces one authoritative view per task.