Admin Overlay
The Spotlight admin overlay is a suite of in-context tools that appear directly on your application when an authenticated admin user loads the page with the SDK installed. Admins can build tours, select elements, customize themes, view analytics, and edit content -- all without leaving the host application.
How It Works
When the SDK initializes, it performs a two-phase authentication check:
- API key validation -- the
X-API-Keyheader identifies the tenant. - JWT validation -- the
Authorization: Bearertoken is verified against the tenant's JWKS endpoint.
If the authenticated user is detected as an admin (via the tenant's configured admin strategy), the SDK injects the admin overlay toolbar into the page.
// The SDK automatically detects admin status after initialization
SpotlightSDK.init({
apiKey: 'sk_live_...',
// JWT is read from your existing auth system
getToken: () => authService.getAccessToken(),
});
// If the user has admin privileges, the toolbar appears automatically.Overlay Components
The admin overlay consists of five primary panels, each accessible from the floating toolbar:
| Component | Purpose | Shortcut |
|---|---|---|
| Tour Builder | Create and edit guided product tours | Ctrl+Shift+T |
| Element Selector | Target DOM elements with confidence scoring | Ctrl+Shift+E |
| Theme Builder | Customize colors, typography, and spacing | Ctrl+Shift+H |
| Analytics Panel | View completion rates and drop-off analysis | Ctrl+Shift+A |
| Inline Editor | Edit content titles, bodies, and CTAs in place | Ctrl+Shift+I |
Admin Detection
Admin status is determined by a pluggable strategy configured per tenant. The backend supports three strategies:
# Checks the Spotlight.Admin.Users DynamoDB table
# An entry with matching tenant_id + user_id = admin
strategy = TableLookupStrategy(client=dynamodb_client, settings=settings)
is_admin = await strategy.is_admin(tenant_id, user_id, jwt_claims)# Checks the JWT `permissions` array for a specific scope
# Works with Auth0 RBAC. Default scope: "spotlight:admin"
strategy = JwtPermissionStrategy(permission="spotlight:admin")
is_admin = await strategy.is_admin(tenant_id, user_id, jwt_claims)# Checks a custom JWT claim for an admin role value
# Supports both string claims ("role": "admin")
# and array claims ("roles": ["admin", "user"])
strategy = JwtRoleStrategy(claim_name="role", admin_value="admin")
is_admin = await strategy.is_admin(tenant_id, user_id, jwt_claims)Strategies can also be composed. The CompositeStrategy chains multiple strategies and returns True on the first match:
strategy = CompositeStrategy([
JwtPermissionStrategy(),
TableLookupStrategy(client, settings),
])Architecture
Host Application
+-----------------------------------------------------+
| |
| Your App UI |
| |
| +-----------------------------------------------+ |
| | Spotlight Admin Overlay (injected by SDK) | |
| | | |
| | [Toolbar] [Tour Builder] [Theme Builder] | |
| | [Element Selector] [Analytics] [Editor] | |
| +-----------------------------------------------+ |
| |
+-----------------------------------------------------+
| |
| SDK API calls | Admin API calls
v v
GET /v1/sdk/config POST /v1/admin/tours
POST /v1/sdk/events PUT /v1/admin/themes
POST /v1/sdk/progress GET /v1/admin/analyticsThe overlay communicates with two API surfaces:
- SDK endpoints (
/v1/sdk/*) -- for fetching configuration and recording user events. - Admin endpoints (
/v1/admin/*) -- for CRUD operations on tours, content, themes, audiences, and admin users. These endpoints require therequire_admindependency, which runs the tenant's admin detection strategy.
Audit Trail
Every admin action emits a domain event that is persisted to the Spotlight.Audit.AdminActions DynamoDB table via EventBridge. Events include before/after snapshots of the modified entity:
{
"event_type": "TourUpdatedByAdmin",
"category": "admin",
"tenant_id": "tenant_abc",
"source": "admin_api",
"data": {
"actor_id": "user_123",
"actor_email": "admin@example.com",
"entity_type": "tour",
"entity_id": "tour_456",
"operation": "update",
"before": { "title": "Old Title", "status": "draft" },
"after": { "title": "New Title", "status": "draft" }
}
}The audit table supports querying by actor (gsi-actor) and by entity (gsi-entity) for full change history.
Permissions Summary
| Action | Requires Admin | Audit Logged |
|---|---|---|
| View tour analytics | Yes | No |
| Create / edit tours | Yes | Yes |
| Publish / archive tours | Yes | Yes |
| Create / edit content | Yes | Yes |
| Manage themes | Yes | Yes |
| Manage admin users | Yes | Yes |
| Toggle circuit breakers | Yes | Yes |
| View SDK config | No | No |
| Record user events | No | No |