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.

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 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 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 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 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). 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 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.

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.

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.