A production-ready theming system for Django
shadcn/ui-inspired β’ Reactive β’ Tailwind-ready β’ Component Library
Quick Start β’ Features β’ Documentation β’ License
A shadcn/ui-inspired theming system for Django. Provides CSS custom properties-based theming with light/dark mode support, multiple color presets, and seamless Django template integration.
Works standalone with any Django project, or integrates deeply with djust LiveViews for reactive theme switching.
- π¨ 11 design systems: Material, iOS, Fluent, Minimalist, Playful, Corporate, Retro, Elegant, Neo-Brutalist, Organic, Dense
- π 19 color presets: Default, Shadcn, Blue, Green, Purple, Orange, Rose, Cyberpunk, Forest, Amber, Slate, Nebula, Natural 20, Catppuccin Mocha, RosΓ© Pine, Tokyo Night, Nord, Synthwave '84, Outrun
- π Mix & match: Combine any design system with any color preset (209 combinations)
- π― Complete control: Typography, spacing, shadows, animations, border radius, component styles
- π Light/Dark/System mode with anti-FOUC (Flash of Unstyled Content) protection
- π¦ Context processor for template variable injection
- πΎ Session + localStorage persistence
- πͺ Cookie-based preset for server-side rendering
- π LiveView mixin for reactive theme switching
- β‘ No page reload - instant theme changes via WebSocket
- π Server-side state sync - themes persist across sessions
- π― Compatible with djust-experimental
- π¨ Generate tailwind.config.js with theme CSS variables
- π― Use theme colors in Tailwind classes (
bg-primary,text-accent, etc.) - π @apply support for custom CSS components
- π Export colors in JSON/Python formats
- π Import/Export shadcn theme JSON
- π 100% compatible with themes.shadcn.com
- π¦ Round-trip import/export without data loss
- π¨ Share themes with the shadcn community
- π§© Ready-to-use components: Button, Card, Badge, Alert, Input
- π¨ Automatically themed - adapt to your preset and mode
- βΏ Accessible and responsive
- π Template tags for easy integration
- π Quick setup with
djust-theme init - π¨ Generate configs for Tailwind, shadcn, examples
- π List presets, export colors, import themes
- π‘ Interactive with helpful error messages
Most theming libraries only change colors. djust-theming provides complete design systems that control:
- Typography - Font families, sizes, weights, and line heights
- Spacing - Consistent spacing scales (tight, normal, loose)
- Border Radius - Sharp, rounded, or pill-shaped components
- Shadows - Flat, subtle, material, or elevated depth systems
- Animations - Motion behaviors (instant, snappy, smooth, bouncy)
- Component Styles - Button, card, and input variants
11 Design Systems:
- Material - Google's Material Design with elevation-based hierarchy
- iOS - Apple's design language with fluid animations
- Fluent - Microsoft's Fluent Design System with depth and motion
- Minimalist - Pure, distraction-free design with maximum content focus
- Playful - Fun, energetic design with bouncy animations
- Corporate - Professional, clean design for business applications
- Retro - Classic web aesthetic with pixel-perfect design
- Elegant - Premium design with serif fonts and generous spacing
- Neo-Brutalist - Bold, dramatic design with sharp edges and high contrast
- Organic - Soft, rounded design inspired by natural forms
- Dense - Compact, information-dense design for data-heavy interfaces
19 Color Presets: Default, Shadcn, Blue, Green, Purple, Orange, Rose, Cyberpunk, Forest, Amber, Slate, Nebula, Natural 20, Catppuccin Mocha, RosΓ© Pine, Tokyo Night, Nord, Synthwave '84, Outrun
= 209 Unique Combinations out of the box, or create your own!
# Material Design + Cyberpunk colors
LIVEVIEW_CONFIG = {
'theme': {
'theme': 'material',
'preset': 'cyberpunk',
}
}
# iOS + Forest green palette
LIVEVIEW_CONFIG = {
'theme': {
'theme': 'ios',
'preset': 'forest',
}
}
# Neo-Brutalist + Sunset oranges
LIVEVIEW_CONFIG = {
'theme': {
'theme': 'neo_brutalist',
'preset': 'sunset',
}
}The fastest way to see djust-theming in action:
cd example_project
pip install -r requirements.txt
pip install -e ..
python manage.py runserverVisit http://localhost:8000 to explore all features interactively.
pip install djust-theming# settings.py
INSTALLED_APPS = [
'djust_theming',
# ...
]
# urls.py
from django.urls import path, include
urlpatterns = [
# ...
path('theming/', include('djust_theming.urls')),
]
TEMPLATES = [{
# ...
'OPTIONS': {
'context_processors': [
# ... existing processors ...
'djust_theming.context_processors.theme_context',
],
},
}]
# Optional: customize defaults
LIVEVIEW_CONFIG = {
'theme': {
'theme': 'material', # Design system (material, ios, fluent, etc.)
'preset': 'blue', # Color preset
'default_mode': 'system', # light, dark, or system
'persist_in_session': True,
'enable_dark_mode': True,
}
}{% load static theme_tags %}
<!DOCTYPE html>
<html>
<head>
{% theme_head link_css=True %}
<link href="{% static 'djust_theming/css/base.css' %}" rel="stylesheet">
</head>
<body>
<nav class="navbar">
<div class="navbar-inner">
<span class="navbar-brand">My App</span>
{% theme_switcher %}
</div>
</nav>
<div class="main-area">
<div class="content-pane">
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
<p class="text-muted">Welcome!</p>
<button class="btn btn-primary">Get Started</button>
</div>
</div>
</div>
</div>
</body>
</html>{% load theme_tags static %}
<!DOCTYPE html>
<html>
<head>
{% theme_head %}
<link href="{% static 'djust_theming/css/base.css' %}" rel="stylesheet">
</head>
<body>
{% theme_switcher show_labels=False %}
{% theme_mode_toggle %}
{% theme_preset_selector layout="grid" %}
</body>
</html>| Preset | Use Case | Style |
|---|---|---|
default |
Neutral zinc β professional | Light/dark zinc |
shadcn |
shadcn/ui compatibility | Light/dark zinc |
blue |
Corporate, business apps | Blue |
green |
Finance, sustainability | Green |
purple |
Creative, premium apps | Purple |
orange |
Energetic, warm interfaces | Orange |
rose |
Modern, approachable | Rose/Pink |
cyberpunk |
High-tech, gaming | Neon cyan/magenta |
forest |
Nature, eco apps | Deep green |
amber |
Dashboards, terminals | Warm amber/gold |
slate |
Minimal, focus-first | Monochrome |
nebula |
Dark data-heavy apps | Deep space violet |
natural20 |
Developer tools, terminals | Bloomberg-inspired cyan |
catppuccin |
Developer editors | Soothing pastels (Mocha) |
rose_pine |
Elegant developer tools | Muted pine pastels |
tokyo_night |
Code editors | Vibrant Tokyo neon |
nord |
Arctic-inspired UIs | Cool blue/gray |
synthwave |
Retro, 80s aesthetic | Glowing pink/cyan |
outrun |
Retro racing aesthetic | Hot pink/purple sunset |
from djust_theming.presets import ThemePreset, ThemeTokens, ColorScale, THEME_PRESETS
MY_THEME = ThemePreset(
name="custom",
display_name="Custom",
description="My custom theme",
light=ThemeTokens(
background=ColorScale(0, 0, 100),
foreground=ColorScale(240, 10, 4),
primary=ColorScale(200, 80, 50),
primary_foreground=ColorScale(0, 0, 98),
# ... all other tokens
),
dark=ThemeTokens(
# ... dark mode tokens
),
)
# Register it
THEME_PRESETS["custom"] = MY_THEMEThe included base.css provides a complete design system:
- Layout:
.app-layout,.navbar,.sidebar,.content-pane,.container - Components:
.card,.btn,.badge,.alert,.modal,.toast,.empty-state,.stat-card - Forms:
.form-input,.form-select,.form-group,.form-label,.search-input - Tables:
.table,.table-hover,.table-responsive - Utilities: spacing (
.mt-4,.p-3), flex (.flex,.items-center), text (.text-sm,.font-bold), colors (.text-muted,.bg-muted) - Animations: fade, slide, shimmer skeleton, loading dots, toast transitions
All components use CSS custom properties from the theme, so they automatically adapt to any preset and light/dark mode.
NEW in v0.2.0: Reactive theme switching without page reload! π
from djust import LiveView
from djust_theming import ThemeMixin
class DashboardView(ThemeMixin, LiveView):
template_name = "dashboard.html"
def mount(self, request, **kwargs):
super().mount(request, **kwargs)
# Theme context is automatically available:
# self.theme_head, self.theme_switcher,
# self.theme_preset, self.theme_modeIn your template:
<!DOCTYPE html>
<html>
<head>
{{ theme_head }} <!-- Injects CSS + JS automatically -->
<link href="{% static 'djust_theming/css/base.css' %}" rel="stylesheet">
</head>
<body>
<!-- Theme switcher with reactive controls (uses dj-click/dj-change) -->
{{ theme_switcher }}
<!-- Your content here -->
</body>
</html>Features:
- β Theme variables injected into LiveView context via ThemeMixin
- β Reactive theme mode switching (light/dark/system) without page reload
- β Reactive preset switching with CSS hot-swapping (no reload needed!)
- β
Server-side state sync via WebSocket (
push_event) - β Works with djust v0.3+ (djust-experimental compatible)
How it works:
- User clicks theme switcher β sends
dj-clickevent to server - Server updates theme state and pushes CSS update via
push_event('theme_update', {...}) - Client receives WebSocket event and updates CSS + DOM instantly (no page reload!)
This provides a Phoenix LiveView-style reactive theming experience.
NEW in v0.3.0: First-class Tailwind CSS support! π¨
djust-theming now generates Tailwind configs that map to your theme's CSS variables, allowing you to use theme colors directly in Tailwind classes and @apply directives.
# Generate tailwind.config.js for your chosen preset
python manage.py djust_theme tailwind-config --preset blue --output tailwind.config.js
# Or use the default preset
python manage.py djust_theme tailwind-configOnce configured, use theme colors in your templates:
<!-- Use theme colors in Tailwind classes -->
<button class="bg-primary text-primary-foreground hover:bg-primary/90 px-4 py-2 rounded-md">
Primary Button
</button>
<div class="bg-card text-card-foreground border border-border rounded-lg p-6">
Card content
</div>
<input class="bg-background border-input focus:ring-ring focus:ring-2 rounded-md px-3 py-2" />Generate CSS examples:
python manage.py djust_theme generate-examples --output theme-components.cssThen use @apply in your CSS:
.btn-primary {
@apply bg-primary text-primary-foreground px-4 py-2 rounded-md;
@apply hover:opacity-90 transition-opacity;
}
.card {
@apply bg-card text-card-foreground rounded-lg border border-border;
@apply shadow-sm p-6;
}# Generate Tailwind config
python manage.py djust_theme tailwind-config [--preset PRESET] [--output FILE]
# Export colors in JSON/Python format
python manage.py djust_theme export-colors --preset blue --format json
# List available presets
python manage.py djust_theme list-presets
# Generate @apply examples
python manage.py djust_theme generate-examples --output theme.cssfrom djust_theming.tailwind import (
generate_tailwind_config,
export_preset_as_tailwind_colors,
generate_tailwind_apply_examples,
)
# Generate config programmatically
config = generate_tailwind_config(preset_name='blue', extend_colors=True)
with open('tailwind.config.js', 'w') as f:
f.write(config)
# Export colors as Python dict
colors = export_preset_as_tailwind_colors('blue')
print(colors['light-primary']) # 'hsl(221, 83%, 53%)'All theme colors are available as Tailwind utilities:
bg-primary,text-primary,border-primary, etc.bg-secondary,text-secondary, etc.bg-accent,bg-muted,bg-destructivebg-success,bg-warning(extensions)bg-card,bg-popover,bg-backgroundborder-border,border-inputring-ring(for focus states)
All colors support opacity modifiers: bg-primary/50, text-accent/80, etc.
NEW in v0.4.0: Import and export themes in shadcn/ui format! π
djust-theming is now fully compatible with shadcn/ui themes. Import themes from themes.shadcn.com or export your djust presets to share with the shadcn community.
# Import a shadcn theme JSON file
python manage.py djust_theme shadcn-import my-theme.json
# Import and register it in THEME_PRESETS
python manage.py djust_theme shadcn-import my-theme.json --register# Export a djust preset to shadcn JSON format
python manage.py djust_theme shadcn-export --preset blue --output blue-theme.jsonThis JSON file can be:
- Uploaded to themes.shadcn.com
- Imported into other shadcn/ui projects
- Shared with the shadcn community
from djust_theming.shadcn import (
import_shadcn_theme_from_file,
export_to_shadcn_format,
export_shadcn_theme_to_file,
)
# Import a shadcn theme
preset = import_shadcn_theme_from_file('custom-theme.json')
from djust_theming.presets import THEME_PRESETS
THEME_PRESETS[preset.name] = preset
# Export to shadcn format
theme_json = export_to_shadcn_format('blue')
print(theme_json['cssVars']['light']['primary']) # '221.2 83.2% 53.3%'
# Save to file
export_shadcn_theme_to_file('blue', 'blue-theme.json')djust-theming uses the same HSL-based CSS variable system as shadcn/ui, ensuring 100% compatibility:
- β All shadcn color tokens supported
- β Light and dark mode variants
- β Border radius configuration
- β Extension tokens (success, warning) preserved
- β Round-trip import/export without data loss
This means you can:
- Find a theme you like on themes.shadcn.com
- Download the JSON
- Import it into djust-theming
- Use it in your Django app with all djust features (reactive switching, Tailwind integration, etc.)
NEW in v0.5.0: Pre-built theme-aware components! π§©
djust-theming includes a library of ready-to-use components that automatically adapt to your theme and light/dark mode.
{% load theme_components %}
<!-- Button variants -->
{% theme_button "Save" variant="primary" %}
{% theme_button "Cancel" variant="secondary" %}
{% theme_button "Delete" variant="destructive" %}
<!-- Cards -->
{% theme_card title="User Profile" %}
<p>Profile content here</p>
{% end_theme_card %}
<!-- Badges -->
{% theme_badge "New" variant="success" %}
{% theme_badge "Beta" variant="secondary" %}
<!-- Alerts -->
{% theme_alert "Operation successful!" variant="success" dismissible=True %}
<!-- Inputs -->
{% theme_input "email" label="Email Address" placeholder="you@example.com" type="email" %}All components use theme CSS variables and automatically adapt to theme changes:
| Component | Variants | Usage |
|---|---|---|
theme_button |
primary, secondary, destructive, ghost, link | Buttons with consistent styling |
theme_card |
- | Card containers with header/body/footer |
theme_badge |
default, secondary, success, warning, destructive, outline | Small status indicators |
theme_alert |
default, success, warning, destructive | Alert messages with optional dismissal |
theme_input |
- | Form inputs with labels |
theme_icon |
check, x, alert, info | SVG icons (integrate your own icon library) |
All components are:
- β Fully themed with CSS variables
- β Automatically adapt to light/dark mode
- β Responsive and accessible
- β Customizable via additional classes
- β No JavaScript required (except dismissible alerts)
Add custom classes to any component:
{% theme_button "Submit" variant="primary" class="w-full mt-4" %}
{% theme_card title="Stats" class="shadow-lg" %}Components work seamlessly with Tailwind classes:
{% theme_button "Click me" variant="primary" class="px-8 py-4 text-lg" %}ThemeManager(request)β Manage theme state for a sessionThemeCSSGenerator(preset_name)β Generate CSS from tokensThemeSwitcher(theme_manager, config)β Render switcher componentThemeModeButton(theme_manager)β Simple toggle buttonPresetSelector(theme_manager, layout)β Preset selector (dropdown/grid/list)
{% theme_head %}β CSS variables + anti-FOUC script{% theme_css %}β CSS only (no scripts){% theme_switcher %}β Full switcher UI{% theme_mode_toggle %}β Light/dark toggle button{% theme_preset_selector layout="grid" %}β Preset picker{% theme_preset %}β Current preset name{% theme_mode %}β Current mode setting{% theme_resolved_mode %}β Resolved mode (always light/dark)
// Available globally as window.djustTheme
djustTheme.setMode('dark'); // 'light', 'dark', 'system'
djustTheme.toggle(); // Toggle light/dark
djustTheme.setPreset('blue'); // Change preset (triggers reload)
djustTheme.getMode(); // Current mode setting
djustTheme.getResolvedMode(); // Always 'light' or 'dark'
// Events
window.addEventListener('djust-theme-changed', (e) => {
console.log(e.detail.mode, e.detail.resolvedMode);
});A complete Django application demonstrating all features is included in the example_project/ directory.
Features:
- Homepage with feature overview
- Component library showcase
- Theme preset gallery
- Tailwind CSS integration examples
- Interactive theme switching
See example_project/README.md for setup instructions.
Contributions welcome! Please read CONTRIBUTING.md for guidelines.
- π Documentation
- π Issues
- π¬ Discussions
MIT License - see LICENSE file for details.
Copyright (c) 2026 djust contributors
Made with β€οΈ by the djust community