Knowledge

Custom dashboards

A Custom dashboard is a per-workspace, per-user mosaic of DashboardWidgets that surfaces the metrics, lists, and alerts the user wants on their landing…

Last updated

Overview

A Custom dashboard is a per-workspace, per-user mosaic of DashboardWidgets that surfaces the metrics, lists, and alerts the user wants on their landing page. Dashboards live at /ws/{slug}/dashboards and the active dashboard renders as the workspace home (/ws/{slug}/).

The system ships with a per-role default layout so a freshly invited member always lands on a useful screen, and lets each user personalise from there. Widgets are arranged by drag-and-drop, persist per user, and are extensible via the plugin SDK.

Why it exists

Operators, approvers, owners, and viewers have wildly different "what do I need right now" needs. A change-heavy engineer wants the queue of in-flight CHGs, an incident commander wants the open-incident grid and the MTTR sparkline, an owner wants the executive summary and the DORA card. A single fixed homepage cannot serve all five roles; a fully blank customisable canvas overwhelms new users on day one. The CustomDashboard model splits the difference: opinionated defaults per role, full personalisation on top.

Key concepts

CustomDashboard

A CustomDashboard (CustomDashboard: workspace, owner (UserProfile), name, is_default, layout JSONField, created_at) holds the user-personalised dashboard for a single user. The layout JSON is an array of {widget_kind, widget_id, x, y, w, h, config} objects. Each user can have many dashboards but exactly one is_default=True per workspace, used as their homepage.

DashboardWidget registry

The DashboardWidget registry (WB.18) is the platform-side catalogue of every widget kind a dashboard can host. Each kind exposes:

  • kind — a stable identifier (open_changes, incident_grid, mttr_sparkline, etc.).
  • default_size{w, h} in grid units (12-column grid).
  • config_schema — JSON Schema for the widget's per-instance configuration (filters, time range, group-by).
  • render — the React component to mount.
  • data_loader — the React Query hook that fetches the widget's payload.

Six built-in widget kinds

The product ships with six widgets:

  1. Open changes queue — table of in-flight ChangeRequest rows, configurable filter and sort.
  2. Incident grid — colour-coded grid of open incidents by severity and status.
  3. DORA card — the four DORA metrics (deploy frequency, lead time, change-failure rate, MTTR) with a 7/30/90-day trend.
  4. MTTR sparkline — single-metric trend chart for mean-time-to-resolve.
  5. Recent activity — workspace-wide audit-log feed, filtered to the user's subscriptions.
  6. My approvals — pending ApprovalStep rows assigned to the user.

Additional widget kinds appear automatically when an installed plugin registers them via the SDK (see Plugin SDK below).

Per-role default layouts

When a user opens the workspace for the first time, the system materialises a default CustomDashboard from the role default:

  • Owner — DORA card + Recent activity + Open changes queue + My approvals.
  • Admin — Recent activity + Incident grid + Open changes queue + My approvals.
  • Approver — My approvals (large) + Open changes queue + Incident grid.
  • Engineer — Open changes queue + Incident grid + MTTR sparkline + My approvals.
  • Viewer — DORA card + Incident grid + Recent activity.

The defaults are seeded from apps/dashboards/defaults.py; admins can override the per-role default for the workspace by saving any dashboard as the "role default" from the action menu.

Drag-reorder via @dnd-kit

The layout editor uses @dnd-kit for keyboard-accessible drag-and-drop with collision detection. Drag a widget by its header to a new grid slot; release to commit. The grid auto-flows other widgets out of the way. Resize handles on each widget corner change w/h in the layout JSON. Edit mode is toggled per dashboard with a pencil icon — outside edit mode the dashboard is locked to prevent accidental drag.

Layout persistence

Layout changes are debounced (1 second) and persisted in two places:

  1. localStorage under vigilo_dashboard_layout_{workspace_slug}_{dashboard_id} for instant reload, even offline.
  2. Server via PATCH /api/v1/dashboards/{id}/ so the layout follows the user across browsers.

On load, the server payload always wins over local cache to avoid stale state after a cross-device edit.

Plugin SDK

Third-party widgets are added via the Plugin SDK: a plugin declares one or more widget kinds in its manifest.json, ships its React render component as an ESM bundle, and registers a data loader. Once the plugin is enabled on a workspace, the new widget kinds appear in the Add widget picker and can be added to any dashboard. See Platform plugins for SDK details.

Common workflows

Personalise the homepage

  1. Open the workspace; the role default dashboard renders.
  2. Click the Edit pencil in the top-right.
  3. Drag widgets to reorder, resize from the corner handles, or click Add widget to pick from the registry.
  4. Click Save (or wait for the 1-second debounce) to persist.

Add a new dashboard

  1. From /ws/{slug}/dashboards, click New dashboard, give it a name.
  2. Add widgets from the registry; configure each (filter, time range) via the widget's gear menu.
  3. Toggle Default to make this dashboard your homepage (replaces the previous default for your user).

Use a plugin widget

  1. Admin enables the plugin under Settings → Integrations → Plugins.
  2. The widget kind appears in the Add widget picker for all members of the workspace.
  3. Add it like any built-in widget.

Permissions

  • All roles can edit their own dashboards.
  • Admins / owners can override the per-role default layout for the workspace.
  • Owners can disable specific widget kinds workspace-wide (e.g., hide DORA card from viewers if the org doesn't want metrics in the viewer role).

Troubleshooting

Layout reverts on reload — The 1-second debounce was interrupted by a page navigation before the server persist completed. Wait a beat after the last drag before navigating, or click Save explicitly.

Plugin widget shows "Component failed to load" — The plugin bundle returned a 4xx or threw at mount. Open the browser console for the stack trace, and check Settings → Integrations → Plugins for plugin health.

Drag-and-drop doesn't work with the keyboard — Make sure you have Edit mode on. In edit mode, focus a widget and press space to pick it up, arrow keys to move, space again to drop. @dnd-kit honours prefers-reduced-motion.

Default layout changed without me asking — An admin updated the per-role default and your dashboard had is_role_default=True. Your customisations are preserved on any non-role-default dashboard.

Related