kiwi-tcms-admin-overlay
A Kiwi TCMS plugin that overlays a sophisticated admin shell on top of Django's stock admin — dashboard, command palette, smart sidebar grouping, contextual badges, and live notifications — without modifying Kiwi TCMS or any other plugin.
Screenshots
The overlay layered on a real Kiwi TCMS install:
| Dashboard with categorised sidebar, hero, three cards (Quick stats / System health / Recent activity), and the plugin tile grid below | |
Same view zoomed on the cards — note the per-card monospace data, hairline grid, and the top-right ▤ ◐ ↻ action buttons |
|
Notifications bell dropdown — per-user activity stream with read markers and the Mark all action |
|
| Recent activity card with long Django content-type pills wrapping cleanly inside the column | |
Stock Django changelist restyled — mono uppercase headers, hairline rules, hover paper-sunken; the trailing column shows the per-row badges (e.g. 45 pass · 9 fail on TestRun) |
The full design preview is at docs/design-preview.html — open it in any browser to see every component at full fidelity, including the light/dark/system theme toggle, without spinning up Django.
Why
Kiwi's /admin/ is the stock Django admin (lightly skinned by Grappelli). Once several plugins are installed, the index becomes a flat alphabetic wall of model classes. There's no global search, no dashboard, no per-domain grouping, no contextual signal. This plugin enriches that experience without forking anything.
How it stays out of the way
- Pure additive. Composes the existing Django admin via response-rewriting middleware (the same pattern used by
kiwitcms-reviewandkiwitcms-requirements). NoAdminSitesubclass. No template inheritance fights with Grappelli. - No Kiwi changes. Drops in via the
kiwitcms.pluginsentry point. - Easily disabled. Set
KIWI_TCMS_ADMIN_OVERLAY = {"enabled": False}and the overlay deactivates without uninstall. - No rebranding. "Kiwi TCMS" wordmark is preserved everywhere, per upstream license.
What it adds
| Surface | Where | What |
|---|---|---|
| Console rail | top of every admin page | Brand mark + status line + theme/density/refresh actions |
| Dashboard | /admin/ |
Quick stats, system health, recent activity, plugin tiles |
| Sidebar | /admin/ |
Categorised model navigation grouped by domain |
| Command palette | anywhere via Cmd/Ctrl+K | Substring search across admin models, add-forms, recent objects |
| Row badges | every changelist | Per-row context like 45 pass · 9 fail on TestRun, severity pill on Bug |
| Notifications bell | topbar | Per-user activity stream with persistent read markers |
| Accessibility | everywhere | WCAG 2.1 AA contrast in light/dark; prefers-reduced-motion respected; full keyboard nav |
Compatibility
| Versions tested | |
|---|---|
| Django | 4.2 LTS, 5.0, 5.1, 5.2 |
| Python | 3.9, 3.10, 3.11, 3.12 |
| Kiwi TCMS | any release that loads plugins via kiwitcms.plugins entry point |
Install (development)
pip install -e /path/to/kiwi-tcms-admin-overlay
./manage.py migrate kiwi_tcms_admin_overlay
./manage.py runserver
Visit /admin/ — the new shell renders. Stock admin pages still work.
Configure
Every option is optional. Defaults shown:
# settings.py (or local_settings.py)
KIWI_TCMS_ADMIN_OVERLAY = {
"enabled": True,
"categories": None, # None → use defaults; list → replace
"category_overrides": {}, # surgical {"app_label": "category_key"}
"dashboard_cache_seconds": 30,
"notifications_poll_seconds": 60,
"show_uncategorised_warning": True,
"theme_default": "system", # light | dark | system
}
Extending — for plugin authors
Three registries are available; call them from your own AppConfig.ready():
from kiwi_tcms_admin_overlay import (
AdminCategory, register_category,
Badge, register_badge,
register_notification_source,
)
class MyPluginConfig(AppConfig):
def ready(self):
# Sidebar grouping
register_category(AdminCategory(
"my_domain", "My Domain", "fa-flask", 25,
("my_plugin_app",),
))
# Per-row changelist badges
def badge_provider(model, queryset):
return {row.pk: [Badge("active", "pass")] for row in queryset.filter(active=True)}
register_badge("my_plugin_app", "mything", badge_provider)
# Notification source for the bell
def notifs(request, limit):
for item in MyNotification.objects.filter(user=request.user)[:limit]:
yield {
"source": "my_plugin",
"key": str(item.pk),
"label": item.title,
"hint": "my_plugin.mything",
"verb": "needs review",
"actor": item.from_user.username,
"time": item.created_at.isoformat(),
"href": item.get_absolute_url(),
}
register_notification_source("my_plugin", notifs)
All registrations are app-startup-only; runtime mutation is rejected so per-user caches stay consistent.
Architecture
┌─────────────────────────────────────────────────────┐
│ Browser (admin page) │
│ ┌────────────────────────────────────────────────┐ │
│ │ overlay.css + shell.js + palette.js + │ │
│ │ badges.js + notifications.js │ │
│ └────────────────────────────────────────────────┘ │
│ ↕ │
│ /admin_overlay/api/{dashboard,health,sidebar,…}/ │
└─────────────────────────────────────────────────────┘
↕
┌─────────────────────────────────────────────────────┐
│ Django (your existing Kiwi install) │
│ • AdminOverlayMiddleware injects bundle into HTML │
│ • ModelAdmin permissions gate every endpoint │
│ • OverlayNotificationRead persists read markers │
└─────────────────────────────────────────────────────┘
Testing
make test # full pytest suite (107 tests at 0.1.0)
make test-a11y # contrast + accessibility-only (fast canary)
make lint # flake8 + pylint
The accessibility CI surface includes a contrast verifier that asserts every documented design-token pair meets WCAG AA in both light and dark mode. See docs/accessibility.md for the manual axe-core audit procedure.
Design preview
docs/design-preview.html is a single self-contained file demonstrating every UI component at full fidelity, with light/dark/system theme cycling. Open it in any browser without Django running.
Status
v0.1.0 — feature-complete, internal use only. PyPI publish on hold pending broader review.
License
GPL-2.0-or-later, matching Kiwi TCMS upstream.
Metadata
Release files for kiwi-tcms-admin-overlay 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kiwi_tcms_admin_overlay-0.1.0.tar.gz | 68.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 151.5 kB
Release files / kiwi_tcms_admin_overlay-0.1.0.tar.gz
| Download URL | kiwi_tcms_admin_overlay-0.1.0.tar.gz |
|---|---|
| Size | 68.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
72e7498b30ca238e38d7dfdfc3cf9c54c7f35726a1654db448b7236c453effa4
|
|
BLAKE2b-256 checksum How to use checksums |
083ae3d7c0a0a73a1004abe0885308d4a07fe871f38a3c7e678d192ee7a96c15
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|
Release files / kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl
| Download URL | kiwi_tcms_admin_overlay-0.1.0-py3-none-any.whl |
|---|---|
| Size | 83.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1326e6da1217b00e679e9d3a11c42e7f6a0415f733c4e86c50382a05b20084d4
|
|
BLAKE2b-256 checksum How to use checksums |
999c19f35e43fc6132754609ff5011ed4ed020802f9f32335934d81ab77d917e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.14
|