Dashboard
The Dashboard is the per-module view — a grid of typed cards specific to whichever module you're in (CRM, Content, Analytics). Unlike Today (a daily feed of observations across modules), the Dashboard is the persistent operational view for one module at a time.
Module dashboards
Each module ships with a default dashboard layout. Examples:
| Module | Default cards |
|---|---|
| CRM | Pipeline by stage · Stuck deals · Recent wins · Top accounts by activity · Forecast vs commit |
| Content | Calendar (14-day) · Engagement by network · Recent posts · Drafts ready · Backlog |
| Analytics | KPI tracker · Custom queries · Cross-module rollups · Anomalies |
Cards are typed — the registry is the same one Today pulls from (see Today). The difference is selection: Today picks observation-flavored cards for the daily feed; Dashboard pins the operational cards for at-a-glance status.
Layout
3-column grid at desktop, single column on mobile. Each card is 2-3 rows tall depending on type. The layout is fixed per module in the default install but customizable per user (see below).
Custom dashboards
Beyond the default per-module dashboard, you can create custom dashboards mixing card types from any module. Useful for cross- functional views:
- "Customer health" — pulls cards from CRM (engagement) + Content (touch frequency) + Analytics (NPS trend).
- "Weekly leadership pack" — pipeline summary + content performance + KPI rollups, all on one screen.
Settings → Dashboards → New. Pick cards from any module, arrange, save. The custom dashboard appears in the left nav.
Card invalidation
When an underlying entity changes (a deal moves stage, a contact's email opens), affected cards regenerate. The mechanism:
- The entity write fires a Postgres trigger that mirrors into the knowledge graph (see Knowledge graph).
- The trigger emits a card-invalidation event tagged with the entity's node id.
- A worker consumer pulls the event and looks up which active
cards cited that node (via the
card_citationsindex). - Each affected card is enqueued for regeneration.
Card invalidation is async — the new card lands in the Dashboard within seconds, visible without a refresh thanks to the realtime subscription.
Card freshness
| Status | Meaning |
|---|---|
live | Current — generated within freshness threshold (default 12 h). |
regenerating | Underlying entity changed; new version in flight. Old version shown with a "regenerating" indicator. |
stale | Past freshness threshold without regeneration. Shown with a "tap to refresh" affordance. |
error | Last regeneration attempt failed. Error visible to admins; user sees a placeholder. |
The freshness threshold is configurable per card type. KPI cards might want to be fresh-within-hours; an "annual goal progress" card is fine refreshing daily.
Drill-in
Click any card → drill-in view. Shows:
- The full underlying query result (not just the summary).
- All citations expanded.
- A panel for asking the orchestrator about this specific card — "explain the stuck deals more" runs an inline agent turn with the card's context pre-loaded.
- Export-to-CSV for the row data, where applicable.
The drill-in agent inherits the standard four-namespace context plus a synthetic SKILL block describing "you are explaining dashboard card X — be specific about what you see in its data."
Per-user variants
Each user can:
- Reorder cards within a module dashboard (saved to their preferences).
- Hide cards they don't find useful.
- Pin a card to the top.
These are personal preferences; they don't affect other users in the tenant.
Tenant-wide customization
Admins can:
- Add/remove card types from each module's default dashboard.
- Adjust freshness thresholds per type.
- Disable card types entirely (also removes them from Today).
Settings → Dashboards → <Module>.
Realtime
The Dashboard subscribes to card-update events for the cards currently in view. Backgrounded tabs unsubscribe to avoid running up the realtime budget. When you come back, the subscription re-establishes and any updates from the gap apply at once.
Performance budget
Per-card regeneration:
- Same subagent pattern as Today cards.
- Typical p95 under 8 s end-to-end.
- Burst capacity bounded by the BullMQ worker concurrency (configurable per tenant on self-host; cloud sizes per plan tier).
If 50 cards invalidate at once (e.g. after a bulk import), they queue and process in priority order — pinned cards first, then by recency-of-cite.