Theme System
Comprehensive guide to Antler's theme system with 16+ color themes and real-time switching
Theme System
Antler CMS features a sophisticated theme system that provides 16+ built-in color themes with seamless switching capabilities. The system supports both site-wide defaults and user preferences, with full integration between development and production modes.
Available Themes
Color Theme Collection
The theme system includes a comprehensive collection of professionally designed color themes:
Blue Family
- Blue - Classic professional blue
- Indigo - Deep indigo for sophistication
- Cyan - Bright cyan for modern appeal
- Sky - Light and airy blue
Purple Family
- Purple - Rich purple for creativity
- Violet - Soft violet tones
Pink/Red Family
- Pink - Soft pink for warmth
- Rose - Elegant rose tones
- Red - Bold red for energy
Green Family
- Green - Natural green
- Emerald - Vibrant emerald
- Lime - Fresh lime green
- Teal - Sophisticated teal
Warm Tones
- Orange - Vibrant orange for friendliness
- Amber - Warm amber tones
- Yellow - Bright yellow for optimism
Neutral
- Slate - Professional gray tones
Theme Architecture
Core Components
-
Theme Registry (
src/utils/theme-registry.ts)- Defines all 16 available themes
- Provides theme metadata and validation
-
Theme Loader (
src/utils/theme-loader.ts)- Handles dynamic theme switching
- Manages localStorage persistence
- Prevents FOUC with initialization scripts
-
Theme Stylesheets (
src/styles/themes/)- Individual CSS files for each theme
- CSS custom properties for consistent theming
- Dark mode variants using
[data-theme="dark"]selector
-
Theme Components
ThemeToggle.tsx: Dark/light mode switcher- Settings page: Complete theme customization interface
Theme Structure
Each theme defines CSS custom properties for consistent styling:
/* Example: theme-blue.css */
:root {
--theme-primary: #3b82f6;
--theme-primary-dark: #1d4ed8;
--theme-primary-light: #60a5fa;
--theme-secondary: #64748b;
--theme-accent: #f59e0b;
/* Background colors */
--theme-bg-primary: #ffffff;
--theme-bg-secondary: #f8fafc;
--theme-bg-tertiary: #f1f5f9;
/* Text colors */
--theme-text-primary: #0f172a;
--theme-text-secondary: #475569;
--theme-text-muted: #64748b;
/* Border and surface colors */
--theme-border: #e2e8f0;
--theme-surface: #ffffff;
--theme-surface-hover: #f8fafc;
}
[data-theme="dark"] {
--theme-primary: #60a5fa;
--theme-bg-primary: #0f172a;
--theme-bg-secondary: #1e293b;
--theme-text-primary: #f8fafc;
/* ... dark mode variants */
}
Static Site Integration
Automatic Theme Loading
The static site automatically loads themes through BaseLayout.astro:
---
// BaseLayout.astro
import siteConfig from '../site.config.json';
const defaultTheme = siteConfig.customization?.theme?.default || 'blue';
---
<html lang="en">
<head>
<!-- Dynamic theme loading -->
<link
id="theme-stylesheet"
rel="stylesheet"
href={`/src/styles/themes/theme-${defaultTheme}.css`}
/>
<!-- FOUC prevention script -->
<script is:inline>
(function() {
// Initialize theme before page render
const savedTheme = localStorage.getItem('selectedTheme') || 'blue';
const savedMode = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
// Load theme stylesheet
const themeLink = document.getElementById('theme-stylesheet');
if (themeLink) {
themeLink.href = `/src/styles/themes/theme-${savedTheme}.css`;
}
// Apply dark mode
if (savedMode === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark');
}
})();
</script>
</head>
<body>
<slot />
</body>
</html>
User Theme Selection
Users can customize themes through the /settings page:
- Color Theme Selection: Grid of all 16 available themes
- Dark Mode Toggle: Switch between light and dark modes
- Reset to Default: Restore site’s default theme
- Live Preview: Instant theme switching without page reload
Admin Interface Integration
Admin Theme Loading
The admin interface supports the same theme system with slight variations for server-side rendering:
<!-- src/pages/admin/index.astro -->
<html lang="en">
<head>
<link
id="theme-stylesheet"
rel="stylesheet"
href="/src/styles/themes/theme-blue.css"
/>
<script is:inline>
// Same FOUC prevention as static site
(function() {
const savedTheme = localStorage.getItem('selectedTheme') || 'blue';
const savedMode = localStorage.getItem('theme') ||
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
const themeLink = document.getElementById('theme-stylesheet');
if (themeLink) {
themeLink.href = `/src/styles/themes/theme-${savedTheme}.css`;
}
if (savedMode === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark');
}
})();
</script>
</head>
</html>
Admin-Specific Styling
The admin interface includes additional global styles for optimal user experience:
// AdminApp.tsx - Global admin styles
const globalStyles = `
body {
background-color: var(--theme-bg-secondary);
color: var(--theme-text-primary);
}
[data-theme="dark"] body {
background-color: var(--theme-bg-primary);
}
/* Custom scrollbar theming */
::-webkit-scrollbar-thumb {
background-color: var(--theme-border);
}
[data-theme="dark"] ::-webkit-scrollbar-thumb {
background-color: var(--theme-text-muted);
}
`;
Available Themes
| Theme | Primary Color | Description |
|---|---|---|
| Amber | #f59e0b | Warm golden yellow |
| Blue | #3b82f6 | Classic blue (default) |
| Cyan | #06b6d4 | Bright cyan |
| Emerald | #10b981 | Rich emerald green |
| Gray | #6b7280 | Neutral gray |
| Green | #22c55e | Vibrant green |
| Indigo | #6366f1 | Deep indigo |
| Lime | #84cc16 | Bright lime green |
| Orange | #f97316 | Vibrant orange |
| Pink | #ec4899 | Bright pink |
| Purple | #a855f7 | Rich purple |
| Red | #ef4444 | Bold red |
| Rose | #f43f5e | Soft rose |
| Sky | #0ea5e9 | Light sky blue |
| Teal | #14b8a6 | Balanced teal |
| Yellow | #eab308 | Bright yellow |
User Guide
Changing Themes
For End Users:
- Navigate to
/settingson your site - Select a color theme from the grid
- Toggle dark/light mode as desired
- Changes are saved automatically
Theme Persistence:
- Selections are saved to
localStorage - Themes persist across browser sessions
- System dark mode preference is respected by default
Theme Switching Behavior
- Instant Application: Theme changes apply immediately without page reload
- Cross-Page Consistency: Theme selection persists across all pages
- Admin Sync: Theme changes in the main site apply to admin interface
- Fallback Handling: Defaults to site’s configured theme if localStorage is unavailable
Developer Guide
Creating Custom Themes
-
Create Theme Stylesheet:
/* src/styles/themes/theme-custom.css */ :root { --theme-primary: #your-primary-color; --theme-primary-dark: #your-primary-dark; --theme-primary-light: #your-primary-light; /* Define all required CSS variables */ } [data-theme="dark"] { /* Dark mode variants */ } -
Register Theme:
// src/utils/theme-registry.ts export const themes = [ // ... existing themes { id: 'custom', name: 'Custom', primary: '#your-primary-color', description: 'Your custom theme' } ]; -
Update Site Configuration:
// site.config.json { "customization": { "theme": { "default": "custom" } } }
Using Theme Variables
In CSS:
.my-component {
background-color: var(--theme-bg-primary);
color: var(--theme-text-primary);
border: 1px solid var(--theme-border);
}
.my-component:hover {
background-color: var(--theme-surface-hover);
}
In Components:
<!-- Astro component -->
<div class="bg-theme-primary text-white p-4">
<h2 style="color: var(--theme-text-primary)">Themed Content</h2>
</div>
// React component
const ThemedButton = () => (
<button
style={{
backgroundColor: 'var(--theme-primary)',
color: 'var(--theme-bg-primary)'
}}
>
Themed Button
</button>
);
Theme-Aware Tailwind Classes
The system integrates with Tailwind CSS for responsive, theme-aware styling:
<!-- Light/dark mode responsive -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Content that adapts to dark mode
</div>
<!-- Using theme variables with Tailwind -->
<div class="bg-[var(--theme-bg-primary)] text-[var(--theme-text-primary)]">
Theme-aware content
</div>
Configuration
Site-Level Configuration
Configure default theme in site.config.json:
{
"customization": {
"theme": {
"default": "blue",
"allowUserSelection": true,
"darkModeDefault": "system"
}
}
}
Environment-Specific Themes
You can set different default themes for different environments:
// astro.config.mjs
export default defineConfig({
// ... other config
vite: {
define: {
__DEFAULT_THEME__: JSON.stringify(
process.env.NODE_ENV === 'production' ? 'blue' : 'purple'
)
}
}
});
Performance Considerations
Optimization Features
- CSS Loading: Only one theme stylesheet loaded at a time
- FOUC Prevention: Inline scripts prevent flash of unstyled content
- Lazy Loading: Theme stylesheets are swapped dynamically
- Caching: Browser caches theme stylesheets for faster subsequent loads
Best Practices
- Minimize Custom Properties: Only define necessary CSS variables
- Use Semantic Names: Choose descriptive variable names for maintainability
- Test All Themes: Ensure your content works well with all 16 themes
- Consider Contrast: Maintain accessibility standards across all themes
Troubleshooting
Common Issues
Theme Not Loading:
- Check that theme stylesheet exists in
src/styles/themes/ - Verify theme ID matches registry entry
- Ensure localStorage permissions are available
FOUC (Flash of Unstyled Content):
- Confirm initialization script is present in page head
- Check that script runs before body content loads
- Verify CSS custom properties are defined
Admin Theme Inconsistency:
- Ensure all admin pages include theme loading script
- Check that
global.cssis imported in admin layouts - Verify theme variables are used consistently
Dark Mode Not Working:
- Confirm
[data-theme="dark"]selectors are present - Check that dark mode toggle updates
data-themeattribute - Verify localStorage is saving dark mode preference
Debug Mode
Enable theme debugging by adding to localStorage:
localStorage.setItem('theme-debug', 'true');
This will log theme loading events to the browser console.
Migration Guide
From Legacy Theme System
If migrating from an older theme system:
- Backup Current Themes: Save existing theme customizations
- Update CSS Variables: Replace old variables with new theme variables
- Test All Pages: Verify theme consistency across site and admin
- Update Documentation: Inform users about new theme options
Upgrading Themes
When adding new themes or updating existing ones:
- Maintain Backward Compatibility: Keep existing theme IDs unchanged
- Test Thoroughly: Verify all components work with new themes
- Update Registry: Add new themes to theme registry
- Document Changes: Update this documentation with new theme information
API Reference
Theme Loader Functions
// Load a specific theme
loadTheme(themeId: string): void
// Get current theme
getCurrentTheme(): string
// Save theme preference
saveTheme(themeId: string): void
// Clear theme preference
clearTheme(): void
// Initialize theme system
initializeTheme(): void
// Dark mode functions
toggleDarkMode(): void
setDarkMode(enabled: boolean): void
isDarkMode(): boolean
Theme Registry
interface Theme {
id: string;
name: string;
primary: string;
description?: string;
}
// Get all available themes
getAvailableThemes(): Theme[]
// Validate theme ID
isValidTheme(themeId: string): boolean
// Get theme by ID
getTheme(themeId: string): Theme | undefined
This comprehensive theme system provides a robust foundation for customizing the appearance of both your static site and admin interface, ensuring a consistent and professional look across your entire Antler application.