ayra / laravel-themes
A powerful theme management system for Laravel 12.x that helps you organize themes, layouts, assets, and widgets efficiently. Based on teepluss/theme with modern Laravel compatibility.
Installs: 7 993
Dependents: 0
Suggesters: 0
Security: 0
Stars: 4
Watchers: 1
Forks: 2
Open Issues: 0
Requires
- php: ^8.2
- laravel/framework: ^12.0
- opis/closure: ^3.6
Requires (Dev)
- orchestra/testbench: ^9.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2025-08-17 08:43:22 UTC
README
A powerful and modern theme management system for Laravel 12.x that helps you organize themes, layouts, assets, and widgets efficiently. This package is based on teepluss/theme but completely rewritten for modern Laravel compatibility.
✨ Features
- 🎨 Multi-Theme Support: Create and manage multiple themes with ease
- 🏗️ Flexible Layouts: Support for multiple layouts per theme
- 📦 Asset Management: Built-in asset pipeline with dependency management
- 🧩 Widget System: Create reusable widgets for your themes
- 🍞 Breadcrumb Management: Easy breadcrumb generation and customization
- 🔧 Artisan Commands: Powerful CLI tools for theme management
- 🎯 Blade Directives: Custom Blade directives for theme functionality
- 🚀 Laravel 12 Ready: Full compatibility with the latest Laravel version
- 📱 Middleware Support: Route-based theme switching
- 🎭 Partial Views: Modular view system with partials and sections
- 🔄 Theme Switching: Session/cookie-based theme persistence
- 📤 Export/Import: Backup and share themes easily
- 💾 Auto-Backup: Automatic theme backup with rotation
- 🌐 CDN Support: Built-in CDN integration for assets
- 📊 Theme Statistics: Get detailed theme information
- 👀 Theme Preview: Preview themes via URL parameters
- 🎛️ Conditional Assets: Load assets based on conditions
- 🔒 Asset Integrity: SRI support for security
🚀 Quick Start
Requirements
- PHP 8.2 or higher
- Laravel 12.x
Installation
- Install via Composer:
composer require ayra/laravel-themes
- Publish Configuration:
php artisan vendor:publish --provider="Ayra\Theme\ThemeServiceProvider"
- Add to .env:
APP_THEME=default APP_THEME_LAYOUT=layout APP_THEME_DIR=public/themes
- Create Your First Theme:
php artisan theme:create default
📚 Documentation
Table of Contents
- Basic Usage
- Theme Management
- Asset Management
- Layouts & Views
- Widgets
- Breadcrumbs
- Blade Directives
- Configuration
- Artisan Commands
- Advanced Features
- Theme Switching
- Export & Import
- Asset Optimization
- Theme Preview
🎯 Basic Usage
Setting Up a Theme
use Ayra\Theme\Facades\Theme; // Set theme and layout Theme::uses('default')->layout('main'); // Render a view return Theme::view('home.index', ['title' => 'Welcome']);
Controller Integration
namespace App\Http\Controllers; use Ayra\Theme\Facades\Theme; class HomeController extends Controller { public function index() { Theme::uses('default')->layout('main'); return Theme::view('home.index', [ 'title' => 'Welcome to Our Site', 'description' => 'A beautiful theme-powered website' ]); } }
🎨 Theme Management
Creating Themes
# Create a new theme php artisan theme:create my-theme # Create theme with custom facade php artisan theme:create my-theme --facade="MyTheme" # Duplicate existing theme php artisan theme:duplicate default new-theme # List all themes php artisan theme:list # Remove a theme php artisan theme:destroy my-theme
Theme Structure
public/themes/my-theme/
├── assets/
│ ├── css/
│ ├── js/
│ └── img/
├── layouts/
├── partials/
│ └── sections/
├── views/
├── widgets/
├── theme.json
└── config.php
Theme Manifest (theme.json)
{ "slug": "my-theme", "name": "My Beautiful Theme", "author": "Your Name", "email": "your@email.com", "description": "A stunning theme for Laravel applications", "web": "https://yoursite.com", "license": "MIT", "version": "1.0.0" }
🔄 Theme Switching
Session/Cookie Based Switching
// Switch theme and persist in session/cookie Theme::switch('dark-theme', true); // Switch theme for current request only Theme::switch('light-theme', false); // Get current theme from session/cookie $currentTheme = Theme::getCurrentTheme(); // Check if specific theme is active if (Theme::isActive('dark-theme')) { // Dark theme specific logic } // Clear theme session/cookie Theme::clearTheme();
Theme Preview via URL
// Preview theme: /home?theme=dark-theme // Preview layout: /home?layout=mobile // Add middleware to routes Route::get('/home', function () { return Theme::view('home.index'); })->middleware('theme.preview');
Route-Based Theme Switching
// Apply theme middleware to routes Route::get('/admin', function () { return Theme::view('admin.dashboard'); })->middleware('theme:admin,admin-layout'); // Route groups with theme Route::group(['middleware' => 'theme:mobile,mobile-layout'], function () { Route::get('/mobile', function () { return Theme::view('mobile.home'); }); });
📤 Export & Import
Export Themes
# Export theme to ZIP php artisan theme:export default # Export with custom output path php artisan theme:export default --output=/path/to/backup.zip
Import Themes
# Import theme from ZIP php artisan theme:import /path/to/theme.zip # Import with custom name php artisan theme:import /path/to/theme.zip --name="my-custom-theme" # Force import (overwrite existing) php artisan theme:import /path/to/theme.zip --force
Auto-Backup System
# Create backup with automatic rotation php artisan theme:backup default # Keep specific number of backups php artisan theme:backup default --keep=10
📦 Asset Management
Basic Asset Management
// In your theme config.php or controller $asset = Theme::asset(); // Add CSS and JS files $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->add('jquery', 'js/jquery.min.js', ['bootstrap']); // Theme-specific assets $asset->themePath()->add('custom', 'css/custom.css'); // External CDN assets $asset->add('fontawesome', 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css');
Advanced Asset Features
// CDN Support $asset->enableCdn('https://cdn.example.com'); $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->disableCdn(); // Asset Versioning $asset->addVersioned('app', 'js/app.js'); $asset->addVersioned('style', 'css/style.css', [], '2.0.0'); // Conditional Assets $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('desktop', 'desktop-css', 'css/desktop.css'); // Asset Integrity (SRI) $asset->addWithIntegrity('bootstrap', 'css/bootstrap.min.css', 'sha384-...'); // Asset Optimization $asset->optimize(true); // Use minified versions in production
Asset Containers
// Create named containers $asset->container('footer')->add('footer-script', 'js/footer.js'); // Render specific containers @scripts('footer')
Inline Assets
// Inline CSS $asset->writeStyle('custom-style', 'body { background: #f0f0f0; }'); // Inline JavaScript $asset->writeScript('custom-script', 'console.log("Hello World!");');
🏗️ Layouts & Views
Layout System
// Set layout Theme::layout('admin'); // Multiple layouts Theme::layout('mobile')->uses('mobile-theme');
View Rendering
// Basic view Theme::view('home.index', $data); // With specific theme and layout Theme::uses('admin')->layout('dashboard')->view('admin.dashboard', $data); // Scope to theme directory Theme::scope('home.index', $data)->render(); // Watch both theme and app views Theme::watch('home.index', $data)->render();
Partials
// Render partial @partial('header', ['title' => 'Page Header']) // Sections (from partials/sections/) @sections('main') // Partial with layout context Theme::partialWithLayout('sidebar', ['menu' => $menu]);
🧩 Widgets
Creating Widgets
# Global widget php artisan theme:widget UserProfile --global # Theme-specific widget php artisan theme:widget UserProfile default
Widget Class
namespace App\Widgets; use Ayra\Theme\Widget; class WidgetUserProfile extends Widget { public function render($data = []) { return view('widgets.user-profile', $data); } }
Using Widgets
// In Blade templates @widget('user-profile', ['user' => $user]) // In PHP Theme::widget('user-profile', ['user' => $user])->render();
🍞 Breadcrumbs
Creating Breadcrumbs
// Simple breadcrumb Theme::breadcrumb() ->add('Home', '/') ->add('Products', '/products') ->add('Category', '/products/category'); // Array-based Theme::breadcrumb()->add([ ['label' => 'Home', 'url' => '/'], ['label' => 'Products', 'url' => '/products'], ['label' => 'Category', 'url' => '/products/category'] ]);
Custom Templates
// Set custom template Theme::breadcrumb()->setTemplate(' <nav aria-label="breadcrumb"> <ol class="breadcrumb"> @foreach($crumbs as $i => $crumb) @if($i != (count($crumbs) - 1)) <li class="breadcrumb-item"> <a href="{{ $crumb["url"] }}">{{ $crumb["label"] }}</a> </li> @else <li class="breadcrumb-item active">{{ $crumb["label"] }}</li> @endif @endforeach </ol> </nav> '); // Render breadcrumbs {!! Theme::breadcrumb()->render() !!}
🎭 Blade Directives
Available Directives
// Theme data @get('title') @getIfHas('description', 'Default description') // Partials and sections @partial('header', ['title' => 'Header']) @sections('main') // Content @content() // Assets @styles() @scripts() @styles('footer') @scripts('footer') // Widgets @widget('user-profile', ['user' => $user]) // Utilities @protect('email@example.com') @dd('Debug info') @d('Debug info') @dv()
🛠️ Helper Functions
Date & Time Helpers
// Format dates format_date('2024-01-15', 'F j, Y') // January 15, 2024 human_date('2024-01-15') // 2 months ago time_ago('2024-01-15') // 2 months ago // Date checks is_weekend('2024-01-15') // false is_business_day('2024-01-15') // true // Age calculation get_age('1990-05-20') // 33
Formatting Helpers
// Number formatting format_bytes(1024) // 1 KB format_number(1500) // 1.5K format_currency(99.99, 'USD') // $99.99 // Text formatting slugify('Hello World!') // hello-world truncate('Long text here...', 10) // Long text... word_limit('Many words in this sentence', 5) // Many words in this... // Search highlighting highlight_search('Hello World', 'world') // Hello <mark>World</mark>
Security & Privacy Helpers
// Password & token generation generate_password(16, true) // Random secure password generate_token(32) // Random hex token // Data masking mask_email('user@example.com') // us**@ex***.com mask_phone('+1-555-123-4567') // +1-5**-***-4567 // Email protection protectEmail('user@example.com') // JavaScript-protected email link
Device & Browser Detection
// Device type is_mobile() // true/false is_tablet() // true/false is_desktop() // true/false // Browser information $browser = get_browser_info(); // Returns: ['browser' => 'Chrome', 'version' => '120.0', 'os' => 'Windows'] // Client information get_client_ip() // Client IP address get_country_code() // Country code from IP
File & Media Helpers
// File validation is_image('photo.jpg') // true is_video('movie.mp4') // true is_audio('song.mp3') // true // File utilities sanitize_filename('My File (1).pdf') // My_File_1.pdf get_file_extension('document.pdf') // pdf get_file_size('/path/to/file') // 2.5 MB
Validation Helpers
// Input validation validate_email('user@example.com') // true validate_url('https://example.com') // true validate_ip('192.168.1.1') // true
UI & Design Helpers
// Colors get_random_color() // #a1b2c3 get_contrast_color('#ffffff') // #000000 // Emojis get_emoji('smile') // 😊 get_emoji('heart') // ❤️ get_flag_emoji('US') // 🇺🇸 // Gravatar get_gravatar_url('user@example.com', 200) // Gravatar URL
Testing & Development Helpers
// Random test data get_random_name() // John Smith get_random_email() // john.smith@gmail.com get_random_company() // TechCorp get_random_phone() // +1-555-123-4567 get_random_address() // 123 Main St, New York, NY 10001 get_random_website() // https://www.example.com // Random quotes get_random_quote() // Inspirational quote
SEO & Meta Helpers
// Basic meta tags meta_init() // Common meta tags // Custom meta tags meta_tags([ 'title' => 'Page Title', 'description' => 'Page description', 'keywords' => 'laravel, themes' ]) // SEO tags seo_tags( 'Page Title', 'Page description', 'keywords', 'Author Name', 'https://example.com/image.jpg', 'https://example.com/page' )
Utility Helpers
// Ordinal numbers get_ordinal(1) // 1st get_ordinal(2) // 2nd get_ordinal(3) // 3rd // Pluralization get_plural('category', 1) // category get_plural('category', 5) // categories // QR Code & Barcode (requires additional libraries) generate_qr_code('https://example.com') generate_barcode('123456789')
🚀 Advanced Features
Theme Statistics
// Get all available themes $themes = Theme::getAvailableThemes(); // Get theme statistics $stats = Theme::getThemeStats('default'); // Returns: ['views' => 15, 'partials' => 8, 'assets' => 12, 'layouts' => 3, 'widgets' => 5] // Check theme existence if (Theme::exists('my-theme')) { // Theme exists }
Theme Preview URLs
// Generate preview URLs $previewUrl = Theme::getPreviewUrl('dark-theme', '/home'); // Returns: http://yoursite.com/home?theme=dark-theme $layoutPreviewUrl = Theme::getPreviewUrl('default', '/admin', 'admin-layout'); // Returns: http://yoursite.com/admin?theme=default&layout=admin-layout
Conditional Asset Loading
// Load assets based on conditions $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('desktop', 'desktop-css', 'css/desktop.css'); // In your Blade templates @if(request()->isMobile()) @foreach(Theme::asset()->getConditionalAssets('mobile') as $name => $asset) <link rel="stylesheet" href="{{ $asset['path'] }}"> @endforeach @endif
Asset Optimization
// Enable optimization for production if (app()->environment('production')) { Theme::asset()->optimize(true); } // This will automatically use minified versions if they exist // css/style.css → css/min/style.min.css
Theme Switching Examples
// Switch theme with persistence Theme::switch('dark-theme', true); // Switch theme for current request only Theme::switch('light-theme', false); // Check current theme $currentTheme = Theme::getCurrentTheme(); // Check if specific theme is active if (Theme::isActive('dark-theme')) { // Dark theme specific logic }
Export/Import Examples
# Export theme php artisan theme:export default --output=/backups/theme.zip # Import theme php artisan theme:import /backups/theme.zip --name="restored-theme" --force # Create backup with rotation php artisan theme:backup default --keep=10
Advanced Asset Management
// CDN Support $asset->enableCdn('https://cdn.example.com'); $asset->add('bootstrap', 'css/bootstrap.min.css'); // Asset Versioning $asset->addVersioned('app', 'js/app.js'); $asset->addVersioned('style', 'css/style.css', [], '2.0.0'); // Asset Integrity (SRI) $asset->addWithIntegrity('bootstrap', 'css/bootstrap.min.css', 'sha384-...'); // Conditional Assets $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('desktop', 'desktop-css', 'css/desktop.css');
📚 Complete Helper Function Reference
Date & Time Functions
format_date($date, $format, $timezone)
- Format date with custom formathuman_date($date)
- Get human readable datetime_ago($timestamp)
- Get time ago from timestampis_weekend($date)
- Check if date is weekendis_business_day($date)
- Check if date is business dayget_age($birthDate)
- Calculate age from birth date
Formatting Functions
format_bytes($bytes, $precision)
- Format bytes to human readableformat_number($number, $precision)
- Format number with abbreviationsformat_currency($amount, $currency, $locale)
- Format currencyslugify($text, $separator)
- Create URL-friendly slugtruncate($text, $length, $ending)
- Truncate text to lengthword_limit($text, $limit, $ending)
- Limit text to word counthighlight_search($text, $search, $highlight)
- Highlight search terms
Security Functions
generate_password($length, $special_chars)
- Generate random passwordgenerate_token($length)
- Generate random tokenmask_email($email, $mask)
- Mask email for privacymask_phone($phone, $mask)
- Mask phone for privacyprotectEmail($email)
- Protect email from bots
Device Detection Functions
is_mobile()
- Check if request is from mobileis_tablet()
- Check if request is from tabletis_desktop()
- Check if request is from desktopget_browser_info()
- Get browser informationget_client_ip()
- Get client IP addressget_country_code($ip)
- Get country code from IP
File Functions
sanitize_filename($filename)
- Sanitize filenameget_file_extension($filename)
- Get file extensionis_image($filename)
- Check if file is imageis_video($filename)
- Check if file is videois_audio($filename)
- Check if file is audioget_file_size($filepath)
- Get file size
Validation Functions
validate_email($email)
- Validate email addressvalidate_url($url)
- Validate URLvalidate_ip($ip)
- Validate IP address
UI Functions
get_random_color()
- Get random colorget_contrast_color($hexColor)
- Get contrasting colorget_emoji($name)
- Get emoji by nameget_flag_emoji($countryCode)
- Get country flag emojiget_gravatar_url($email, $size)
- Get Gravatar URL
Utility Functions
get_ordinal($number)
- Get ordinal suffixget_plural($singular, $count)
- Get plural formget_random_quote()
- Get random inspirational quoteget_random_name()
- Get random name for testingget_random_email()
- Get random email for testingget_random_company()
- Get random company for testing
SEO Functions
meta_init()
- Print common meta tagsmeta_tags($tags)
- Generate meta tags from arrayseo_tags($title, $description, $keywords, $author, $image, $url)
- Generate SEO meta tags
🎯 Usage Examples in Themes
In Theme Configuration
// public/themes/my-theme/config.php return [ 'events' => [ 'before' => function($theme) { // Set dynamic title with current date $theme->setTitle('My Theme - ' . format_date(now(), 'F Y')); // Set meta tags $theme->setDescription('A beautiful theme created on ' . human_date(now())); // Add conditional assets based on device if (is_mobile()) { $theme->asset()->add('mobile-css', 'css/mobile.css'); } }, 'asset' => function($asset) { // Add versioned assets $asset->addVersioned('main', 'css/main.css'); $asset->addVersioned('app', 'js/app.js'); // Add CDN assets $asset->enableCdn('https://cdn.example.com'); $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->disableCdn(); } ] ];
In Blade Templates
{{-- layouts/main.blade.php --}} <!DOCTYPE html> <html lang="en"> <head> {!! meta_init() !!} {!! seo_tags($title ?? 'My Site', $description ?? 'Welcome', $keywords ?? '') !!} @styles() {{-- Conditional assets --}} @if(is_mobile()) <link rel="stylesheet" href="{{ asset('css/mobile.css') }}"> @endif </head> <body> <header> <h1>{{ $title ?? 'Welcome' }}</h1> <p>Last updated: {{ human_date($lastUpdated) }}</p> {{-- Device-specific content --}} @if(is_mobile()) <div class="mobile-nav">Mobile Navigation</div> @elseif(is_tablet()) <div class="tablet-nav">Tablet Navigation</div> @else <div class="desktop-nav">Desktop Navigation</div> @endif </header> <main> @content() </main> <footer> <p>© {{ date('Y') }} {{ get_random_company() }}</p> <p>Generated in {{ format_bytes(memory_get_peak_usage()) }}</p> </footer> @scripts() </body> </html>
In Controllers
namespace App\Http\Controllers; use Ayra\Theme\Facades\Theme; class HomeController extends Controller { public function index() { // Switch theme based on user preference if (request()->has('theme')) { Theme::switch(request()->get('theme'), true); } // Get theme statistics $stats = Theme::getThemeStats(Theme::getCurrentTheme()); // Prepare data with helper functions $data = [ 'title' => 'Welcome to ' . get_random_company(), 'description' => 'A beautiful site created on ' . human_date(now()), 'stats' => $stats, 'isMobile' => is_mobile(), 'browserInfo' => get_browser_info(), 'randomQuote' => get_random_quote() ]; return Theme::view('home.index', $data); } }
This comprehensive set of helper functions makes your Laravel Themes package incredibly powerful and user-friendly! Users can now build sophisticated themes with minimal custom code, using these built-in utilities for common tasks.
🎓 How to Use - Complete Tutorial
🚀 Getting Started - Step by Step
1. Installation & Setup
# Install the package composer require ayra/laravel-themes # Publish configuration php artisan vendor:publish --provider="Ayra\Theme\ThemeServiceProvider" # Add to .env file echo "APP_THEME=default" >> .env echo "APP_THEME_LAYOUT=main" >> .env echo "APP_THEME_DIR=public/themes" >> .env # Create your first theme php artisan theme:create default
2. Basic Theme Structure
After running php artisan theme:create default
, you'll have:
public/themes/default/
├── assets/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── script.js
│ └── img/
├── layouts/
│ └── layout.blade.php
├── partials/
│ ├── header.blade.php
│ ├── footer.blade.php
│ └── sections/
│ └── main.blade.php
├── views/
│ └── index.blade.php
├── widgets/
├── theme.json
└── config.php
3. Create Your First Layout
{{-- public/themes/default/layouts/layout.blade.php --}} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ Theme::get('title', 'My Website') }}</title> {!! meta_init() !!} @styles() </head> <body> @partial('header') <main> @content() </main> @partial('footer') @scripts() </body> </html>
4. Create Header Partial
{{-- public/themes/default/partials/header.blade.php --}} <header class="site-header"> <nav class="main-nav"> <div class="logo"> <a href="/">{{ Theme::get('site_name', 'My Site') }}</a> </div> <ul class="nav-menu"> <li><a href="/">Home</a></li> <li><a href="/about">About</a></li> <li><a href="/contact">Contact</a></li> </ul> {{-- Device-specific navigation --}} @if(is_mobile()) <div class="mobile-menu-toggle">☰</div> @endif </nav> {{-- Breadcrumbs --}} {!! Theme::breadcrumb()->render() !!} </header>
5. Create Main Content Section
{{-- public/themes/default/partials/sections/main.blade.php --}} <section class="main-content"> <div class="container"> <h1>{{ $title ?? 'Welcome' }}</h1> @if(isset($description)) <p class="lead">{{ $description }}</p> @endif {{-- Show last updated time --}} @if(isset($lastUpdated)) <p class="text-muted"> <small>Last updated: {{ human_date($lastUpdated) }}</small> </p> @endif {{-- Content area --}} <div class="content"> @yield('content') </div> </div> </section>
6. Create Footer Partial
{{-- public/themes/default/partials/footer.blade.php --}} <footer class="site-footer"> <div class="container"> <div class="footer-content"> <div class="footer-section"> <h3>About Us</h3> <p>{{ Theme::get('footer_about', 'A beautiful website built with Laravel Themes.') }}</p> </div> <div class="footer-section"> <h3>Contact</h3> <p>Email: {!! protectEmail('contact@example.com') !!}</p> <p>Phone: {{ mask_phone('+1-555-123-4567') }}</p> </div> <div class="footer-section"> <h3>Quick Links</h3> <ul> <li><a href="/privacy">Privacy Policy</a></li> <li><a href="/terms">Terms of Service</a></li> </ul> </div> </div> <div class="footer-bottom"> <p>© {{ date('Y') }} {{ get_random_company() }}. All rights reserved.</p> <p>Generated in {{ format_bytes(memory_get_peak_usage()) }}</p> </div> </div> </footer>
7. Create Your First View
{{-- public/themes/default/views/index.blade.php --}} @extends('theme::layouts.layout') @section('content') <div class="welcome-section"> <h1>{{ $title ?? 'Welcome to Our Site' }}</h1> @if(isset($description)) <p class="lead">{{ $description }}</p> @endif {{-- Show random quote --}} <blockquote class="inspirational-quote"> "{{ get_random_quote() }}" </blockquote> {{-- Device-specific content --}} @if(is_mobile()) <div class="mobile-features"> <h3>Mobile Optimized</h3> <p>This site is optimized for mobile devices!</p> </div> @elseif(is_tablet()) <div class="tablet-features"> <h3>Tablet Friendly</h3> <p>Perfect for tablet users!</p> </div> @else <div class="desktop-features"> <h3>Desktop Experience</h3> <p>Full desktop experience with advanced features!</p> </div> @endif {{-- Theme statistics --}} @if(isset($stats)) <div class="theme-stats"> <h3>Theme Statistics</h3> <ul> <li>Views: {{ $stats['views'] }}</li> <li>Partials: {{ $stats['partials'] }}</li> <li>Assets: {{ $stats['assets'] }}</li> <li>Layouts: {{ $stats['layouts'] }}</li> <li>Widgets: {{ $stats['widgets'] }}</li> </ul> </div> @endif </div> @endsection
8. Configure Your Theme
{{-- public/themes/default/config.php --}} <?php return [ 'events' => [ 'before' => function($theme) { // Set dynamic title with current date $theme->setTitle('My Beautiful Theme - ' . format_date(now(), 'F Y')); // Set meta information $theme->setDescription('A stunning theme created on ' . human_date(now())); $theme->setAuthor('Your Name'); $theme->setKeywords('laravel, themes, beautiful, responsive'); // Set site information $theme->set('site_name', 'My Awesome Site'); $theme->set('footer_about', 'Building amazing websites with Laravel Themes.'); // Set breadcrumb template $theme->breadcrumb()->setTemplate(' <nav aria-label="breadcrumb"> <ol class="breadcrumb"> @foreach($crumbs as $i => $crumb) @if($i != (count($crumbs) - 1)) <li class="breadcrumb-item"> <a href="{{ $crumb["url"] }}">{{ $crumb["label"] }}</a> </li> @else <li class="breadcrumb-item active">{{ $crumb["label"] }}</li> @endif @endforeach </ol> </nav> '); }, 'asset' => function($asset) { // Add theme-specific assets $asset->themePath()->add([ ['style', 'css/style.css'], ['script', 'js/script.js'] ]); // Add versioned assets $asset->addVersioned('main', 'css/main.css'); $asset->addVersioned('app', 'js/app.js'); // Add conditional assets based on device if (is_mobile()) { $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('mobile', 'mobile-js', 'js/mobile.js'); } elseif (is_tablet()) { $asset->addConditional('tablet', 'tablet-css', 'css/tablet.css'); } else { $asset->addConditional('desktop', 'desktop-css', 'css/desktop.css'); $asset->addConditional('desktop', 'desktop-js', 'js/desktop.js'); } // Add CDN assets $asset->enableCdn('https://cdnjs.cloudflare.com'); $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->add('jquery', 'js/jquery.min.js'); $asset->disableCdn(); // Add assets with integrity (SRI) $asset->addWithIntegrity('bootstrap', 'css/bootstrap.min.css', 'sha384-...'); } ] ];
9. Create Your Controller
<?php namespace App\Http\Controllers; use Ayra\Theme\Facades\Theme; class HomeController extends Controller { public function index() { // Switch theme based on user preference or request if (request()->has('theme')) { Theme::switch(request()->get('theme'), true); } // Get current theme information $currentTheme = Theme::getCurrentTheme(); $themeStats = Theme::getThemeStats($currentTheme); // Prepare data with helper functions $data = [ 'title' => 'Welcome to ' . get_random_company(), 'description' => 'A beautiful and responsive website built with Laravel Themes. Created on ' . human_date(now()), 'lastUpdated' => now(), 'stats' => $themeStats, 'isMobile' => is_mobile(), 'isTablet' => is_tablet(), 'isDesktop' => is_desktop(), 'browserInfo' => get_browser_info(), 'clientIP' => get_client_ip(), 'countryCode' => get_country_code(), 'randomQuote' => get_random_quote(), 'randomName' => get_random_name(), 'randomEmail' => get_random_email(), 'randomCompany' => get_random_company() ]; return Theme::view('index', $data); } public function about() { // Set breadcrumbs Theme::breadcrumb() ->add('Home', '/') ->add('About', '/about'); $data = [ 'title' => 'About Us', 'description' => 'Learn more about our company and mission.', 'team' => [ get_random_name(), get_random_name(), get_random_name() ] ]; return Theme::view('about', $data); } public function contact() { // Set breadcrumbs Theme::breadcrumb() ->add('Home', '/') ->add('Contact', '/contact'); $data = [ 'title' => 'Contact Us', 'description' => 'Get in touch with our team.', 'contactInfo' => [ 'email' => 'contact@example.com', 'phone' => '+1-555-123-4567', 'address' => get_random_address() ] ]; return Theme::view('contact', $data); } }
10. Add Routes
{{-- routes/web.php --}} <?php use App\Http\Controllers\HomeController; Route::get('/', [HomeController::class, 'index']); Route::get('/about', [HomeController::class, 'index']); Route::get('/contact', [HomeController::class, 'contact']); // Theme preview routes Route::get('/preview/{theme}', function($theme) { Theme::switch($theme, false); return Theme::view('index'); })->middleware('theme.preview'); // Admin routes with specific theme Route::group(['middleware' => 'theme:admin,admin-layout'], function () { Route::get('/admin', function () { return Theme::view('admin.dashboard'); }); }); // Mobile routes with mobile theme Route::group(['middleware' => 'theme:mobile,mobile-layout'], function () { Route::get('/mobile', function () { return Theme::view('mobile.home'); }); });
🎨 Advanced Theme Features
Creating Multiple Themes
# Create different themes for different purposes
php artisan theme:create admin
php artisan theme:create mobile
php artisan theme:create corporate
php artisan theme:create blog
Theme Switching in Real-Time
// In your controller or middleware public function switchTheme(Request $request) { $theme = $request->get('theme'); if (Theme::exists($theme)) { Theme::switch($theme, true); // Redirect back with success message return redirect()->back()->with('success', "Theme switched to {$theme}"); } return redirect()->back()->with('error', 'Theme not found'); } // Add theme switcher to your layout <div class="theme-switcher"> <h4>Choose Theme:</h4> @foreach(Theme::getAvailableThemes() as $themeName => $themeInfo) <a href="{{ route('switch.theme', ['theme' => $themeName]) }}" class="theme-option {{ Theme::isActive($themeName) ? 'active' : '' }}"> {{ $themeInfo['name'] ?? $themeName }} </a> @endforeach </div>
Creating Widgets
# Create a global widget php artisan theme:widget UserProfile --global # Create a theme-specific widget php artisan theme:widget RecentPosts default
{{-- app/Widgets/WidgetUserProfile.php --}} <?php namespace App\Widgets; use Ayra\Theme\Widget; class WidgetUserProfile extends Widget { public function render($data = []) { $user = $data['user'] ?? auth()->user(); if (!$user) { return ''; } return view('widgets.user-profile', [ 'user' => $user, 'lastSeen' => human_date($user->last_seen_at), 'memberSince' => human_date($user->created_at) ]); } } {{-- resources/views/widgets/user-profile.blade.php --}} <div class="user-profile-widget"> <div class="user-avatar"> <img src="{{ get_gravatar_url($user->email, 100) }}" alt="{{ $user->name }}"> </div> <div class="user-info"> <h4>{{ $user->name }}</h4> <p>Member since {{ $memberSince }}</p> <p>Last seen {{ $lastSeen }}</p> </div> </div>
Using Widgets in Your Views
{{-- In your Blade templates --}} <div class="sidebar"> @widget('user-profile', ['user' => auth()->user()]) @widget('recent-posts', ['limit' => 5]) </div>
🔧 Asset Management Examples
Advanced Asset Configuration
// In your theme config.php 'asset' => function($asset) { // Enable CDN for production if (app()->environment('production')) { $asset->enableCdn('https://cdn.example.com'); } // Add core assets $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->add('jquery', 'js/jquery.min.js', ['bootstrap']); // Add theme assets with versioning $asset->addVersioned('main', 'css/main.css'); $asset->addVersioned('app', 'js/app.js'); // Add conditional assets based on device if (is_mobile()) { $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('mobile', 'mobile-js', 'js/mobile.js'); } // Add assets with integrity $asset->addWithIntegrity('bootstrap', 'css/bootstrap.min.css', 'sha384-...'); // Disable CDN $asset->disableCdn(); }
Asset Containers
// Create named containers for different sections $asset->container('header')->add('header-css', 'css/header.css'); $asset->container('footer')->add('footer-js', 'js/footer.js'); // In your Blade templates @styles('header') @scripts('footer')
📱 Responsive Design with Device Detection
Device-Specific Content
{{-- In your Blade templates --}} @if(is_mobile()) <div class="mobile-navigation"> <button class="menu-toggle">☰</button> <nav class="mobile-menu"> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> </nav> </div> @elseif(is_tablet()) <div class="tablet-navigation"> <nav class="tablet-menu"> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> </nav> </div> @else <div class="desktop-navigation"> <nav class="desktop-menu"> <a href="/">Home</a> <a href="/about">About</a> <a href="/contact">Contact</a> <a href="/blog">Blog</a> <a href="/portfolio">Portfolio</a> </nav> </div> @endif
Device-Specific Assets
// In your theme config if (is_mobile()) { $asset->addConditional('mobile', 'mobile-css', 'css/mobile.css'); $asset->addConditional('mobile', 'mobile-js', 'js/mobile.js'); } elseif (is_tablet()) { $asset->addConditional('tablet', 'tablet-css', 'css/tablet.css'); } else { $asset->addConditional('desktop', 'desktop-css', 'css/desktop.css'); $asset->addConditional('desktop', 'desktop-js', 'js/desktop.js'); } // In your Blade templates @foreach(Theme::asset()->getConditionalAssets('mobile') as $name => $asset) <link rel="stylesheet" href="{{ asset($asset['path']) }}"> @endforeach
🎯 Real-World Use Cases
E-commerce Theme
// Theme switching based on user preference if (auth()->check() && auth()->user()->theme_preference) { Theme::switch(auth()->user()->theme_preference, true); } // Seasonal themes $currentMonth = date('n'); if (in_array($currentMonth, [11, 12])) { Theme::switch('christmas', false); // Don't persist seasonal themes } elseif (in_array($currentMonth, [10])) { Theme::switch('halloween', false); } // Device-specific product display if (is_mobile()) { $productsPerPage = 6; $view = 'mobile.product-grid'; } else { $productsPerPage = 12; $view = 'desktop.product-grid'; }
Blog Theme
// Dynamic meta tags $metaTags = [ 'title' => $post->title, 'description' => truncate($post->excerpt, 160), 'keywords' => implode(', ', $post->tags->pluck('name')->toArray()), 'author' => $post->author->name, 'image' => $post->featured_image, 'url' => request()->url() ]; // SEO optimization {!! seo_tags($metaTags['title'], $metaTags['description'], $metaTags['keywords'], $metaTags['author'], $metaTags['image'], $metaTags['url']) !!} // Reading time estimation $wordCount = str_word_count(strip_tags($post->content)); $readingTime = ceil($wordCount / 200); // 200 words per minute
Corporate Theme
// Company information $companyInfo = [ 'name' => get_random_company(), 'founded' => '1995', 'employees' => format_number(rand(50, 1000)), 'revenue' => format_currency(rand(1000000, 10000000), 'USD') ]; // Team member cards @foreach($team as $member) <div class="team-member"> <img src="{{ get_gravatar_url($member->email, 200) }}" alt="{{ $member->name }}"> <h3>{{ $member->name }}</h3> <p>{{ $member->position }}</p> <p>Member since {{ human_date($member->joined_at) }}</p> </div> @endforeach
🚀 Performance Optimization
Asset Optimization
// Enable optimization in production if (app()->environment('production')) { Theme::asset()->optimize(true); } // Use CDN for external assets $asset->enableCdn('https://cdn.example.com'); $asset->add('bootstrap', 'css/bootstrap.min.css'); $asset->disableCdn(); // Asset versioning for cache busting $asset->addVersioned('main', 'css/main.css');
Conditional Loading
// Load heavy assets only when needed if (request()->routeIs('blog.*')) { $asset->addConditional('blog', 'blog-css', 'css/blog.css'); $asset->addConditional('blog', 'blog-js', 'js/blog.js'); } if (request()->routeIs('admin.*')) { $asset->addConditional('admin', 'admin-css', 'css/admin.css'); $asset->addConditional('admin', 'admin-js', 'js/admin.js'); }
🔒 Security Features
Email Protection
// Protect email addresses from bots <p>Contact us at: {!! protectEmail('contact@example.com') !!}</p> // Mask sensitive information <p>Phone: {{ mask_phone('+1-555-123-4567') }}</p> <p>Email: {{ mask_email('user@example.com') }}</p>
Asset Integrity
// Add SRI (Subresource Integrity) for external assets $asset->addWithIntegrity('bootstrap', 'css/bootstrap.min.css', 'sha384-...');
📊 Monitoring & Analytics
Theme Usage Statistics
// Get theme statistics $stats = Theme::getThemeStats('default'); // Display in admin panel <div class="theme-stats"> <h3>Theme Statistics</h3> <ul> <li>Views: {{ $stats['views'] }}</li> <li>Partials: {{ $stats['partials'] }}</li> <li>Assets: {{ $stats['assets'] }}</li> <li>Layouts: {{ $stats['layouts'] }}</li> <li>Widgets: {{ $stats['widgets'] }}</li> </ul> </div> // Track theme usage $themes = Theme::getAvailableThemes(); foreach ($themes as $themeName => $themeInfo) { $usageCount = Theme::getThemeStats($themeName); // Store in database for analytics }
🎨 Customization Tips
Creating Custom Helpers
// In your theme's config.php or a custom helper file if (!function_exists('theme_specific_helper')) { function theme_specific_helper($value) { return 'Theme: ' . $value; } } // Use in your views {{ theme_specific_helper('Hello World') }}
Extending Theme Classes
// Create custom theme class class CustomTheme extends \Ayra\Theme\Theme { public function customMethod() { return 'Custom functionality'; } } // Register in service provider $this->app->singleton('theme', function($app) { return new CustomTheme($app['config'], $app['events'], $app['view'], $app['asset'], $app['files'], $app['breadcrumb'], $app['manifest']); });
This comprehensive tutorial shows you exactly how to use every feature of the Laravel Themes package! From basic setup to advanced customization, you now have everything you need to build amazing, responsive themes.