Dashboard
The engine includes a built-in development dashboard for inspecting process topology, run state, traces, and manual event emission.
It is intended for:
- development
- local operator visibility
- debugging workflows and retries
- inspecting deferred and dead-letter runs
It is not intended to be a production multi-user admin panel. There is no auth layer, tenancy model, or long-term analytics UI.
Enabling It
Add a server option when creating the engine:
import { createEngine } from '@yellatech/engine'
const engine = createEngine({
store: { type: 'sqlite', path: './app.db' },
server: { port: 3000 },
})
Then open:
http://127.0.0.1:3000
You can inspect the resolved server address with:
const server = await engine.getServer()
console.log(server?.address)
What It Shows
Overview
The Overview tab is the runtime summary page:
- current queue counts
- recent runs
- operator-facing statuses like
deferredanddead-letter - bucketed observability summaries and trends
This is the first place to answer:
- is work flowing?
- are retries increasing?
- is latency drifting up?
- are dead-letter runs appearing?
Processes
The Processes tab shows registered handlers and their event bindings.
If you declare emits, the dashboard can also render the static event graph that connects processes together.
Runs
The Runs tab is the operational browser for individual runs.
It supports:
- status filters
- root-only view
- paging
- direct drill-in to a run sidebar
The sidebar resolves the selected run, its root chain, and the current step detail in one server call, so operators can inspect the chain without the client walking parent runs itself.
Trace
The Trace tab renders a Gantt-style execution view for a run chain.
It is useful for:
- seeing which steps actually ran
- distinguishing execution time from paused/deferred time
- spotting long gaps between chained steps
Graph
The Graph tab renders the declared static workflow topology from emits.
Use it to confirm that your process graph matches the mental model you intended.
Emit
The Emit tab is a manual event launcher for testing:
- event name
- JSON payload
- optional idempotency key
This is useful when developing workflows without wiring a full upstream system first.
Live Updates
The dashboard uses a mix of:
- streamed lifecycle invalidation over
GET /events - bounded refresh intervals for heavier views
- bucketed observability endpoints for charts
That means the UI stays live without polling every endpoint constantly. The ticker at the bottom is fed directly from streamed engine lifecycle events.
Operator Status
The dashboard exposes both raw state and derived status.
That distinction matters:
completedstate withdeferredstatus means the step finished and intentionally paused the chainerroredstate withdead-letterstatus means retries were exhausted
The core engine state machine stays small, while the dashboard still exposes the operator-facing nuance.
HTTP Routes
The dashboard server exposes both the UI and its API surface:
| Route | Description |
|---|---|
GET / | Dashboard UI |
GET /health | Queue stats, uptime, registered processes |
GET /overview | Combined overview payload: health, recent runs, and optional observability summary. Supports ?limit=, ?root=true, and ?observabilityWindow=30m. |
GET /metrics | Engine queue snapshot and runtime totals |
GET /observability | Bucketed rollups for runs/effects over a time window. Supports ?window=, ?from=, ?to=, ?bucketMs=, and ?errorLimit=. |
GET /events | SSE stream of lightweight lifecycle invalidation events |
GET /runs | List runs with ?state=, ?status=, ?limit=, ?offset=, ?root=true |
GET /runs/:id | Single run detail |
GET /runs/:id/overlay | Bundled sidebar payload for the selected run, its root chain, and selected step effects |
GET /runs/:id/chain | Full causal chain from the specified run downward |
GET /runs/:id/trace | Gantt-style trace data with timing spans and gaps |
GET /runs/:id/effects | Durable effect records for a run |
POST /runs/:id/retry | Retry an errored run |
POST /runs/:id/requeue | Requeue a dead-letter run with a fresh retry budget |
POST /runs/:id/resume | Resume a deferred run chain, with an optional JSON body merged into the stored payload |
GET /graph | Static event-flow graph from emits declarations |
POST /emit | Emit an event with { event, payload, idempotencyKey? } |
Extending the Dashboard
The UI components are exported from @yellatech/engine/ui.
Packages like Conduit use the same shell and add their own tabs on top of the engine runtime views.
That means you can:
- reuse the existing shell
- add custom tabs
- keep the engine panels intact
- serve one combined dashboard from your own package
Development Workflow
# Terminal 1
npm run example
# Terminal 2
npm run dev:ui
The Vite dev server runs with HMR and proxies dashboard API calls back to the engine server.