| title | Theme Development | |
|---|---|---|
| slug | themes | |
| audience | developer | |
| category | developers | |
| order | 10 | |
| time | 30 | |
| prerequisites |
|
Complete guide for creating and customizing themes in TallCMS using the file-based multi-theme system.
TallCMS uses a file-based theme system where each theme is a self-contained directory with its own configuration, assets, and template overrides. Themes are automatically discovered and can override any template in the application.
- File-Based Themes: Themes live in
themes/{slug}/directories with Laravel-compliant structure - Template Override Resolution: Themes override templates by path priority (theme → app default)
- Asset Management: Each theme has its own Vite build process with automatic asset compilation
- Configuration: Themes use
theme.jsonfor metadata and daisyUI/Tailwind v4 CSS config inresources/css/app.css - Zero Code Changes: Existing blocks and templates work unchanged with theme overrides
themes/{slug}/ # Theme root directory
├── theme.json # Theme metadata and configuration
├── package.json # NPM dependencies and build scripts
├── vite.config.js # Vite build configuration
├── public/ # Static assets (images, fonts, etc.)
│ ├── css/
│ ├── js/
│ ├── img/
│ └── build/ # Compiled assets (auto-generated)
│ ├── manifest.json # Vite asset manifest
│ └── assets/ # Hashed asset files
└── resources/ # Source files
├── views/ # Template overrides
│ ├── layouts/ # Layout templates
│ ├── cms/blocks/ # Block template overrides
│ └── components/ # Component overrides
├── css/
│ └── app.css # Main stylesheet (Tailwind v4 + daisyUI)
├── js/
│ └── app.js # JavaScript entry point
└── img/ # Source images
# Interactive mode (recommended)
php artisan make:theme
# Or with options
php artisan make:theme my-awesome-theme \
--description="A modern theme" \
--author="Your Name"Edit themes/my-awesome-theme/theme.json:
{
"name": "My Awesome Theme",
"slug": "my-awesome-theme",
"version": "1.0.0",
"description": "A modern, clean theme for business websites",
"author": "Your Name",
"daisyui": {
"preset": "corporate",
"prefersDark": "business"
},
"supports": {
"dark_mode": true,
"responsive": true,
"theme_controller": false
}
}# Install dependencies
npm install
# Navigate to theme
cd themes/my-awesome-theme
# Build assets
npm run build
# Return and activate
cd ../..
php artisan theme:activate my-awesome-themeOverride any template by creating files in the same relative path structure:
# Override main layout
themes/my-theme/resources/views/layouts/app.blade.php
# Override blocks
themes/my-theme/resources/views/cms/blocks/hero-block.blade.php
# Override components
themes/my-theme/resources/views/components/hero-section.blade.phpResolution Priority:
- Theme Template:
themes/{active}/resources/views/... - Application Default:
resources/views/...
Use daisyUI component classes and semantic colors:
<div class="card bg-base-100 shadow-xl">
<div class="card-body">
<h2 class="card-title">Pricing</h2>
<p class="text-base-content">Simple, predictable pricing.</p>
<div class="card-actions">
<a href="#" class="btn btn-primary">Get started</a>
</div>
</div>
</div>{{-- CMS core runtime (contact-form, comments, Alpine plugins) --}}
@tallcmsCoreJs
{{-- Theme-specific compiled assets (CSS + theme-only JS) --}}
@themeVite(['resources/css/app.css', 'resources/js/app.js'])
{{-- Static assets --}}
<img src="@themeAsset('images/logo.png')" alt="Logo">CMS block components (contact-form, comments, Alpine plugins) are loaded once from the root Vite build via @tallcmsCoreJs. Theme app.js is for theme-specific behavior only and must not import resources/js/tallcms.
This separation means:
- Core JS changes ship to all themes immediately with a single
npm run buildat the project root — no theme rebuilds needed. - Theme JS stays small and focused on theme-specific functionality.
- Guard tests (
tests/Unit/ThemeCoreJsGuardTest.php) enforce this boundary in CI.
Your theme's resources/css/app.css must include source directives for Tailwind CSS to discover all classes used by TallCMS blocks:
@import "tailwindcss";
@plugin "@tailwindcss/typography";
/* Scan paths for class discovery (paths relative to theme CSS file) */
@source "../views/**/*.blade.php";
@source "../../../../resources/views/**/*.blade.php";
@source "../../../../plugins/tallcms/pro/resources/views/blocks/**/*.blade.php";
@source "../../../../packages/tallcms/cms/resources/views/**/*.blade.php";
/* TallCMS Block PHP files - REQUIRED for DaisyUI dynamic classes */
@source "../../../../packages/tallcms/cms/src/Filament/Blocks/**/*.php";
@plugin "daisyui" {
themes: light --default, dark --prefersdark;
}Important: The PHP block source directive is essential. Block PHP files define DaisyUI class options (button variants, colors, etc.) that must be scanned for the CSS build to include them. Without this directive, dynamic styles like divider colors or button variants won't render on the frontend.
Define custom colors in resources/css/app.css:
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui" {
themes: mybrand --default;
}
@plugin "daisyui/theme" {
name: "mybrand";
default: true;
color-scheme: light;
--color-base-100: oklch(98% 0.02 240);
--color-base-content: oklch(20% 0.05 240);
--color-primary: oklch(55% 0.3 240);
--color-primary-content: oklch(98% 0.01 240);
/* ... additional color variables */
}cd themes/my-theme
npm run dev # Hot reloadingcd themes/my-theme
npm run buildphp artisan theme:list # List themes
php artisan theme:list --detailed # Detailed info
php artisan theme:build my-theme # Build assets
php artisan theme:activate my-theme # Activate theme- daisyUI-First: Use component classes before custom CSS
- Semantic Colors: Use
bg-base-*,text-base-content,btn-primary - Mobile-First: Design for mobile, enhance for larger screens
- Override Minimally: Only override what needs to change
- Test Both: Check admin preview and frontend display
Theme not activating:
- Ensure
theme.jsonis valid JSON - Check
npm run buildcompleted - Verify symlinks in
public/themes/
Styles not loading:
- Check Vite manifest exists
- Use
@themeVitedirective - Clear view cache:
php artisan view:clear
DaisyUI classes not working on frontend (but work in admin preview):
- Ensure your theme CSS includes the PHP block source directive:
@source "../../../../packages/tallcms/cms/src/Filament/Blocks/**/*.php";
- Rebuild theme:
cd themes/my-theme && npm run build - Clear caches:
php artisan optimize:clear
Template overrides not working:
- Verify file path matches exactly
- Ensure theme is activated
- Clear caches
$themeManager = app('theme.manager');
$activeTheme = active_theme();
$assetUrl = theme_asset('images/logo.png');@tallcmsCoreJs {{-- Shared CMS runtime (Alpine components, plugins) --}}
@themeVite(['resources/css/app.css']) {{-- Theme CSS/JS assets --}}
@themeAsset('images/logo.png') {{-- Static theme asset URL --}}