Themes
A theme is a collection of Blade views, assets, and configurations that define the look and feel of your site. Themes allow you to create reusable, customizable designs.
What is a Theme?
A theme is responsible for:
- Providing the base
layouts/ - Defining the visual appearance of
sections/ - Implementing reusable
blocks/ - Providing CSS/JS assets for the frontend
Theme Structure
themes/my-theme/
├── views/
│ ├── layouts/
│ │ └── page.blade.php
│ ├── sections/
│ │ ├── hero.blade.php
│ │ ├── features.blade.php
│ │ └── footer.blade.php
│ ├── blocks/
│ │ ├── row.blade.php
│ │ ├── column.blade.php
│ │ └── text.blade.php
│ └── templates/
│ └── page.json
├── assets/
│ ├── css/
│ │ └── theme.css
│ └── js/
│ └── theme.js
└── config.jsonCreating a Theme
1. Create Theme Directory
mkdir -p themes/my-theme/{views/layouts,views/sections,views/blocks,views/templates}
mkdir -p themes/my-theme/{assets/css,assets/js}2. Create Layout
{{-- themes/my-theme/views/layouts/page.blade.php --}}
<html @editor('dark') lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ $meta_title ?? ($title ?? '') . ' | ' . config('app.name') }}</title>
<link rel="stylesheet" href="{{ theme('css/theme.css') }}">
</head>
<body class="page-layout">
@sections('header')
<main>
@yield('content')
</main>
@sections('footer')
<script src="{{ theme('js/theme.js') }}"></script>
</body>
</html>3. Create Sections
{{-- themes/my-theme/views/sections/hero.blade.php --}}
@schema([
'name' => 'Hero',
'settings' => [
['id' => 'title', 'type' => 'text', 'label' => 'Title', 'default' => 'Welcome'],
['id' => 'subtitle', 'type' => 'textarea', 'label' => 'Subtitle', 'default' => ''],
['id' => 'bg_color', 'type' => 'color', 'label' => 'Background', 'default' => '#6366f1'],
],
])
<section {!! $section->editorAttributes() !!}
class="hero-section"
style="background-color: {{ $section->settings->bg_color }}">
<div class="container">
<h1>{{ $section->settings->title }}</h1>
<p>{{ $section->settings->subtitle }}</p>
</div>
</section>4. Create Blocks
{{-- themes/my-theme/views/blocks/row.blade.php --}}
@schema([
'name' => 'Row',
'settings' => [
['id' => 'columns', 'type' => 'select', 'label' => 'Columns', 'default' => '2',
'options' => [
['value' => '1', 'label' => '1 Column'],
['value' => '2', 'label' => '2 Columns'],
['value' => '3', 'label' => '3 Columns'],
]],
],
'blocks' => [
['type' => 'column'],
],
])
<div {!! $block->editorAttributes() !!}
class="grid grid-cols-{{ $block->settings->columns }}">
@blocks($block)
</div>5. Create Template
{
"sections": {
"main": {
"type": "page-content"
}
},
"order": ["main"]
}Theme Assets
Using the theme() Helper
{{-- CSS --}}
<link rel="stylesheet" href="{{ theme('css/theme.css') }}">
{{-- JS --}}
<script src="{{ theme('js/theme.js') }}"></script>
{{-- Images --}}
<img src="{{ theme('images/logo.png') }}" alt="Logo">Vite Integration
{{-- For Vite-based themes --}}
@vite(['themes/my-theme/css/theme.css', 'themes/my-theme/js/theme.js'])Theme Settings
Themes can have global settings. Values are stored in themes/my-theme/config.json under a pagebuilder key:
// themes/my-theme/config.json
{
"pagebuilder": {
"colors.primary": "#6366f1",
"colors.secondary": "#4f46e5",
"fonts.body": "Inter, sans-serif"
}
}The schema for these settings is defined in config/pagebuilder.php under theme_settings_schema. See Configuration for the full schema reference.
Accessing Theme Settings
$theme is a ThemeSettings instance shared with all Blade views, providing type-safe getters (getString, getInt, getBool, getArray, getFloat):
<style>
:root {
--color-primary: {{ $theme->getString('colors.primary', '#6366f1') }};
--font-body: {{ $theme->getString('fonts.body', 'Inter, sans-serif') }};
}
</style>Activating a Theme
Via Configuration
// config/pagebuilder.php
return [
'theme' => 'my-theme',
];Via Middleware
// In route or controller
Route::get('/page/{slug}', [PageController::class, 'show'])
->middleware(\PageBuilder\Http\Middleware\ThemeMiddleware::class . ':my-theme');Via Facade
use PageBuilder\Facades\Theme;
Theme::set('my-theme');Theme Overriding
Themes can override package defaults:
themes/my-theme/views/
├── sections/ # Override package sections
│ └── hero.blade.php
├── blocks/ # Override package blocks
│ └── row.blade.php
└── templates/ # Override package templates
└── page.jsonTheme Discovery
The system discovers themes in this order:
- Theme Views —
themes/{theme}/views/ - App Views —
resources/views/ - Package Views — Package's
resources/views/
Last registration wins.
Multi-Theme Support
Premium Content
Multi-theme system documentation is available to sponsors only.
// Example: Dynamic theme switching
use PageBuilder\Facades\Theme;
// Switch theme based on user preference
Theme::set($user->theme);
// Or based on route
Theme::set(Route::currentRouteName());Tips
- Keep themes modular — Separate concerns into sections and blocks
- Use presets — Provide common configurations as presets
- Asset versioning — Use file modification timestamps for cache busting
- Responsive design — Make themes responsive by default
- Editor support — Always include
@editorandeditorAttributes()