Web UI Explorer¶
The civicrm-py Web UI provides an interactive browser for exploring CiviCRM data and testing API queries. It integrates seamlessly with both Django and Litestar, offering a clean, responsive interface with light and dark theme support.
Overview¶
The Web UI includes three main features:
- Dashboard
A landing page with quick access to available entities and navigation links.
- Entity Browser
Browse, search, and paginate through CiviCRM entities. View individual records with all field values displayed in a readable format.
- API Playground
Execute live API queries with a form-based query builder. Select entities, choose actions, specify fields, and add where clauses. Results display as formatted JSON with query history tracking.
Both Django and Litestar integrations share the same Jinja2 templates, ensuring a consistent experience across frameworks.
Features¶
Theme Support: Light, dark, and auto (system preference) themes
Entity Browser: Grid view of entity types with pagination
Search: Filter entities by display name
Record Details: View all fields for individual records
API Playground: Interactive query builder with JSON results
Query History: Track recent queries in the playground
Authentication: Staff/admin authentication with debug bypass option
Responsive Design: Works on desktop and mobile devices
Django Integration¶
The Django Web UI uses class-based views with Jinja2 templating and integrates with Django’s authentication system.
Configuration¶
Create a WebUIConfig instance to customize the Web UI:
from civicrm_py.contrib.django.webui import WebUIConfig
webui_config = WebUIConfig(
title="CiviCRM Explorer", # Header title
theme="auto", # "light", "dark", or "auto"
enable_playground=True, # Show API playground
enable_entity_browser=True, # Show entity browser
enable_request_history=True, # Track query history
default_entities=[ # Entities shown in browser
"Contact",
"Activity",
"Contribution",
"Event",
],
items_per_page=25, # Pagination size
max_history_items=50, # Max history entries
require_staff=True, # Require staff login
login_url="/admin/login/", # Login redirect URL
debug=False, # Skip auth in debug mode
)
Configuration Options¶
Option |
Default |
Description |
|---|---|---|
|
“CiviCRM Explorer” |
Title displayed in the header |
|
“auto” |
Color theme: “light”, “dark”, or “auto” (follows system) |
|
True |
Show the API playground for testing queries |
|
True |
Show the entity browser for exploring data |
|
True |
Store and display query history in playground |
|
Contact, Activity, Contribution, Event |
Entity types to show by default in the browser |
|
25 |
Number of records per page in entity lists |
|
50 |
Maximum query history entries to keep |
|
True |
Require Django staff or superuser login |
|
“/admin/login/” |
URL to redirect unauthenticated users |
|
False |
Skip authentication with warning (never use in production) |
Template Setup¶
Add the shared templates directory to your Django settings:
# settings.py
from civicrm_py.contrib.django.webui import TEMPLATES_DIR
TEMPLATES = [
{
"BACKEND": "django.template.backends.jinja2.Jinja2",
"DIRS": [TEMPLATES_DIR],
"APP_DIRS": True,
"NAME": "webui_jinja2",
"OPTIONS": {
"environment": "your_app.jinja2.environment",
},
},
# Keep your existing Django template backend
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
# ...
},
]
URL Configuration¶
Include the Web UI URL patterns in your project:
# urls.py
from django.urls import include, path
from civicrm_py.contrib.django.webui import WebUIConfig, get_urlpatterns
webui_config = WebUIConfig(
title="My CiviCRM Explorer",
theme="auto",
)
urlpatterns = [
# ... your other URLs
path("explorer/", include(get_urlpatterns(webui_config))),
]
This registers the following URL patterns:
URL Pattern |
Name |
Description |
|---|---|---|
|
|
Main dashboard |
|
|
Entity type selection |
|
|
Entity list with pagination |
|
|
Single entity detail view |
|
|
API query playground |
|
|
Query execution endpoint (JSON) |
Views¶
The Django integration provides these class-based views:
WebUIIndexViewRenders the main dashboard with links to the entity browser and playground.
EntityBrowserViewDisplays a grid of available entity types for browsing.
EntityListViewShows a paginated, searchable list of entities with ID, display name, and timestamps.
EntityDetailViewDisplays all fields for a single entity record in a key-value table format.
PlaygroundViewRenders the interactive API query builder form.
PlaygroundExecuteViewHandles query execution and returns JSON responses.
All views use the StaffRequiredMixin which checks WebUIConfig.require_staff
and redirects unauthenticated users to the login page.
Authentication¶
By default, the Web UI requires Django staff or superuser access. The authentication flow works as follows:
User visits a Web UI page
If
require_staff=Trueand not in debug mode: - Check if user is authenticated - Check if user hasis_stafforis_superuser- Redirect tologin_urlif either check failsIf
debug=Trueor DjangoDEBUG=True: - Skip authentication with a warning logged to console
Warning
Never enable debug=True in production. The Web UI exposes CiviCRM data
that should only be accessible to authorized staff.
Litestar Integration¶
The Litestar Web UI uses async controllers with dependency injection for the CiviClient instance.
Configuration¶
Configure the Web UI through WebUIConfig:
from civicrm_py.contrib.litestar.webui import WebUIConfig
webui_config = WebUIConfig(
title="CiviCRM Explorer", # Header title
theme="auto", # "light", "dark", or "auto"
enable_playground=True, # Show API playground
enable_entity_browser=True, # Show entity browser
enable_request_history=True, # Track query history
default_entities=[ # Entities shown in browser
"Contact",
"Activity",
"Contribution",
"Event",
],
items_per_page=25, # Pagination size
max_history_items=50, # Max history entries
require_auth=True, # Require authentication
guards=None, # Custom Litestar guards
auth_exclude_paths=["/static"], # Paths to skip auth
debug=False, # Skip auth in debug mode
)
Configuration Options¶
Option |
Default |
Description |
|---|---|---|
|
“CiviCRM Explorer” |
Title displayed in the header |
|
“auto” |
Color theme: “light”, “dark”, or “auto” |
|
True |
Show the API playground |
|
True |
Show the entity browser |
|
True |
Track query history in playground |
|
Contact, Activity, Contribution, Event |
Entity types to show by default |
|
25 |
Records per page in entity lists |
|
50 |
Maximum query history entries |
|
True |
Require authentication for access |
|
None |
Custom Litestar guard functions |
|
[“/static”] |
Paths to exclude from authentication |
|
False |
Skip auth with warning (never use in production) |
Plugin Integration¶
Enable the Web UI through the CiviPlugin configuration:
from litestar import Litestar
from civicrm_py.contrib.litestar import CiviPlugin, CiviPluginConfig
from civicrm_py.contrib.litestar.webui import WebUIConfig
civi_config = CiviPluginConfig(
enable_webui=True,
webui_path="/explorer",
webui_config=WebUIConfig(
title="CiviCRM Explorer",
theme="auto",
),
)
app = Litestar(plugins=[CiviPlugin(civi_config)])
Manual Controller Setup¶
For more control, register the controllers directly:
from litestar import Litestar
from civicrm_py.contrib.litestar.webui import WebUIConfig, get_webui_controllers
from civicrm_py.contrib.litestar.webui.controllers import get_template_config
webui_config = WebUIConfig(title="My Explorer")
controllers = get_webui_controllers(webui_config, base_path="/explorer")
app = Litestar(
route_handlers=controllers,
template_config=get_template_config(),
)
Controllers¶
The Litestar integration provides these async controllers:
WebUIControllerHandles the main dashboard at the base path.
EntityBrowserControllerManages entity browsing with routes for listing entity types, viewing entity lists with pagination, and displaying entity details.
PlaygroundControllerProvides the interactive API playground with query execution.
All controllers receive the CiviClient through Litestar’s dependency injection
system, enabling async operations.
Custom Authentication¶
Provide custom guards for authentication:
from litestar.connection import ASGIConnection
from litestar.handlers import BaseRouteHandler
from litestar.exceptions import NotAuthorizedException
async def require_admin(
connection: ASGIConnection,
_: BaseRouteHandler,
) -> None:
"""Guard that requires admin access."""
user = connection.user
if not user or not getattr(user, "is_admin", False):
raise NotAuthorizedException("Admin access required")
webui_config = WebUIConfig(
require_auth=True,
guards=[require_admin],
)
Customization¶
Theme Customization¶
The Web UI supports three themes through the theme configuration option:
"light": Light background with dark text"dark": Dark background with light text"auto": Follows the user’s system preference usingprefers-color-scheme
The CSS uses CSS custom properties for theming:
:root {
--bg-primary: #f8fafc;
--bg-secondary: #ffffff;
--text-primary: #1e293b;
--text-secondary: #64748b;
--accent-color: #0ea5e9;
/* ... more variables */
}
[data-theme="dark"] {
--bg-primary: #0f172a;
--bg-secondary: #1e293b;
--text-primary: #f1f5f9;
--text-secondary: #94a3b8;
/* ... */
}
Entity Selection¶
Control which entities appear in the browser:
config = WebUIConfig(
default_entities=[
"Contact",
"Activity",
"Contribution",
"Event",
"Membership",
"Participant",
"Campaign",
],
)
Pagination¶
Adjust the number of items per page:
config = WebUIConfig(
items_per_page=50, # Show 50 records per page
)
UI Description¶
Dashboard¶
The dashboard displays:
A header with the configured title and navigation links
Cards for “Entity Browser” and “API Playground” with descriptions
A grid of quick-access buttons for default entity types
A quick reference section listing common API operations
Navigation includes links to Dashboard, Entities, and Playground, with the current page highlighted.
Entity Browser¶
The entity browser shows:
A grid of cards, one for each configured entity type
Each card links to the entity list view
Cards display the entity name with a “Browse records” subtitle
Entity List¶
The entity list provides:
A search input for filtering by display name
Record count showing “X of Y records”
A table with columns: ID, Display Name, Created, Modified, Actions
Pagination controls for navigating through results
A “View” button for each record linking to the detail view
Entity Detail¶
The entity detail view shows:
The entity type and ID in the header
A “Back to List” navigation button
A two-column table with field names and values
Special formatting for null, boolean, and nested object values
API Playground¶
The playground offers:
A two-column layout with Query Builder and Results
Entity dropdown populated with configured entity types
Action selector for “get” and “getFields” operations
Text input for comma-separated field selection
Textarea for JSON where clauses
Limit input with validation
Execute button to run queries
Results panel showing count and formatted JSON
Query history section tracking recent queries with timestamps
Security Considerations¶
The Web UI exposes CiviCRM data through a browser interface. Follow these security practices:
Always require authentication in production. Set
require_staff=True(Django) orrequire_auth=True(Litestar).Never enable debug mode in production. The
debug=Trueoption bypasses authentication entirely.Use HTTPS to protect data in transit.
Limit default entities to only those users should access.
Review Litestar guards to ensure they properly verify user permissions.
When debug mode is enabled with authentication required, the Web UI logs a prominent warning to the console:
WARNING: CiviCRM Web UI is running WITHOUT AUTHENTICATION
The Web UI is accessible without login because debug mode is enabled.
This exposes CiviCRM data to anyone with network access.
DO NOT USE IN PRODUCTION!
Comparison: Django vs Litestar¶
Authentication: Uses StaffRequiredMixin with is_staff/is_superuser checks
Client Access: Gets client from request via middleware or creates new SyncCiviClient
URL Generation: Uses Django’s reverse() function
Templates: Jinja2 backend with using="webui_jinja2"
from civicrm_py.contrib.django.webui import WebUIConfig, get_urlpatterns
urlpatterns = [
path("explorer/", include(get_urlpatterns(WebUIConfig()))),
]
Authentication: Uses Litestar guards (custom or built-in)
Client Access: Dependency injection provides async CiviClient
URL Generation: Path-based helper function with base_path
Templates: Standard Litestar TemplateConfig with Jinja2
from civicrm_py.contrib.litestar.webui import WebUIConfig, get_webui_controllers
controllers = get_webui_controllers(WebUIConfig(), base_path="/explorer")