Configuration, navigation, and extension

Enable the theme by placing newadmin before django.contrib.admin in INSTALLED_APPS. No special ModelAdmin or AdminSite is required.

Options and defaults

Option

Default

Purpose

SITE_TITLE

None

Browser title; inherits AdminSite.site_title

SITE_HEADER

None

Brand; inherits AdminSite.site_header

LOGO

None

Relative image path in staticfiles

DEFAULT_MODE

"auto"

light, dark, or auto; saved preference takes precedence

PALETTE

"sapphire"

Only supported palette in this alpha; customize tokens with CSS

MENU.ORDER

[]

Default native application order

MENU.ICONS

{}

Default icons for applications and models

MENU.LINKS

[]

Additional permission-checked links

CUSTOM_CSS

[]

Relative paths to extra stylesheets

DASHBOARD

None

Generic dashboard or importable provider path

SITES

{}

Overrides by AdminSite instance name

All options are optional. Example:

NEWADMIN = {
    "SITE_TITLE": "My studio",
    "SITE_HEADER": "Editorial administration",
    "LOGO": "branding/logo.svg",
    "DEFAULT_MODE": "auto",
    "MENU": {
        "ORDER": ["catalog", "auth"],
        "ICONS": {"catalog": "folder", "catalog.article": "file-text",
                  "catalog.category": "tag", "auth.user": "users"},
        "LINKS": [{"LABEL": "Reports", "URL_NAME": "reports:index",
                   "ICON": "chart", "PERMISSIONS": ["reports.view_report"]}],
    },
    "CUSTOM_CSS": ["branding/admin.css"],
}

catalog, article, category, and reports:index are examples. Use names from your own applications, models, and routes. Settings are validated by python manage.py check and when the theme resolves them.

Multiple AdminSite instances

SITES keys are AdminSite(name=...) instance names, regardless of the URL prefix where they are mounted:

from django.contrib.admin import AdminSite
from django.urls import path
from news.models import Article

operations = AdminSite(name="operations")
operations.register(Article)
urlpatterns = [path("operations/", operations.urls)]

NEWADMIN = {
    "SITE_HEADER": "Administration",
    "SITES": {"operations": {
        "SITE_HEADER": "Operations",
        "CUSTOM_CSS": ["branding/operations.css"],
        "MENU": {"ORDER": ["news"], "LINKS": []},
    }},
}

Mappings are merged recursively; lists are replaced in full. None keeps its meaning: for example, SITE_HEADER=None uses the AdminSite header and DASHBOARD=None keeps the generic dashboard. An unconfigured site inherits the global values. Each request gets independent options, and Django keeps the current site’s model registrations and permissions.

The light/dark/auto preference is shared by origin and browser, as in Django. Desktop sidebar collapse and filtering keep native storage. On mobile, the menu starts closed on every page and does not change the desktop preference. See accessibility and responsive behavior.

Custom CSS

LOGO and CUSTOM_CSS are relative staticfiles paths. External URLs, absolute paths, .. segments, backslashes, queries, and fragments are rejected. They work with collectstatic and manifest storage.

On standard templates, CUSTOM_CSS loads after theme styles, native page styles, and ModelAdmin.Media CSS. The --newadmin-* variables customize the appearance. For colors that map to Django’s native variables, define values on :root or html, for example:

html[data-theme="light"] {
  --newadmin-primary: #184c40;
  --newadmin-primary-hover: #123b31;
}

Also design the dark and automatic variants when changing colors that need them. Keep sufficient contrast for text, controls, and focus indicators.

Template blocks

Put overrides in a directory from TEMPLATES['DIRS'] or in an application installed before newadmin. Extend the same template name and use block.super to keep the theme’s content and resources:

{% extends "admin/base_site.html" %}
{% block newadmin_branding %}{{ block.super }}{% endblock %}
{% block newadmin_footer %}<p>Editorial team help</p>{% endblock %}
{% extends "admin/nav_sidebar.html" %}
{% block newadmin_sidebar_extra %}
  {{ block.super }}
  {# Project-specific content, with its permission checks. #}
{% endblock %}

newadmin_branding is inside the header brand, newadmin_sidebar_extra follows the applications and includes MENU.LINKS by default, and newadmin_footer is at the bottom of the document. The blocks receive the usual admin context. The footer is empty by default.

Native blocks (branding, extrastyle, responsive, extrahead, content, and others) remain available. Keep block.super when adding resources. Widgets, inlines, and ModelAdmin.Media keep Django’s native loading; the theme does not require replacements or install a rich-text editor. Complete consumer overrides and third-party integrations need their own visual review.

See dashboard.md for custom data panels.