To use Mod with Django, you will want to decide how you want Mod's files loaded in your app. There are two options:
Global
This will load Mod's CSS and JavaScript globally in your app for all pages. If you're not an advanced Django developer, this is the recommended approach.
Global CSS and ESM JavaScript
This will load Mod's CSS globally and set up your JavaScript to load via ESM. This is recommended for advanced Django developers building a production-level app that want to reduce page size.
Using Global CSS and JavaScript
To start installing Mod in your app, first, you'll want to copy the required Mod files into your app. Use the table below to know where files should go:
Paths for Plus Users
If you've purchased a copy of Mod Plus, you will want to use the plus
file variants (e.g., mod-light-plus.min.css
) below.
Type | File in mod(-plus).zip | Target path in app | What is it? |
---|---|---|---|
File | mod-light(-plus).min.css | static/css/mod-light(-plus).min.css | The light-themed version of Mod. |
File | mod-dark(-plus).min.css | static/css/mod-dark(-plus).min.css | The dark-themed version of Mod. |
File | mod(-plus).iife.min.js | static/js/mod(-plus).iife.min.js | The IIFE version of the JavaScript for Mod's interactive components. Use this if you want to load Mod's JavaScript globally in your app. |
File | fonts/lucide.woff2 | static/fonts/lucide.woff2 | The icon font used by Mod, Lucide. |
File | fonts/mod-brand-icons.woff2 | static/fonts/mod-brand-icons.woff2 | The icon font for brand logos used by Mod. |
Important: the above paths assume that you have a publicly-loaded static folder at static/fonts. Ensure that your urls.py
includes a pattern for this so that Mod's icon fonts load properly:
urls.py
from django.urls import re_path
from django.conf import settings
urlpatterns = [
...other url patterns...
re_path(r'^fonts/(?P<path>.*)#39;, serve, {'document_root': settings.BASE_DIR / '<app_name>/static/fonts'}),
]
The above will ensure that the static/fonts
folder is properly routed to from your application's root (e.g., http://localhost:8000/fonts/lucide.woff2
).
Once you have the files copied over to your app (and if need be, urls.py
updated), next, you'll want to update your settings.py
file (relative to your project) to include an additional context processor to your TEMPLATES
array's OPTIONS
object for the theme
cookie that you'll use to handle theme toggling (see below):
<project>/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], # Empty since we're using app templates
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'<app_name>.context_processors.theme',
],
},
},
]
Above, you'll want to replace <app_name>
with the name of your Django app.
Next, you'll need to add the context processor for the theme
cookie to your app:
<app_name>/context_processors.py
def theme(request):
return {'theme': request.COOKIES.get('theme', 'light')}
With that in place, the last thing to update is your main HTML file at templates/base.html
:
templates/base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}My Site{% endblock %}</title>
<!-- Start Mod Includes -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/mod-'|add:theme|add:'(-plus).min.css' %}">
<script src="{% static 'js/mod-plus.iife.min.js' %}"></script>
<!-- End Mod Includes -->
</head>
<body data-mod-theme="{{ theme }}">
{% block content %}
{% endblock %}
</body>
</html>
Above, you'll want to be mindful of placement. Make note of the <!-- Start Mod Includes -->
and <!-- End Mod Includes -->
comments. All of the required includes for the files we copied over earlier are included here. This also includes the Google Fonts CDN links for Mod's font, Inter (optional and can be replaced with static assets in the app).
For theme switching, we pull in the theme
variable that we set up earlier via our context processor and first, using the |add
template filter, dynamically switch between our different Mod theme CSS files (we do this by using the filter inside of the URL for our CSS file). Remember, the theme
variable stores either the current value of the theme
cookie, or, the default light
.
On our HTML's <body>
tag, we're adding the data attribute data-mod-theme
and passing it a reference to the theme
variable we defined above.
data-mod-theme is required
Styles in Mod are theme-scoped using the data-mod-theme
attribute on your <body>
tag. If this is omitted, Mod's components will appear broken/unstyled.
With this, Mod should be loaded globally in your app. For pages with components that require JavaScript, calls to the specific component's JavaScript can be loaded directly in your template's HTML:
templates/test.html
{% extends 'base.html' %}
{% load static %}
{% block title %}Test Page{% endblock %}
{% block content %}
<div class="mod-command-palette">
<!-- HTML for command palette component -->
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
if (window.mod) {
window.mod.command_palette();
}
});
</script>
{% endblock %}
Above, we add a <script>
tag to our template and inside, add an event listener for the DOMContentLoaded
event. In that listener's callback, we check to see if the global window.mod
value is defined, and if it is, call to the JavaScript method to enable interaction for the component(s) on our page (here, we're using the Mod Plus Command Palette component).
Using Global CSS and ESM JavaScript
To start installing Mod in your app, first, you'll want to copy the required Mod files into your app. Use the table below to know where files should go:
Paths for Plus Users
If you've purchased a copy of Mod Plus, you will want to use the plus
file variants (e.g., mod-light-plus.min.css
) below.
Type | File in mod(-plus).zip | Target path in app | What is it? |
---|---|---|---|
File | mod-light(-plus).min.css | static/css/mod-light(-plus).min.css | The light-themed version of Mod. |
File | mod-dark(-plus).min.css | static/css/mod-dark(-plus).min.css | The dark-themed version of Mod. |
File | mod(-plus).esm.min.js | static/js/mod(-plus).esm.min.js | The ESM version of the JavaScript for Mod's interactive components. Use this if you want to load Mod's JavaScript incrementally in your app. |
File | fonts/lucide.woff2 | static/fonts/lucide.woff2 | The icon font used by Mod, Lucide. |
File | fonts/mod-brand-icons.woff2 | static/fonts/mod-brand-icons.woff2 | The icon font for brand logos used by Mod. |
Important: the above paths assume that you have a publicly-loaded static folder at static/fonts. Ensure that your urls.py
includes a pattern for this so that Mod's icon fonts load properly:
urls.py
from django.urls import re_path
from django.conf import settings
urlpatterns = [
...other url patterns...
re_path(r'^fonts/(?P<path>.*)#39;, serve, {'document_root': settings.BASE_DIR / '<app_name>/static/fonts'}),
]
The above will ensure that the static/fonts
folder is properly routed to from your application's root (e.g., http://localhost:8000/fonts/lucide.woff2
).
Once you have the files copied over to your app (and if need be, urls.py
updated), next, you'll want to update your settings.py
file (relative to your project) to include an additional context processor to your TEMPLATES
array's OPTIONS
object for the theme
cookie that you'll use to handle theme toggling (see below):
<project>/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [], # Empty since we're using app templates
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'<app_name>.context_processors.theme',
],
},
},
]
Above, you'll want to replace <app_name>
with the name of your Django app.
Next, you'll need to add the context processor for the theme
cookie to your app:
<app_name>/context_processors.py
def theme(request):
return {'theme': request.COOKIES.get('theme', 'light')}
With that in place, the last thing to update is your main HTML file at templates/base.html
:
templates/base.html
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}My Site{% endblock %}</title>
<!-- Start Mod Includes -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/mod-'|add:theme|add:'(-plus).min.css' %}">
<script type="module" src="{% static 'js/mod-plus.esm.min.js' %}"></script>
<!-- End Mod Includes -->
</head>
<body data-mod-theme="{{ theme }}">
{% block content %}
{% endblock %}
</body>
</html>
Above, you'll want to be mindful of placement. Make note of the <!-- Start Mod Includes -->
and <!-- End Mod Includes -->
comments. All of the required includes for the files we copied over earlier are included here. This also includes the Google Fonts CDN links for Mod's font, Inter (optional and can be replaced with static assets in the app).
To load Mod's JavaScript, we add the type
attribute to our <script>
tag and set it to module
so that the browser knows we're loading an ESM module.
For theme switching, we pull in the theme
variable that we set up earlier via our context processor and first, using the |add
template filter, dynamically switch between our different Mod theme CSS files (we do this by using the filter inside of the URL for our CSS file). Remember, the theme
variable stores either the current value of the theme
cookie, or, the default light
.
On our HTML's <body>
tag, we're adding the data attribute data-mod-theme
and passing it a reference to the theme
variable we defined above.
data-mod-theme is required
Styles in Mod are theme-scoped using the data-mod-theme
attribute on your <body>
tag. If this is omitted, Mod's components will appear broken/unstyled.
With this, Mod should be loaded globally in your app. For pages with components that require JavaScript, calls to the specific component's JavaScript can be loaded directly in your template's HTML:
templates/test.html
{% extends 'base.html' %}
{% load static %}
{% block title %}Test Page{% endblock %}
{% block content %}
<div class="mod-command-palette">
<!-- HTML for command palette component -->
</div>
<script type="module" src="{% static 'js/test.js' %}"></script>
{% endblock %}
Above, we add a <script>
tag to our template, importing another JavaScript file where our template's JavaScript will be called:
static/js/test.js
import { command_palette } from '/static/js/mod(-plus).esm.min.js';
command_palette();
Above, we import the JavaScript method for the Mod Plus command palette component and call it to enable the component's interactivity.