Getting Started
Production-ready theming and 177+ components for Django. 12 design systems × 20 color presets = 240 unique theme combinations. No build step. No JavaScript framework.
What's Included
Step 1 — Install
$ pip install djust-theming djust-components # or with uv: $ uv add djust-theming djust-components
Requires Python 3.10+ and Django 4.0+. No Node.js, no npm, no bundler.
Step 2 — Configure
Add both packages to INSTALLED_APPS, include the URLs, and register the context processor:
INSTALLED_APPS = [ 'djust_theming', 'djust_components', ...existing apps... ] TEMPLATES = [{ ...existing config... 'OPTIONS': { 'context_processors': [ ...existing processors... 'djust_theming.context_processors.theme_context', ], }, }] LIVEVIEW_CONFIG = { 'theme': { 'preset': 'blue', 'default_mode': 'system', } }
from django.urls import path, include urlpatterns = [ ...your urls... path( 'theming/', include('djust_theming.urls'), ), ]
The URL include enables the /theming/gallery/,
/theming/gallery/storybook/, and
/theming/gallery/editor/ developer tools.
Step 3 — Add to Templates
Use {% theme_head %} in every page that needs theming.
It inlines critical CSS tokens and defers the rest — no flash of unstyled content.
{% load theme_tags djust_components %} <!DOCTYPE html> <html> <head> {% theme_head %} <!-- inlines tokens, defers components.css --> </head> <body> {% theme_switcher %} <!-- optional: light/dark + preset selector --> <!-- djust-theming template tags --> {% theme_button "Save" variant="primary" %} <!-- djust-components template tags --> {% alert variant="success" %}Done!{% endalert %} {% badge label="New" status="success" %} {% dj_button label="Submit" variant="primary" %} {% block content %}{% endblock %} </body> </html>
djust-theming tags
{% load theme_tags %}
theme_head— CSS tokens + anti-FOUC scripttheme_switcher— Mode + preset selector UItheme_mode_toggle— Light/dark/system toggletheme_preset_selector— Preset picker (dropdown or grid)theme_form— Instantly style any Django formtheme_button,theme_card,theme_alert, ...
djust-components tags
{% load djust_components %}
alert,badge,card,callout— Displaydj_button,dj_input,dj_select— Form controlsmodal,tabs,accordion,dropdown— Interactivedata_table,data_grid,stat_card— Data displaybar_chart,line_chart,sparkline— Charts- ...and 177 total
Automatic System Checks
djust-theming registers Django system checks that run at startup. Misconfigured presets, missing context processors, and WCAG contrast failures are caught before your first request.
| Check ID | Issue |
|---|---|
E001 |
Context processor not in TEMPLATES |
E002 |
Preset name doesn't exist |
E003 |
Design system name doesn't exist |
W001 |
Color pair fails WCAG AA contrast (4.5:1) |
$ python manage.py check System check identified no issues. # Silence a check after review: SILENCED_SYSTEM_CHECKS = [ 'djust_theming.W001' ]
JavaScript API
Available globally as window.djustTheme when {% theme_head %} is loaded.
// Change mode djustTheme.setMode('dark'); // light | dark | system djustTheme.toggle(); // toggle light ↔ dark // Change color preset djustTheme.setPreset('blue'); // any preset name // Query current state djustTheme.getMode(); // 'light' | 'dark' | 'system' djustTheme.getResolvedMode(); // always 'light' or 'dark' // Listen for changes window.addEventListener('djust-theme-changed', (e) => { console.log(e.detail.mode, e.detail.resolvedMode); });
Session persistence
Theme state is persisted in both localStorage (client-side)
and session (server-side). The server uses session values
for SSR, so the first render is always correct even without JavaScript.
Anti-FOUC protection
Critical CSS tokens are inlined in <style>,
component CSS is deferred via preload.
A small inline script applies the correct theme class before first paint —
no flash of light mode on a dark-mode session.
Developer Tools
Available in DEBUG=True or for is_staff users. Include the URLs to enable them.
Every component rendered with every variant, live. Fast visual reference.
/theming/gallery/
Per-component docs: API reference, variants, CSS variables, and source code.
/theming/gallery/storybook/
Tweak CSS tokens in real-time and export a tokens.css file.
/theming/gallery/editor/
Management Commands
# Scaffold a new theme python manage.py djust_theme create-theme my-brand --preset blue --design-system minimalist # List all presets python manage.py djust_theme list-presets # Export preset colors for Tailwind python manage.py djust_theme tailwind-config --preset blue --output tailwind.config.js # Import/export shadcn/ui themes python manage.py djust_theme shadcn-import my-theme.json python manage.py djust_theme shadcn-export --preset blue --output blue-theme.json # Validate a custom theme before publishing python manage.py djust_theme validate-theme my-brand python manage.py djust_theme check-compat my-brand