Production-ready theming system for Django — shadcn/ui inspired, reactive, Tailwind-ready, with component library
Project description
djust-theming
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.
Features
Design Systems & Color Presets
- 🎨 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
djust LiveView Integration (v0.2.0)
- 🔌 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
Tailwind CSS Support (v0.3.0)
- 🎨 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
shadcn/ui Compatibility (v0.4.0)
- 🔄 Import/Export shadcn theme JSON
- 🌐 100% compatible with themes.shadcn.com
- 📦 Round-trip import/export without data loss
- 🎨 Share themes with the shadcn community
Component Library (v0.5.0)
- 🧩 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
Powerful CLI (v0.6.0)
- 🚀 Quick setup with
djust-theme init - 🎨 Generate configs for Tailwind, shadcn, examples
- 📋 List presets, export colors, import themes
- 💡 Interactive with helpful error messages
What Makes djust-theming Different?
Design Systems Beyond Colors
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
Mix & Match Any Design System with Any Color
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!
Example Combinations
# 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',
}
}
Quick Start
Option 1: Try the Example App
The fastest way to see djust-theming in action:
cd example_project
pip install -r requirements.txt
pip install -e ..
python manage.py runserver
Visit http://localhost:8000 to explore all features interactively.
Option 2: Install in Your Project
pip install djust-theming
2. Configure
# 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,
}
}
3. Use in Templates
{% 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>
Or with Template Tags
{% 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>
Available Presets
| 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 |
Custom Presets
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_THEME
CSS Design System
The 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.
djust LiveView Integration
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_mode
In 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.
Tailwind CSS Integration
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.
Quick Start
# 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-config
Using Theme Colors in Tailwind
Once 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" />
Using @apply with Theme Colors
Generate CSS examples:
python manage.py djust_theme generate-examples --output theme-components.css
Then 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;
}
CLI Commands
# 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.css
Python API
from 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%)'
Available Theme Colors in Tailwind
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.
shadcn/ui Compatibility
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 shadcn Theme
# 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 to shadcn Format
# Export a djust preset to shadcn JSON format
python manage.py djust_theme shadcn-export --preset blue --output blue-theme.json
This JSON file can be:
- Uploaded to themes.shadcn.com
- Imported into other shadcn/ui projects
- Shared with the shadcn community
Python API
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')
Format Compatibility
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.)
Component Library
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.
Quick Start
{% 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" %}
Available Components
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) |
Styling
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)
Custom Styling
Add custom classes to any component:
{% theme_button "Submit" variant="primary" class="w-full mt-4" %}
{% theme_card title="Stats" class="shadow-lg" %}
Integration with Tailwind
Components work seamlessly with Tailwind classes:
{% theme_button "Click me" variant="primary" class="px-8 py-4 text-lg" %}
API
Python
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)
Template Tags
{% 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)
JavaScript
// 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);
});
Example Project
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.
Contributing
Contributions welcome! Please read CONTRIBUTING.md for guidelines.
Support
- 📖 Documentation
- 🐛 Issues
- 💬 Discussions
License
MIT License - see LICENSE file for details.
Copyright (c) 2026 djust contributors
Made with ❤️ by the djust community
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file djust_theming-0.3.0.tar.gz.
File metadata
- Download URL: djust_theming-0.3.0.tar.gz
- Upload date:
- Size: 102.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
214c417ec411fd98f73bc9e2ef8764f65b68462b14efd7208579ba00c7febaf1
|
|
| MD5 |
c894711a21de2ff355a74ac35191a900
|
|
| BLAKE2b-256 |
0b4fb28bb89be21c10dc5bebdcafb19cd2a60b05adbd9b0d15a99695c6bb7c0b
|
Provenance
The following attestation bundles were made for djust_theming-0.3.0.tar.gz:
Publisher:
publish.yml on djust-org/djust-theming
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
djust_theming-0.3.0.tar.gz -
Subject digest:
214c417ec411fd98f73bc9e2ef8764f65b68462b14efd7208579ba00c7febaf1 - Sigstore transparency entry: 985657799
- Sigstore integration time:
-
Permalink:
djust-org/djust-theming@eed43bae8766214ee5909445436458de3239ea19 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/djust-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eed43bae8766214ee5909445436458de3239ea19 -
Trigger Event:
release
-
Statement type:
File details
Details for the file djust_theming-0.3.0-py3-none-any.whl.
File metadata
- Download URL: djust_theming-0.3.0-py3-none-any.whl
- Upload date:
- Size: 105.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cf8a928bb6cb37df3a12c14aca7890d4fe218165cebc2a721a181cba27e542c
|
|
| MD5 |
05735b7db3d66da703988c278bd238f9
|
|
| BLAKE2b-256 |
ac3f42017107775d4ee9f8cce38b05a5c7365ec07b40364e0794c3cae85931c9
|
Provenance
The following attestation bundles were made for djust_theming-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on djust-org/djust-theming
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
djust_theming-0.3.0-py3-none-any.whl -
Subject digest:
5cf8a928bb6cb37df3a12c14aca7890d4fe218165cebc2a721a181cba27e542c - Sigstore transparency entry: 985657851
- Sigstore integration time:
-
Permalink:
djust-org/djust-theming@eed43bae8766214ee5909445436458de3239ea19 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/djust-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@eed43bae8766214ee5909445436458de3239ea19 -
Trigger Event:
release
-
Statement type: