# Dashboard layout > Part of [Web UI](README.md). See also: > [Shape (shared)](shape.md) · [Per-agent page](agent.md) This page covers the per-hive UI that hive-c0re serves. Swarm-wide surfaces — the agent roster, agent creation, linking external forge and matrix accounts, the controller's job graph — are on the [swarm UI](../swarm/ui.md). hive-c0re serves the dashboard at `/dashboard.html` (with the home page at `/`). It has a fixed chrome header at the top and a `
` that shows exactly one tab pane at a time. The URL hash (`#swarm`, `#rebuild`, `#meta`, `#buildlogs`, `#permissions`) drives which pane is active; hash changes don't reload the page. FL0W and the other standalone pages are reachable from the H0M3 hub at `/`, not from the dashboard tab strip. **Chrome header** (fixed, overlays the active tab pane): - **← home back-link**: top-left of the chrome, links to the H0M3 hub at `/`. Every surface links back to the hub rather than to each other. - **Tab strip**: `◆ SW4RM ◆`, `◆ R3BU1LD QU3U3 ◆`, `◆ M3T4 1NPUTS ◆`, `◆ BUILD L0GS ◆`, `◆ P3RM1SS10NS ◆`. In-page tabs only — the SYST3M panels live on the standalone **C0R3** page (`/core.html`), and FL0W / ST4TS live on their own pages too, all reachable from the H0M3 hub (not the tab strip). Count pills on SW4RM (stale containers) and R3BU1LD QU3U3 (rebuilds in flight). - **Banner-thin** (`░▒▓█▓▒░ HYPERHIVE / HIVE-C0RE / WE ARE THE WIRED ░▒▓█▓▒░`) — sits below the tab strip. - **Server-warnings banner** — a generic, sticky top-of-page strip shown on **every** page (dashboard + every stand-alone page — FL0W, H0M3, C0R3, ST4TS), injected at the top of `` by `renderServerWarnings` in `common.js`. Driven by `state.server_warnings` — a list of `{ kind, level, message }` — and coloured by `level` (`warn` amber / `crit` red). hive-c0re owns the threshold + message, so adding a new system warning needs no frontend change. Warnings are a push-based registry (`hive-c0re`'s `warnings.rs`): any subsystem raises/clears its own entry via an RAII guard, and `host_stats::server_warnings()` is just a cheap snapshot of that registry. Producers today include the host disk-pressure check (a `statvfs` probe of `/nix`: ≥85% used → `warn`, ≥95% → `crit`, e.g. `⚠ host nix store N% full (G GiB free) — garbage-collect …`), forge provisioning/CI-runner boot failures, and an agent-state warning (`pending_logins`) computed alongside the container snapshot. A container crash used to have a sibling `agents_crashing` entry here — removed in favour of a swarm-level grafana alert on the crash watcher's own log line (`docs/scheduler/observability.md`), so a hive with no otel export now has no operator-visible crash signal at all. Hidden when there are no warnings. - **Browser tab title** — `hyperhive // h1ve-c0re` by default; updated to ` / // h1ve-c0re` once `hive_name` / `swarm_name` arrive in the state snapshot. The FL0W page uses a slim header (a `← home` back-link + the page title) rather than the dashboard tab strip — it's a standalone surface, not a tab pane. ## SW4RM tab **C0NTAINERS** — live containers as a flat list, one row per container, sorted alphabetically by agent name; every container the rescan reports gets a row. Pulsing red banner at the top of this section if any two sub-agents hash to the same port (`port_conflicts` from `/api/state`): the operator must rename one of them and rebuild. `lifecycle::{spawn,rebuild}` also preflight this and refuse with a clear error message naming the conflicting agent. `↻ UPD4TE 4LL` button appears above the containers list when any agent is stale. ## C0R3 page (`/core.html`) Passive / rare-interaction state, reached from the **Core** tile on the H0M3 hub (served at `/core.html`), with minimal chrome: a `← home` back-link and a single pane, **K3PT ST4T3**. The page is its own esbuild bundle (`core.js`) that cold-loads `/api/state` and subscribes to `/api/dashboard/stream` for `tombstones_changed`, `capabilities_changed`, and `tool_groups_changed` (the latter two re-render the stale-perms sub-section when permission data changes). (Rebuild queue and meta inputs are dashboard tabs — see below.) Per-container CPU, memory and disk load isn't shown in the hive UI. The same figures go out as OTEL metrics and appear in Grafana (see [observability](../scheduler/observability.md)). An agent's CPU and memory caps live per agent in the swarm UI. **K3PT ST4T3** — two sub-sections on one pane: *Tombstones*: agents with kept state and **no container** (size + age + claude-creds badge). One action: `PURG3` (wipes state + applied dirs; `POST /api/purge-tombstone/{name}`). ⚠️ **Not only *destroyed* agents.** Nothing records a destroy: `Provision` writes every definition-side artifact (state subvolume, proposed + applied repos, meta registration, topology entry) *before* the container exists, and that artifact set survives `lifecycle::destroy`. An agent part-way through a spawn is byte-identical on disk to a tombstone, and the pane lists both. The pane carries a standing warning to that effect, and the row badge says `offline` rather than `destroyed` — the absence of a container is all hive-c0re can actually prove. Fixing it properly needs a recorded destroy — **deferred** to the swarm-controller / snapshot-storage rework where the problem changes shape. *Stale permission entries*: agents with explicit capability or tool-group JSON entries but no live container — typically renamed or deleted agents whose entries persisted in `capabilities.json` / `tool-groups.json`. Loaded when the page opens; autorefreshes on `capabilities_changed` + `tool_groups_changed` SSE events. Each ghost agent gets a `✕ clear perms` button (`DELETE /api/permissions/{name}`). ## Build tabs (`#rebuild`, `#meta`, `#buildlogs`) The build lifecycle — rebuild queue, live build log, meta inputs, and build log history — is three tabs of the dashboard: **R3BU1LD QU3U3** (`#rebuild`), **M3T4 1NPUTS** (`#meta`) and **BUILD L0GS** (`#buildlogs`). They live in `builds.js`, which `tabs.js` imports: the dashboard's one tab strip, `/api/state` snapshot and `/api/dashboard/stream` subscription serve them, with `rebuild_queue_changed`, `meta_inputs_changed` and `meta_update_running` on the stream alongside the dashboard's other kinds. The count pill on R3BU1LD QU3U3 is the number of rebuilds in flight. The SW4RM tab does **not** read the graph endpoint, by design — the swarm view stays independent of job-queue internals. Its per-agent pending badges are transient-only, and its queue-summary banner reads the much narrower `GET /api/jobq/rollup` instead (see Container row, below) — a handful of pre-tallied counts, not the graph. The banner's "view queue →" link goes to the `#rebuild` tab. **R3BU1LD QU3U3** — pending, in-flight, and recently settled container operations: rebuilds, meta-update cascades, and first-spawns. One operation runs at a time; the worker drains FIFO. **Is a mounted `JobqGraph`** (the shared generic graph-viewer Preact component, `@hive/shared/jobq-graph.js` — the same one swarm-ui uses) — `builds.js` doesn't render the queue itself; it just mounts the component (`mountJobqGraph(container, props)`, since this page has no JSX pipeline) with an `onUpdate` callback to drive the two things below it that the generic view doesn't show. The component owns fetching, cold and live: `GET /api/jobq/graph` on mount, and a refetch via the mount handle's `.refresh()` on every `rebuild_queue_changed` SSE tick (that event is a bare `{ seq }` trigger carrying no queue payload; both dashboard pages treat the tick as a pure refetch trigger). Each row is one root graph node (`parent: null`); a multi-step op's per-agent subgraphs and sub-steps render as nodes within that one entry (structural `parent` edges define the tree; sibling order is array order, unchanged from the wire). A row shows a state glyph (`⏸` pending / `▶` running / `◐` finishing — own work done, a sub-node still running / `✔` done / `✖` failed / `⊘` cancelled / `·` skipped) and each step's own label/agent. A `Node`-kind dep on a sibling shows as a plain "waits on: `