Console Storybook
Browse production Console pages, components, and Agent workflows against an in-memory fixture. Previews contact no services and run no workloads. Use dummy credentials. To build or change a page, start with Console components and styles.
Run locally
From the repository root, with Node.js 24.22.1+ and the pinned pnpm version:
npm run storybook:installnpm run storybookOpen http://127.0.0.1:6006. Reset story discards the isolated fixture changes.
To build and serve a static copy:
npm run storybook:buildpython3 -m http.server 6006 --bind 127.0.0.1 \ --directory scripts/console-storybook/dist/siteServe at the origin root for absolute /console/ URLs. Build fingerprints keep
cached fixture pages and module imports current. The Console Storybook workflow
uploads a static artifact without publishing the documentation site. It needs
no provider secrets.
Write Console modules in TypeScript
Put browser code in .mts files and import the public .mjs path. TypeScript
resolves that import to the source file. pnpm typecheck checks it against browser
APIs and rejects syntax that needs more than type erasure.
Add the source path to the controller's allowlist in
apps/controller/src/console-assets.ts. The controller and Storybook both use
Node 24 to remove types, preserve line numbers, and serve JavaScript at the same
URL as before.
Node resolves imports literally, including imports inside an .mts file. Point
Node callers of a standalone module directly at its .mts source. The first-agent
CLI (scripts/first-agent.ts), model helper (scripts/first-agent-model.ts), and CI
smoke Agent checks (scripts/ci/first-agent-smoke/agents.ts) all import
agents/starter-model.mts directly.
Test browser behavior through the served .mjs URLs, where the controller
resolves the whole module graph.
Keep a temporary source forwarder such as dom.mjs only while a Node caller
still reaches that exact path. Renaming the caller alone leaves the import in
place. Remove the forwarder, then run those consumers and the browser tests to
verify both paths. A browser-only module needs no forwarder.
Appearance review
Use Pages/Agents → Populated to review the shared shell and controls at desktop (1440 × 1000), tablet (768 × 1024), and mobile (390 × 844). Check keyboard focus, search, navigation, an open dialog, and empty, loading, error, permission-denied, and missing-credential stories. The console stays light under either system appearance.
In Components/Native admin → Available on tablet, check that the 768px preview keeps the Agent name readable beside the visible sidebar. The title uses its own row below the back link and actions. Open Agent UI must still open the fixture. Compare Available at desktop and phone widths to check the surrounding layouts.
The Claw palette, type scale, and surface geometry reference
OpenClaw 6e8d06876fd166064abbec4928fb3bb109ebe999,
particularly src/styles/base.css, layout.css, and components.css.
OCE keeps its own navigation and workflows. Inputs have stronger borders than
the reference's decorative dividers so controls stay distinguishable. The
self-hosted Instrument Sans subset ships its SIL Open Font License beside it;
unsupported glyphs use the system fallback.
Compare before, after, mobile, and the walkthrough: simulated Storybook evidence, not live backend or deployment proof. The reference screen shows OpenClaw's disconnected gateway screen at the commit above.
Pages and components
Stories reach error states through real controls after loading fixture data.
| Group | Coverage |
|---|---|
| Sign in | Password, Google and OIDC sign-in, discovery failure, provider errors, disabled account, rejected login, expired session, delayed session status, failure and retry, unconfirmed logout. |
| Agents | Populated, empty, no matches, loading, inaccessible Namespaces, denied or failed reads; row Stop and Delete restrictions, refusals, uncertain outcomes. |
| Backends | Configured, empty, discovery failure, and access denied. |
| Namespaces | Creation, status cards, empty, denied, recovery. |
| Namespace Deletion | Confirmation, blockers, progress, denials, uncertain outcomes, and retry. |
| Secrets | Namespace listing, search, creation, masked values, consumers, replacement, deletion, missing values, readiness, denials, conflicts, and uncertain saves. |
| Model Provider | Shared Installation provider values and explicit Credential Source destination authorization. |
| Settings and navigation | Account, sign-out failure, unknown route. |
| Create Agent | Installed default, missing/loading/denied Presets, Preset variables, fixed model choices before credential entry and manual model IDs, OpenAI Codex/OpenClaw and Anthropic OpenClaw harnesses, Service Accounts switching and bound Presets, seeded workspace files, storage/grant denial, repository selection/discovery and rejected-grant recovery, invalid JSON, partial save/conflict, unknown save outcome. |
| Agent detail | First and later drafts, version details, native JSON and plugin editors, immutable plugin snapshot, queued/running/succeeded/failed activity, exact-version diagnostics, error and permission states. |
| Navigation components | Account menu, Namespace switcher, mobile drawer, admin link and denial, OCE branding, simulated OCC version, missing development metadata, debug runtime image identities and unavailable metadata. |
| Channels | Unconfigured cards, Slack editor with pairing/open/disabled policies, everyone and restricted channel sender access, incomplete sender access, unsupported mixed sender lists, unsupported wildcard channel maps, read-only snapshot, save conflict. |
| Credentials | Named Secret selection and creation, API-key and Slack Secret switching, denied metadata and grants, partially missing tokens, missing authentication, operator-managed credentials, issued ChatGPT account, model Secret replacement, pending grants, and unknown authentication saves. |
| Native admin | Available launch, stopped or unsupported runtime, denied panel hidden. The launch target is an explanatory fixture page. |
| Workspace | Four editable deployed files, undeployed Agent, denied reads, initial operate denial, a retained editor after an operate grant or revocation, missing file, unknown write outcome, rereads after a version change. |
| Stop Agent | Confirmation, stopped requested state, permission denial, unknown outcome requiring refresh. |
| Deletion | Confirmation, pending cleanup, permission denial, conflict, unknown outcome. |
Pending-read stories use the real client's 15-second timeout; reset them to replay loading.
In Pages → Create Agent → Repository-only Credential Proxy, check that the model-only Dedicated OpenClaw form permits creation without a repository selection. Choose Codex, select the repository, and turn off issue management under Customize access to use its approved access level.
Return navigation
Return while deployments load shows the rechecked Agents list first. Watch “Reading deployment…” become “Deployment access denied,” without the old result reappearing.
In Return to loaded pages, Return to Agent panels, and Slow rechecks, Back preserves search, expanded panels, and Credentials. Refresh reloads.
Namespace navigation and Agent flows
In Components → Navigation → Namespace switcher, switch Engineering/Research and check URL, collection, and Back behavior. Mobile Namespace selector checks long names and direct switching. In Mobile drawer, widen past 760px while open: Agents search must work without Escape. Shrink and check reopening and dismissal. In Compact drawer scroll position at 390×480, press Page Down and wheel over the overlay. Visit Namespaces and return with Back: Secrets keeps its heading and search in view. Escape and widening to desktop restore page scrolling. No-readable, unavailable, loading, and denied stories cover restrictions.
In Pages → Namespaces → Unavailable selection, check the warning's reason, recover inline, and check the URL, dismissed warning, unchanged page, and Back navigation. Unavailable selection mobile repeats this at 390px; Unavailable selection without access shows access guidance. Simulated examples: desktop, mobile, recovered, no access, walkthrough, desktop selector, mobile empty collection, Namespaces page, no selector, and a switching walkthrough.
Agent creation, editing, deployment, Stop, and Delete stories are in Console Storybook Agent workflows.
Create and deploy
Moved to Agent workflows.
Return to loaded pages
Moved to Agent workflows.
Keep edits while navigating
Moved to Agent workflows.
Choose and switch version Secrets
Moved to Agent workflows.
Inspect bound Secrets in versions
Moved to Agent workflows.
Discover and configure plugins
Moved to Agent workflows.
Update
Moved to Agent workflows.
Stop
Moved to Agent workflows.
Delete
Moved to Agent workflows.
Maintain coverage
In Pages/Settings → Nested Driver values, expand a Driver and switch between Fields and JSON. Confirm that nesting, arrays, empty values, and redaction stay intact and the open groups remain open. Scroll the long page to verify that the account control stays at the viewport bottom. Open its menu at both ends of the page, with Debug mode off and on. Repeat on a phone and open the navigation drawer; the page must not scroll horizontally.
When changing the Settings Driver access stories, build and serve the preview
and open each indexed story in a fresh browser context. Inspect the embedded
frame's story query and the fixture requests from its first load:
pages-settings--driver-configuration-deniedloadsstory=settingsDriverConfigurationsDenied. Permissions say the account cannot administer the Installation. Settings sends no Driver GET.pages-settings--driver-configuration-endpoint-refusedloadsstory=settingsDriverConfigurationsEndpointRefused. Permissions allow Installation administration. The first Driver GET returns 403, and the permissions recheck still allows administration. The Driver section shows the refusal without values.
In both stories, the Account and Session cards stay usable. Check the empty and unavailable stories as controls: a 200 with no configurations shows the empty message, and a 503 shows the read failure.
scripts/console-storybook/ installs from its own manifest and lockfile under the
seven-day release-age policy, independently of root dependencies.
prepare-assets.tsreads the public Console assets through the controller's asset reader, then versions the preview indist/assets/. Rebuild after source edits so the development server serves the new assets.public/scenarios.mtsassembles the story catalog and emits as/storybook-fixtures/scenarios.mjs; the asset builder keeps its versioned URL. Check local entries withsatisfies LocalScenario. Keep partial or invalid response fixtures explicit in their owning scenario types. Theme source IDs must name an authored entry; generated policy sources are checked before use. Preserve insertion order and shared fixture values when adding variants. Edit sign-in scenarios inpublic/scenario-groups/sign-in.mtsand Secrets scenarios inpublic/scenario-groups/secrets.mts. Edit Settings scenarios inpublic/scenario-groups/settings.mtsand Create Agent scenarios inpublic/scenario-groups/create-agent.mts. The asset builder publishes typed scenario groups as versioned.mjsmodules for the preview frames. Edit Credentials scenarios inpublic/scenario-groups/credentials.mts; the catalog keeps their three runs in their original positions. Edit Plugins component and Agent detail approver variant previews inpublic/scenario-groups/plugins.mts; shared plugin data stays inpublic/plugin-scenario-data.mts.public/fixtures.mtsintercepts API calls inside the preview. Unconfigured requests report an error and return 501, never reaching a server. Preview CSP also blocks network connections. Authentication and authorization responses are examples, not a security implementation. Its typedpublic/configuration-store.mtsowns Configuration persistence;public/create-agent-routes.mtsowns Create and provisioning job routes.public/preset-fixture.mtsprepares Preset variants, andpublic/network-policy-fixture.mtsowns simulated policy saves and application polls. The router emits as/storybook-fixtures/fixtures.mjs. It checks the names and policy fields it consumes before changing fixture state and returns400 INVALID_REQUESTfor malformed writes or validation request envelopes. Network validation returns HTTP 200 withdata.success: falseand field details for malformed additions inside a valid envelope. Authored rules and scenario refusals run first. IAM payloads and unused registration fields remain opaque.public/frame.mtsstarts the production console and opens configured controls. The asset builder emits it as/storybook-fixtures/frame.mjswith an asset version in the URL.- Edit Namespace scenarios in
public/scenario-groups/namespaces.mts. Imports within Storybook'spublic/fixture source use the.mtspath for a typed fixture. Asset preparation rewrites those imports to versioned.mjsURLs. When defining actions in a typed scenario group, import theStoryActiontype fromscripts/console-storybook/story-action.mts. *.stories.tsexports named stories by group.story.tsadds instructions, UI-gap notices, the preview, and Reset story. The repository'spnpm typecheckchecks these files without installing the separate Storybook dependencies.
Update scenarios and instructions with console changes, exporting new scenarios from their owning story file. Configure API responses; the console owns failure messages and UI markup.
Debug image walkthrough
Open Pages / Navigation / Debug runtime images, expand an Agent, and inspect the gateway image reference, digest, Enterprise source commit, and upstream OpenClaw commit. The sidecar has unknown provenance for both commits. Navigate to Namespaces, confirm diagnostics stay enabled, and repeat in the mobile drawer. In Pages / Settings / Account, turn Debug mode on and off. Debug mode enabled starts with the saved preference enabled; Browser storage unavailable shows a refused save without enabling diagnostics. Use the live Console to verify that the preference survives a reload; each Storybook frame starts with its scenario's preference. Debug metadata unavailable covers a failed read; ordinary navigation stories hide diagnostics. Docker image inspection and the Kubernetes API/worker integration suite, not these fixtures, verify Driver behavior.
Slack reply and DM policy checks
In Components/Channels → Slack Threaded Default, save a new
channel-only setup with DMs disabled and inspect its native Configuration.
Slack Reply Override must preserve an existing replyToMode: "off".
In Slack Dm Policy, trigger an empty Allowlist error, save explicit DM
sender IDs, then switch through Open, Disabled, and Pairing. Reopen the editor
after saving: channel senders stay unchanged. Slack Enterprise Dm
shows organization-wide policy restrictions. Missing-credential, read-only, and
save-failure stories cover surrounding states. Capture final interactions and
native values outside the repository; attach screenshots and video to the task
and PR.
For policy-denial states and the reviewed-addition walkthrough, follow the Agent policy storyboard.
