# The dashboard

2026-08-11

Phase 6. What a team looks at when they are not looking at one issue.

## 🚨 There is no dashboard framework, because there already is one

Convoro has widgets: a type registry, areas, per-group visibility, live
arranging, and drafts so an administrator can rearrange without publishing
half a page. Every one of those is a thing a "dashboard" would need.

So the tracker **registers widget types** and the dashboard is a widget area.
No second arranging interface, no second visibility model, no second place to
look when something does not appear.

This is the standing rule about building on the platform's own controls, and it
is the same argument that made the board use `.btn-primary` rather than invent
a pill. A dashboard framework beside the widget framework would be two answers
to one question, and the second one would be worse — it would not have drafts.

## What the tracker contributes

Five types, and each is a thing somebody actually asks:

- **Issue count** — a saved query and the number it returns
- **By status** — the open queue broken down, coloured by category
- **By priority** — the same, for what matters
- **Sprint burndown** — the running sprint's chart
- **Recent activity** — what changed, from the history

## 🚨 Every number is a link

A count on a dashboard that cannot be opened is a poster. The question a number
provokes is always *"which ones?"*, and a dashboard that cannot answer it sends
somebody to the search screen to rebuild the query by hand — at which point they
stop looking at the dashboard.

So every count links to the search that produced it, with the query in the URL.

## 🚨 Nothing here is computed that a page view cannot afford

A dashboard is the page somebody leaves open all day, so:

- **Counts are `COUNT(*)`**, not two hundred rows fetched and counted in PHP.
  The search service returns rows because a list needs rows; a dashboard needs
  a number, and those are different queries.
- **The burndown reads snapshots**, which were written by cron. Nothing
  recalculates a chart on a page load — see the sprint note for why it could not
  be correct even if it were affordable.
- **Velocity reads the numbers stamped at completion.** Same reason.

## 🚨 A count gadget cannot be cached across people

Its query may contain `me`, and `me` resolves against whoever is reading — that
was settled in the query-language note and it reaches here. A dashboard showing
one person's "assigned to me" count to everybody would be worse than showing
nothing, because it looks right.

Widget visibility is already per-group; this is per-*person*, which the widget
layer does not know about. Nothing caches today, and this note is what stops
somebody adding it without noticing.

## What this phase does not do

- **Cross-project dashboards.** A widget area is a place on a page; the tracker
  dashboard is a project's page. A dashboard over several projects wants the
  query language to be able to say "these projects", and it deliberately cannot.
- **Gadgets over arbitrary data.** Sales, sign-ups, storage — those belong to
  the modules that own them, registering their own types into the same registry.
  That is the whole point of using it.

## Not matched, deliberately

- **Jira's gadget library.** Dozens of them, most configured through a wizard.
  Five types that answer real questions, and a sixth when somebody asks for it.
- **Per-person dashboards.** A member arranging their own copy of a shared page
  is a much larger idea than it looks — it needs a per-person layout store — and
  the widget layer's drafts are for administrators arranging the shared one.
