> 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. 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. Whether the
dashboard asks anyone to sign in depends on the config; see section 10
and the [status page](https://jaque.sh/docs/project/status.md).

## 1. Embedded in the binary

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 toolbar keeps Overview, Hosts, Services and Panels one
click away; History, Downtimes, Processes, Contacts, Groups and, for an
admin identity, Config sit behind a More menu beside them.

The Availability page, reached from the same More menu, lists SLOs
declared in config above its ad hoc per-object uptime table; see
[SLA](https://jaque.sh/docs/observability/sla.md) for what those numbers mean.

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, each counting in its own vocabulary: the hosts row counts
total, up, down, unreachable, warning, unknown and pending, and the
services row counts total, ok, warning, critical, unreachable, 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.

The problem tables deliberately mix every kind of object, worst first.
So that a row's kind is never in doubt, each one carries a small mark
before its name: a rectangle for a host, a rounded rectangle for a
service, a diamond for a business process, the same shapes the
[process tree](https://jaque.sh/docs/concepts/business-processes.md) draws. A problem process's
row links into the Processes view rather than a host page.

## 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, sorted by severity first.
Each page shows exactly its own kind: hosts never list business
processes, and the services table counts only services. Hosts speak
host vocabulary: UP, DOWN, UNREACHABLE, alongside WARNING and UNKNOWN
where a check reports them. Services keep OK, WARNING, CRITICAL,
UNKNOWN. The status word alone tells you what kind of row you are
reading. A host with no check of its own reads NO CHECK instead of PENDING.

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 instead of 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, by state type and by a time window taken from the same
picker the panels use, with "Last 5 minutes" one click away. It is
newest-first by default, 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. The Check section names the object's
check and notification periods when it has them. A Recheck now button
asks for the object's next check immediately; the result shows on the
next refresh. The row's
Comments section lists the object's comments and lets an operator add or
delete one; every reader sees the list. 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, by state type and by a time window, 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 From and To columns use the word of the object's own kind, so a host's
row reads UP and DOWN.

## 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`. The downtimes table carries a Kind column
naming which of the [four downtime kinds](https://jaque.sh/docs/config/downtimes.md) a row
is: `fixed`, `flexible (pending)` or `flexible (active)`, `triggered by
<downtime id>`, or `recurring <name>`. A "New downtime" form targets
either one object or a selector, without starting from a row; a Flexible
checkbox reveals a Duration (minutes) field that schedules a flexible
downtime instead of a fixed one. The acknowledgements table uses the same
word and the same color as the rest of the interface.

## 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 rather than 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. Config editor (`#/config`)

An admin-only view, reachable from the More menu once signed in with the
`admin` role. It loads the whole CUE document currently served from the
`-config` file and shows it in an editable text area, with a Validate and
an Apply button above it. Both call the matching admin RPC with the
buffer's current text; a rejection lists every diagnostic returned, and
clicking one moves the cursor to its line without leaving the page.
Success clears the diagnostics and shows a confirmation instead.

The view itself is absent, rather than shown disabled, for anyone signed
in below `admin`, for any session when `-auth-config` is not set, and
under `-read-only`.

## 10. Signing in

With no `-auth-config` the dashboard asks for nothing. Every page loads
and every command button works, which is what jaque has always done.

With `-auth-config` set it asks for a name and a password before
showing anything, and the toolbar then names who is signed in and
offers a Log out button. What a session may do follows its role:
`viewer` reads, `operator` also commands, so a viewer sees the same
pages with the command controls gone. The session is a signed cookie
the browser sends on its own; nothing is kept in `localStorage`. See
[Security](https://jaque.sh/docs/deployment/security.md) for where identities are
declared.

`-api-token` has no interface here. It is a credential for callers
outside the browser, and it cannot be combined with `-auth-config`:
jaque refuses to start with both. A binary running with `-api-token`
alone therefore serves a dashboard that reads fine and whose command
buttons will be refused.

With `-read-only` set, the dashboard shows no command controls at all,
regardless of role or whether `-auth-config` is set: acknowledge,
downtime and bulk-action buttons are simply absent rather than merely
disabled. See [Security](https://jaque.sh/docs/deployment/security.md).

## 11. Sinks

When at least one sink is configured, a Sinks section inside the
Settings disclosure 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.

## 12. Security considerations

With no `-auth-config`, the dashboard is served on `-listen` with no
authentication of its own, and `-api-token` protects commands rather than
reads: anyone who can reach the listener can see every object, its output
and its labels. Put the listener behind a reverse proxy that terminates
TLS and authenticates users, or bind it to an address only that proxy can
reach.

With `-auth-config` set, the page's own files are still served to
anyone, but every figure on it comes from the read API and the read API
asks for a session. There is still no TLS here: the cookie and the
password on the sign-in form travel in clear unless something in front
terminates TLS. See [Security](https://jaque.sh/docs/deployment/security.md).

## Theme

The toolbar carries a three-state theme toggle, an icon button next
to Settings: Auto, Light, Dark, with the current state named in the
button's tooltip. 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 one
action that has no page of its own: cycling the theme.
