> Section: [8. Observing it](https://jaque.sh/docs/ui/dashboard.md)
> Next: ui/panels
> Index: https://jaque.sh/llms.txt


The dashboard is a small single-page application compiled into the jaque
binary and served from the same `-listen` address as the command API and
`/metrics`. It reads projections through the query service and submits
commands through the command service; it holds no state of its own beyond
an optional API token in the browser. It exists so that knowing what
jaque knows never requires a second deployment, and its cost is a poll:
every page refreshes by calling `ListStatus` every 5 seconds, so what is
shown is at most 5 seconds behind the event log.

Status: there is no push channel; live updates are on the roadmap, and
until then the 5-second poll is the freshness bound. The dashboard does
not authenticate users; see section 9 and the
[status page](https://jaque.sh/docs/project/status.md).

## 1. Embedded, not a separate service

The assets are compiled into the binary and served directly by it: no
node process, no separate deploy, no version to keep in sync with the
engine. One flag, `-listen`, turns the dashboard, the command API and
`/metrics` on or off together. Navigation is hash-based (`#/overview`,
`#/hosts`, ...), so every view is a URL and a reverse proxy needs no
rewrite rules.

The dashboard follows the operating system's color scheme by default:
paper in light mode, graphite in dark mode. A toolbar switch can
override this; see Theme below. The five state colors are the same ones
the documentation uses, and a state is always shown as its color and its
word, so a screenshot keeps its meaning without the color.

## 2. Overview (`#/overview`)

The landing page. Two rows of state tiles, one for hosts and one for
services, counting total, ok, warning, critical, unknown and pending;
each tile links to the unfiltered `#/hosts` or `#/services`. Below them
two tables: Unhandled problems, with no acknowledgement and no active
downtime, always visible; and Handled problems, acknowledged or in
downtime, inside a disclosure that is closed by default. What needs
attention is not buried under what is already being handled.

## 3. Hosts and services (`#/hosts`, `#/services`)

The full object table: name, state with its SOFT, FLAPPING and
UNREACHABLE qualifiers, output, last change, and an acknowledgement and
downtime glance. Everything is shown by default; a "Problems only" toggle
filters and sorts by severity without changing what no filter means.

A selector box above the table takes the same
[label selector](https://jaque.sh/docs/config/labels-and-views.md) grammar used everywhere
else (`env=prod, team=redes`). Applying it writes the selector into the
URL as a query parameter (`#/hosts?sel=env%3Dprod`), so a filtered table
is a shareable link and each apply is its own history entry that the
browser's back button undoes. A selector that fails to parse shows the
error under the box instead of silently showing the unfiltered table.

With a selector active, both pages show a Bulk actions panel that
acknowledges or schedules downtime against every matching object at
once. That is one command with a selector target, not one request per
row.

## 4. Object detail (`#/object/<host>`, `#/object/<host>/<service>`)

State, output, acknowledgement and downtime detail, and a timeline of
recent transitions from `ListHistory`. The timeline can be filtered by
the resulting status and by state type, and re-ordered oldest-first with
a toggle on the At column; times are shown in the browser's local time,
with the raw timestamp available as a tooltip. The acknowledgement and
downtime forms are the same ones the row-level panel uses. A host's
detail lists its services; a service's detail links back to its host, so
the reader can walk up one level without losing context.

## 5. Labels as navigation

Every row and every detail view shows the object's labels as clickable
chips. Clicking `key=value` navigates to `#/hosts` or `#/services` with
that pair applied as a selector. It is the same mechanism as clicking a
group link from `#/groups`: a group in jaque is a selector, and a label
is a one-term selector.

## 6. History (`#/history`)

The global transition feed from `ListHistory`, newest first, 100 by
default. Filterable by host, by service once a host is set, and by limit;
the same 5-second poll as every other page, plus an explicit "Apply" for
filter changes so a half-typed filter does not fire. The timeline itself
can also be filtered by the resulting status and by state type, and
re-ordered oldest-first with a toggle on the At column; times are shown
in the browser's local time, with the raw timestamp available as a
tooltip.

## 7. Downtimes (`#/downtimes`)

Every scheduled downtime and every acknowledgement across all hosts and
services in one place, so reviewing or clearing them does not mean
visiting each object. Two tables: downtimes with a Delete button that
calls `DeleteDowntime`, and acknowledgements with a Remove button that
calls `RemoveAcknowledgement`. A "New downtime" form targets either one
object or a selector, without starting from a row.

## 8. Contacts and groups (`#/contacts`, `#/groups`)

`#/contacts` lists every configured contact with its type and labels.

`#/groups` has no native groups to show, because jaque has none: a group
is labels and selectors, not a first-class object (see
[Labels and views](https://jaque.sh/docs/config/labels-and-views.md)). The page shows the
saved views with name, selector, description and live member count, and a
table of every label seen across the fleet with its object count. Both
kinds of count link into `#/hosts` with that selector applied.

## 9. Settings and the API token

When jaque runs with `-api-token`, a "Settings" disclosure holds a token
field. The token is saved to the browser's `localStorage` and sent only as
`Authorization: Bearer` on command POSTs. Reads (`ListStatus` and the
rest of the query service) never require it, matching the API's own
posture described in
[Command and query service](https://jaque.sh/docs/api/command-and-query-service.md). There
are no cookies and no session.

## 10. Sinks

When at least one sink is configured, a "Sinks" disclosure next to
Settings lists every sink `ListSinks` reports: name, type, input
(`metrics` or `events`) and selector when one is set. It is read-only and
shows no runtime state; lag and write errors stay on `/metrics`, where a
collector can see them.

## 11. Security considerations

The dashboard is served on `-listen` with no authentication of its own.
`-api-token` protects commands, not reads: anyone who can reach the
listener can see every object, its output and its labels. The token lives
in the browser's `localStorage` in clear. Put the listener behind a
reverse proxy that terminates TLS and authenticates users, or bind it to
an address only that proxy can reach; see
[Security](https://jaque.sh/docs/deployment/security.md).

## Theme

The toolbar carries a three-state theme switch next to Problems only and
Settings: Auto, Light, Dark. Auto follows the operating system's color
preference; Light and Dark override it. The choice is stored in the
browser and applies immediately, charts included.

## Command palette

The palette opens with `/` or with Ctrl-K (Cmd-K on a Mac), and from the
"Search" button in the toolbar. Typing filters views, panels, and every host
and service the dashboard currently knows about; arrows move, Enter goes,
Escape closes.

What it lists comes from the same 5-second poll as the rest of the page, so
an object that appeared seconds ago may not be there yet. It also carries two
actions that have no page of their own: toggling Problems only, and cycling
the theme.
