Theme Inheritance and Template Replacement
Themes in Flute CMS support inheritance — you can create your own theme based on an existing one and override only the necessary parts.
How Inheritance Works
By specifying "extends": "standard" in theme.json, your theme inherits all files from the standard theme. You override only what you want to change.
File Search Order
- Your Theme (
mytheme) - Parent Theme (if specified in
extends) - Standard Theme (
standard)
Example
mytheme/views/layouts/header.blade.php ← exists → used
mytheme/views/layouts/footer.blade.php ← missing → taken from standard
mytheme/views/components/button.blade.php ← exists → used
mytheme/views/components/card.blade.php ← missing → taken from standardMinimal Child Theme
Two files are sufficient:
- theme.json
- _variables.scss
theme.json:
{
"name": "My Theme",
"version": "1.0.0",
"author": "Your Name",
"extends": "standard"
}_variables.scss:
:root[data-theme=light] {
--accent: #6366f1;
}
:root[data-theme=dark] {
--accent: #818cf8;
}Everything else is automatically taken from standard.
Inheritance Chain
You can create multiple levels of inheritance:
standard (base)
└── standard-dark (adds dark styles)
└── mytheme (customizes for project)// standard-dark/theme.json
{
"name": "Standard Dark",
"extends": "standard"
}
// mytheme/theme.json
{
"name": "My Theme",
"extends": "standard-dark"
}Search order: mytheme → standard-dark → standard
Module Template Replacement
Modules (Shop, Forum, News, etc.) have their own templates. You can replace them with your own.
Direct Replacement (replacements)
{
"replacements": {
"shop::pages.catalog": "mytheme::shop.catalog",
"shop::pages.product": "mytheme::shop.product",
"news::components.card": "mytheme::news.card"
}
}Now when the system requests shop::pages.catalog, it will receive mytheme::shop.catalog.
File Structure:
- catalog.blade.php
- product.blade.php
Mass Replacement (wildcard_replacements)
Replace all module templates with one line:
{
"wildcard_replacements": {
"shop::pages.*": "mytheme::shop.pages.*",
"shop::components.*": "mytheme::shop.components.*",
"forum::*": "mytheme::forum.*"
}
}shop::pages.catalog→mytheme::shop.pages.catalogshop::pages.product→mytheme::shop.pages.productforum::widgets.online→mytheme::forum.widgets.online
Regex Replacement (module_replacements)
For complex patterns:
{
"module_replacements": {
"/^shop::pages\\.(.+)$/": "mytheme::shop.$1",
"/^forum::(widgets|pages)\\.(.+)$/": "mytheme::forum.$1.$2"
}
}Resource Replacement (SCSS/JS)
asset_replacements
Replace asset files:
{
"asset_replacements": {
"Themes/standard/assets/sass/app.scss": "Themes/mytheme/assets/sass/app.scss",
"Themes/standard/assets/scripts/app.js": "Themes/mytheme/assets/scripts/app.js"
}
}asset_scss_append
Add your styles on top of standard ones (without replacing):
{
"asset_scss_append": {
"main": [
"Themes/mytheme/assets/sass/overrides.scss",
"Themes/mytheme/assets/sass/custom.scss"
]
}
}These files are compiled after the main app.scss, so they can override styles.
Variables for Layouts (layout_arguments)
Passing data to all templates:
{
"layout_arguments": {
"showSidebar": true,
"sidebarWidth": "280px",
"containerMaxWidth": "1400px",
"headerStyle": "sticky"
}
}Usage in templates:
@if ($showSidebar ?? false)
<aside style="width: {{ $sidebarWidth ?? '250px' }}">
@include('partials.sidebar')
</aside>
@endif
<div class="container" style="max-width: {{ $containerMaxWidth ?? '1200px' }}">
@yield('content')
</div>Theme Settings (settings)
Settings that can be changed in the admin panel:
{
"settings": {
"primary_color": {
"name": "Primary Color",
"description": "Choose the main theme color",
"value": "#007aff"
},
"show_footer": {
"name": "Show Footer",
"description": "Enable/disable site footer",
"value": true
},
"header_layout": {
"name": "Header Style",
"description": "Choose layout style",
"value": "default"
}
}
}Custom Colors (colors.json)
Colors for the page editor:
{
"light": {
"--background": "#ffffff",
"--secondary": "#f8fafc",
"--accent": "#007aff",
"--text": "#1a1a2e"
},
"dark": {
"--background": "#121212",
"--secondary": "#1e1e1e",
"--accent": "#0a84ff",
"--text": "#e0e0e0"
}
}Overriding Components
Full Replacement
Create a file with the same path:
standard/views/components/button.blade.php ← original
mytheme/views/components/button.blade.php ← your versionExtending a Component
If you want to add functionality:
{{-- mytheme/views/components/button.blade.php --}}
@props([
'type' => 'primary',
'size' => 'medium',
'disabled' => false,
'icon' => null, {{-- New parameter --}}
'iconPosition' => 'left', {{-- New parameter --}}
])
@php
$classes = "btn btn-{$type} btn-{$size}";
if ($icon) {
$classes .= " btn-with-icon btn-icon-{$iconPosition}";
}
@endphp
<button {{ $attributes->merge(['class' => $classes]) }} @disabled($disabled)>
@if ($icon && $iconPosition === 'left')
<x-icon :path="$icon" />
@endif
{{ $slot }}
@if ($icon && $iconPosition === 'right')
<x-icon :path="$icon" />
@endif
</button>Caching
Clearing Cache
After changes in the theme:
php flute template:cache:clear
php flute cache:clearAutomatic Recompilation
In development mode, SCSS is recompiled automatically when files change. In production, cache is used.
Full Example of theme.json
{
"name": "My Corporate Theme",
"version": "2.0.0",
"author": "Company Name",
"description": "Corporate theme with custom design",
"extends": "standard",
"settings": {
"accent_color": {
"name": "Accent Color",
"value": "#0066cc"
},
"show_social_links": {
"name": "Show Social Links in Footer",
"value": true
}
},
"layout_arguments": {
"maxWidth": "1400px",
"showBreadcrumbs": true
},
"replacements": {
"flute::pages.home": "mytheme::pages.home"
},
"wildcard_replacements": {
"shop::pages.*": "mytheme::shop.*"
},
"asset_scss_append": {
"main": ["Themes/mytheme/assets/sass/corporate.scss"]
}
}