Web Dashboard
A bundled-in-CLI control-plane and Sui explorer web UI with live data over an in-process GraphQL server.
The dashboard() plugin serves a web UI — a control plane plus a Sui explorer — backed by an
in-process GraphQL server reading the stack's live projection. It's a normal stack member: add it
like any other plugin and the router fronts it under a stack-scoped hostname.
import { defineDevstack, sui, account, dashboard } from '@mysten-incubation/devstack';
export default defineDevstack({
members: [sui(), account('alice'), account('bob'), dashboard()],
stackName: 'main',
});Opening the UI
Like the wallet and other service endpoints, the dashboard is reached through a stable, stack-scoped
router hostname rather than its raw process port. The dashboard route uses the api role on its own
entrypoint port (9810), so the default-stack URL is:
http://api.<app>.localhost:9810Non-default stacks insert the stack segment: http://api.<stack>.<app>.localhost:9810. The plugin
also resolves to a direct loopback url (the broker-allocated port) for tooling that bypasses the
router, but the router-fronted hostname above is the one to open in a browser — it's what the
in-process CORS allowlist is keyed to.
What you can see and do
The dashboard is read-mostly, with a small set of guarded controls:
- Sui explorer — addresses, objects, packages, and transactions, with resolve-first search.
- Walrus & Seal panels — service status and live data for the storage and key-server plugins.
- Logs — the cross-service log store.
- Snapshot & restore progress — capture and restore narrated live, with each snapshot marked
current,stale, orunknownagainst the running stack's graph input id. - Controls — restart, shutdown, and advance-clock, each behind a confirmation.
- Faucet fund — a one-click fund action: SUI funds a fixed amount; WAL and DEEP take an editable amount. Funding reuses the same registered in-process funding strategies the boot-time account-funding pass dispatches through. See Faucet and Funding Strategies.
Options
All fields are optional.
port— preferred loopback port for the dashboard's HTTP/GraphQL server. The port broker forward-scans if it's busy.bindAddress— the NIC the server binds, default'0.0.0.0'. The router runs in Docker and must reach this host process through the host-gateway address on native Linux, so a127.0.0.1-only listener would be unreachable (and 502 through the router). The public URL stays router-fronted and stack-scoped regardless.allowedOrigins— extra CORS origins merged onto the stack-scoped allowlist, for headless test runners and custom dev hosts. This deliberately does not auto-allow a bare*.localhostform: that is not stack-scoped, so a sibling stack could otherwise drive the destructive control-plane mutations cross-origin.
The queryable cross-service log store the dashboard reads is owned by the supervisor, not this plugin. Tune its retention with environment variables:
DEVSTACK_DASHBOARD_LOG_CAPACITY— per-service record cap, default2000.DEVSTACK_DASHBOARD_LOG_MAX_SERVICES— distinct-service ring cap, default256.
Security
The dashboard's destructive control-plane mutations (restart, shutdown, advance-clock, fund) are
guarded by a stack-scoped CORS allowlist owned by the dashboard server itself. The allowlist
covers this stack's own router-fronted origin, the direct loopback origins, and any caller-supplied
allowedOrigins — but not a bare *.localhost. A sibling stack's origin therefore cannot drive
these mutations cross-origin.