Themes
InspireCMS offers a powerful theming system that allows you to customize the look and feel of your website. This guide covers theme creation, management, and customization.
Theme System Overview
Themes in InspireCMS are organized collections of templates, components, assets, and configurations that determine how your website looks and behaves. The theme system:
- Separates content from presentation
- Allows for easy switching between different designs
- Enables component reuse across templates
- Supports theme inheritance and overriding
Theme Structure
A theme in InspireCMS consists of the following components:
resources/views/components/inspirecms/{theme-name}/
├── layout.blade.php # Main layout template
├── page.blade.php # Standard page template
├── header.blade.php # Header component
├── footer.blade.php # Footer component
├── navigation.blade.php # Navigation component
└── ... other components
Viewing and Changing Themes
Viewing Available Themes
To see all available themes:
- Navigate to Settings → Templates in the admin panel
- The "Themes" section shows all installed themes
- The current active theme is highlighted
Changing the Active Theme
To switch themes:
- Go to Settings → Templates
- Find the theme you want to activate
- Click "Change theme" next to that theme
- Confirm the change
The theme change takes effect immediately on your site.
You can view the current theme by running php artisan inspirecms:about
Creating a New Theme
Using the Admin Interface
- Go to Settings → Templates
- Click "Create theme"
- Enter a name for your new theme
- Choose whether to base it on an existing theme
- Click "Create theme"
The new theme will be created in resources/views/components/inspirecms/{your-theme-name}/.
Manual Creation
- Create the theme directory structure:
mkdir -p resources/views/components/inspirecms/your-theme-name
- Create the essential template files:
touch resources/views/components/inspirecms/your-theme-name/layout.blade.php
touch resources/views/components/inspirecms/your-theme-name/page.blade.php
- Implement the basic templates:
<!-- resources/views/components/inspirecms/your-theme-name/layout.blade.php -->
<!DOCTYPE html>
<html lang="{{ $locale ?? app()->getLocale() }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ $title ?? config('app.name') }}</title>
@if (isset($seo) && $seo instanceof \Illuminate\Contracts\Support\Htmlable)
{{ $seo }}
@endif
<!-- Your CSS and other head elements -->
</head>
<body>
{{ $slot }}
</body>
</html>
<!-- resources/views/components/inspirecms/your-theme-name/page.blade.php -->
@php
$locale ??= $content?->getLocale() ?? request()->getLocale();
$title = $content?->getTitle();
$seo = $content?->getSeo()?->getHtml();
$layoutComponent = inspirecms_templates()->getComponentWithTheme('layout');
@endphp
<x-dynamic-component :component="$layoutComponent" :title="$title" :seo="$seo" :locale="$locale">
<header>
<!-- Header content -->
</header>
<main>
{{ $slot }}
</main>
<footer>
<!-- Footer content -->
</footer>
</x-dynamic-component>
Cloning a Theme
To create a new theme based on an existing one:
- Go to Settings → Templates
- Find the theme you want to clone
- Click "Clone theme"
- Enter a name for the new theme
- Click "Clone"
This copies all templates and components from the source theme to your new theme.
Theme Components
Themes use Blade components to create reusable UI elements.
Creating Theme Components
Create a new component in your theme:
<!-- resources/views/components/inspirecms/your-theme/hero.blade.php -->
<section class="hero">
<div class="hero-content">
<h1>{{ $title ?? 'Welcome' }}</h1>
@if(isset($subtitle))
<p>{{ $subtitle }}</p>
@endif
{{ $slot }}
</div>
</section>
Using Theme Components
Using the helper:
@php
$heroComponent = inspirecms_templates()->getComponentWithTheme('hero');
@endphp
<x-dynamic-component :component="$heroComponent" :title="$pageTitle">
<p>Custom hero content here</p>
</x-dynamic-component>
Theme Configuration
Default Theme Setting
Set the default theme in your configuration:
// config/inspirecms.php
'template' => [
'default_theme' => 'your-theme',
'component_prefix' => 'inspirecms',
'exported_template_dir' => resource_path('views/inspirecms/templates'),
],
Theme-specific Configuration
Create theme-specific configuration:
// config/themes/your-theme.php
return [
'assets' => [
'css' => [
'/themes/your-theme/css/main.css',
'/themes/your-theme/css/custom.css',
],
'js' => [
'/themes/your-theme/js/main.js',
],
],
'colors' => [
'primary' => '#3490dc',
'secondary' => '#ffed4a',
'accent' => '#f66d9b',
],
'fonts' => [
'heading' => 'Montserrat, sans-serif',
'body' => 'Open Sans, sans-serif',
],
];
Access theme configuration in templates:
<div style="color: {{ config('themes.your-theme.colors.primary') }}">
Themed content
</div>
Theme Assets
Asset Structure
Organize theme assets in the public directory:
public/themes/your-theme/
├── css/
│ ├── main.css
│ └── custom.css
├── js/
│ └── main.js
├── images/
│ └── logo.svg
└── fonts/
├── font-regular.woff2
└── font-bold.woff2
Including Assets
Include your assets in the theme's layout:
<!-- resources/views/components/inspirecms/your-theme/layout.blade.php -->
<!DOCTYPE html>
<html lang="{{ $locale ?? app()->getLocale() }}">
<head>
<!-- ... other head elements -->
@foreach(config('themes.your-theme.assets.css', []) as $css)
<link rel="stylesheet" href="{{ $css }}">
@endforeach
@stack('styles')
</head>
<body>
{{ $slot }}
@foreach(config('themes.your-theme.assets.js', []) as $js)
<script src="{{ $js }}"></script>
@endforeach
@stack('scripts')
</body>
</html>
Asset Versioning
For production environments, add versioning to prevent caching issues:
<link rel="stylesheet" href="{{ asset('themes/your-theme/css/main.css') }}?v={{ config('themes.your-theme.version', '1.0.0') }}">
Theme Templates
Templates define how content is displayed using your theme components.
Default Templates
Each theme should provide at least these basic templates:
- Layout: The base HTML structure
- Page: Standard page template
- Simple Page: Minimal page template for basic content
Custom Template Types
Create specialized templates for different content types:
<!-- resources/views/components/inspirecms/your-theme/blog-post.blade.php -->
@php
$locale ??= $content?->getLocale() ?? request()->getLocale();
$title = $content?->getTitle();
$seo = $content?->getSeo()?->getHtml();
$layoutComponent = inspirecms_templates()->getComponentWithTheme('layout');
$headerComponent = inspirecms_templates()->getComponentWithTheme('header');
$footerComponent = inspirecms_templates()->getComponentWithTheme('footer');
$sidebarComponent = inspirecms_templates()->getComponentWithTheme('sidebar');
@endphp
<x-dynamic-component :component="$layoutComponent" :title="$title" :seo="$seo" :locale="$locale">
<x-dynamic-component :component="$headerComponent" :locale="$locale" />
<main class="blog-post-container">
<article class="blog-post">
<header>
<h1>@property('blog', 'title')</h1>
<p class="meta">
<time>@property('blog', 'date')</time>
<span class="author">@property('blog', 'author')</span>
</p>
</header>
<div class="blog-content">
@property('blog', 'content')
</div>
<footer>
@propertyArray('blog', 'tags')
<div class="tags">
@foreach($blog_tags ?? [] as $tag)
<span class="tag">{{ $tag }}</span>
@endforeach
</div>
@endif
</footer>
</article>
<aside>
<x-dynamic-component :component="$sidebarComponent" :content="$content" />
</aside>
</main>
<x-dynamic-component :component="$footerComponent" :locale="$locale" />
</x-dynamic-component>
Responsive Design
Ensure your theme works across different devices:
<!-- resources/views/components/inspirecms/your-theme/layout.blade.php -->
<!DOCTYPE html>
<html lang="{{ $locale ?? app()->getLocale() }}">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ...other head elements -->
<style>
/* Basic responsive styles */
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
@media (max-width: 768px) {
.container {
padding: 0 10px;
}
}
</style>
</head>
<body>
<!-- ...content -->
</body>
</html>
Testing Themes
Verify your theme works properly:
- Test with different content types
- Test on various screen sizes and devices
- Validate accessibility compliance
- Check for browser compatibility
Theme Development Best Practices
- Separation of Concerns: Keep presentation logic out of templates
- Component Reusability: Design reusable components
- CSS Organization: Use a structured approach (e.g., BEM methodology)
- Accessibility: Ensure themes meet WCAG guidelines
- Performance: Minimize CSS/JS and optimize assets
- Documentation: Document theme components and configuration options
- Version Control: Track theme changes in version control
Publishing Themes
To share your theme with others:
- Package your theme files
- Include documentation for installation and configuration
- List required assets and dependencies
- Provide example templates and screenshots
Implementation Examples
Let's assume you've created a theme named "abc".
Approach 1: Using Components
Folder Structure
resources/views/components/inspirecms/abc/
├── footer.blade.php
├── header.blade.php
├── layout.blade.php
├── page.blade.php
└── simple-page.blade.php
Component Files
<!-- resources/views/components/inspirecms/abc/layout.blade.php -->
@php
$title ??= config('app.name');
$locale ??= request()->getLocale();
@endphp
<html lang="{{ $locale }}">
<head>
@if (isset($seo) && $seo instanceof \Illuminate\Contracts\Support\Htmlable)
{{ $seo }}
@else
<title>{{ $title }}</title>
@endif
@yield('styles')
</head>
<body>
{{ $slot }}
@yield('scripts')
</body>
</html>
<!-- resources/views/components/inspirecms/abc/header.blade.php -->
<nav>
@foreach (inspirecms()->getNavigation('main', $locale ?? request()->getLocale()) as $item)
<a href="{{ $item->getUrl() }}">{{ $item->getTitle() }}</a>
@endforeach
</nav>
<!-- resources/views/components/inspirecms/abc/footer.blade.php -->
<footer>
<div>
@foreach (inspirecms()->getNavigation('footer', $locale ?? request()->getLocale()) as $item)
<div>
<h4>{{ $item->getTitle() }}</h4>
@if ($item->hasChildren())
<ul>
@foreach ($item->children as $child)
<li><a href="{{ $child->getUrl() }}">{{ $child->getTitle() }}</a></li>
@endforeach
</ul>
@endif
</div>
@endforeach
</div>
<div class="copyright">
<p>Copyright</p>
</div>
</footer>
<!-- resources/views/components/inspirecms/abc/page.blade.php -->
@php
$locale ??= $content?->getLocale() ?? request()->getLocale();
$title = $content?->getTitle();
$seo = $content?->getSeo()?->getHtml();
$layoutComponent = inspirecms_templates()->getComponentWithTheme('layout');
$headerComponent = inspirecms_templates()->getComponentWithTheme('header');
$footerComponent = inspirecms_templates()->getComponentWithTheme('footer');
@endphp
<x-dynamic-component :component="$layoutComponent" :title="$title" :seo="$seo" :locale="$locale">
<x-dynamic-component :component="$headerComponent" :locale="$locale" />
{{ $slot }}
<x-dynamic-component :component="$footerComponent" :locale="$locale" />
</x-dynamic-component>
<!-- resources/views/components/inspirecms/abc/simple-page.blade.php -->
@php
$locale ??= $content?->getLocale() ?? request()->getLocale();
$title = $content?->getTitle();
$seo = $content?->getSeo()?->getHtml();
$layoutComponent = inspirecms_templates()->getComponentWithTheme('layout');
$footerComponent = inspirecms_templates()->getComponentWithTheme('footer');
@endphp
<x-dynamic-component :component="$layoutComponent" :title="$title" :seo="$seo" :locale="$locale">
{{ $slot }}
<x-dynamic-component :component="$footerComponent" :locale="$locale" />
</x-dynamic-component>
Applying Layouts to Templates
<!-- Template: home -->
<x-cms-template :content="$content" type="page">
Home
</x-cms-template>
<!-- Template: tnc -->
<x-cms-template :content="$content" type="simple-page">
TNC Here
</x-cms-template>
Approach 2: Using Template Inheritance
Folder Structure
resources/views/
├── layouts/
│ └── inspirecms/
│ └── abc/
│ ├── base.blade.php
│ ├── footer.blade.php
│ └── topnav.blade.php
└── components/
└── inspirecms/
└── abc/
├── page.blade.php
└── simple-page.blade.php
Learn more about layouts using inheritance in Blade.
Template Files
<!-- resources/views/layouts/inspirecms/abc/base.blade.php -->
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8">
@hasSection('seo')
@yield('seo')
@endif
@sectionMissing('seo')
<title>App Name - @yield('title')</title>
@endif
</head>
<body>
@yield('content')
</body>
</html>
<!-- resources/views/layouts/inspirecms/abc/topnav.blade.php -->
<nav>
@foreach (inspirecms()->getNavigation('topnav', $locale ?? request()->getLocale()) as $item)
<a href="{{ $item->getUrl() }}">{{ $item->getTitle() }}</a>
@endforeach
</nav>
Footer Layout
<!-- resources/views/layouts/inspirecms/abc/footer.blade.php -->
<footer>
<div>
@foreach (inspirecms()->getNavigation('footer', $locale ?? request()->getLocale()) as $item)
<div>
<h4>{{ $item->getTitle() }}</h4>
@if ($item->hasChildren())
<ul>
@foreach ($item->children as $child)
<li><a href="{{ $child->getUrl() }}">{{ $child->getTitle() }}</a></li>
@endforeach
</ul>
@endif
</div>
@endforeach
</div>
<div class="copyright">
<p>Copyright</p>
</div>
</footer>
<!-- resources/views/components/inspirecms/abc/page.blade.php -->
@extends('layouts.'.inspirecms_templates()->getComponentWithTheme('base'))
@section('content')
@include('layouts.'.inspirecms_templates()->getComponentWithTheme('topnav'))
<div class="container">
@yield('page-content', 'No content found')
</div>
@include('layouts.'.inspirecms_templates()->getComponentWithTheme('footer'))
@endsection
<!-- resources/views/components/inspirecms/abc/simple-page.blade.php -->
@extends('layouts.'.inspirecms_templates()->getComponentWithTheme('base'))
@section('content')
<div class="container">
@yield('page-content', 'No content found')
</div>
@include('layouts.'.inspirecms_templates()->getComponentWithTheme('footer'))
@endsection
Applying Layouts to Templates
<!-- Template: home -->
@extends('components.'.inspirecms_templates()->getComponentWithTheme('page'))
@section('seo', $content->getSeo()?->getHtml())
@section('title', $content->getTitle())
@section('page-content')
<p>This is my body content.</p>
@endsection
<!-- Template: tnc -->
@extends('components.'.inspirecms_templates()->getComponentWithTheme('simple-page'))
@section('seo', $content->getSeo()?->getHtml())
@section('title', $content->getTitle())
@section('page-content')
<p>TNC</p>
@endsection