Skip to content

feat(console): support deployment-wide theme bundles - #3048

Merged
freeqaz-openai merged 6 commits into
openclaw:mainfrom
russellb:plan/console-custom-theming
Oct 21, 2026
Merged

freeqaz-openai merged 6 commits into
openclaw:mainfrom
russellb:plan/console-custom-theming

Conversation

@russellb

@russellb russellb commented Oct 20, 2026 •

Copy link
Copy Markdown
Member

A deployment can now set the Console’s product name, logo, and colors without rebuilding the controller. Mount a small theme bundle into the API and restart it. Installations without a bundle keep the standard Console, including its 20-pixel navigation and 40-pixel sign-in logos.

The bundle is public deployment configuration. The files and directories that can replace them must be writable only by trusted deployment administrators. A read-only container mount does not prevent host-side or ConfigMap replacement. The API reads a bounded snapshot at startup, accepts named semantic colors and raster images, and refuses invalid configuration before listening. Requests cannot select filesystem paths, upload themes, or provide CSS or JavaScript. The chart mounts the ConfigMap read-only in the API and can roll the API when the bundle changes.

Verification

The images compare the bundled Console with the example theme on the same revision. The recording starts after sign-in in an isolated browser session, opens and dismisses the Create Secret dialog, then opens mobile navigation. It creates no Secret and contains no credentials. Tested source: 977d738, based on main 4f848ea. Environment: Linux, Node 24, local controller and sandboxed Chromium. The current navigation logo is 20 × 20 CSS pixels; the earlier 32 × 32 captures are historical.

Local controller and Chromium checks exercised sign-in, the computed primary color, Agent navigation, mobile navigation and sign-out. Six integration cases cover escaped branding, public asset boundaries, restart and isolation, malformed bundles, ConfigMap projections and the real API startup error. Helm rendering verified default-off and API-only placement. The nine Pages/Theming Storybook stories use the production loader with simulated page state.

The existing model-ui QA scenario now exercises a mounted theme. Secrets-only and non-browser QA do not incur a theme rollout. The new TypeScript integration test runs in the existing typecheck lane; the ordinary browser test retains screenshots only on failure. We did not run a live cluster or provider model turn locally for the final revision.

Risks

Theme assets are public before authentication. This supports raster images and validated color data, not arbitrary CSS/JavaScript or external asset URLs. A malformed configured bundle prevents API startup; operators recover by restoring a valid bundle or removing the setting and restarting. Palette contrast remains an operator responsibility. This adds no database schema or Agent runtime configuration changes.

Historical verification and approved exception — Russell’s original revision

The following evidence and waiver are from the original author’s PR at 3a0527e, before the current visual integration and QA-selection changes. They are retained for review and do not establish verification of the new head.

Source: 3a0527e2c26f9059077815338c8667202c212427, based on upstream main at e8185dac805b737363c7178d3068b310a53a7c24. Runtime suites and deployment evidence used 37fa6330b; the follow-up changes only the Storybook fixture selection. All changed app source files remain identical.

Check Result
node --test tests/integration/console-theme.test.mjs tests/integration/console-api.test.mjs 15 passed, no skips, using matching controller-image dependencies
node --test tests/browser/console.test.mjs 50 passed, no skips, in an isolated source copy with matching runtime dependencies and installed Chrome
node --test tests/integration/production-kubernetes-packaging.test.mjs 92 passed, no skips
Native TypeScript build check Passed in the isolated matching dependency graph; the original checkout is missing a baseline Fastify compiler dependency
Lint, formatting, workspace, documentation links/length, flow structure, CI manifest audit Passed
Final navigation sizing Existing targeted browser checks: 2 passed; live browser measured 32×32 desktop/mobile logos and 40×40 sign-in logo

Live evidence below uses Custom OCE branding on a local Podman Compose control plane with Kubernetes compute in k3d. Sign-in, Agent list/detail navigation, mobile drawer, and sign-out completed with no browser page errors. The API was healthy. All 11 changed app source files in the deployed controller match this commit. Tested controller image ID: 5daf170a1bf8bf5b4e2702505e629bfa0dacb3e2a76f4ff460633e1aa9cf9c5f.

Sign-in

Custom OCE sign-in with the custom logo and palette

Desktop navigation

Custom OCE Agent list with the 32 pixel navigation logo

Mobile navigation

Custom OCE mobile navigation drawer

Interaction walkthrough: sign in, inspect an Agent, open mobile navigation, and sign out.

custom-oce-walkthrough.mp4

The full Storybook CI build passed for this commit. Its downloaded static artifact was inspected through the full manager in headless Chrome; sign-in and mobile drawer interactions passed with no browser page errors. The final artifact waits for each visible state before capture; the missing-authentication preview verifies that deployment is disabled. All nine Pages/Theming previews were inspected: SignIn, Desktop, Mobile, LongName, Empty, Denied, Loading, MissingCredentials, and PublicError. These simulate resource/session/runtime state and do not prove persistence, credential propagation, or Agent execution.

Long-name preview (simulated UI proof)

Long product name wraps beside the custom logo without covering navigation

Canonical independent review completed through the shared autoreview helper using Codex gpt-6.1-sol at medium reasoning. The validated result is scoped-clean for P0–P2, with no findings, for the branch range from e8185dac805b737363c7178d3068b310a53a7c24 to 37fa6330b146da5afd326c24e65cc0331a151f2e. The reviewer assessed source and the sample image; it did not independently execute runtime tests. The separate canonical review of the one-line Storybook fixture follow-up (37fa6330b → 3a0527e2c) also completed with a validated scoped-clean P0–P2 result and no findings. Together, those two reviews covered the then-current head, 3a0527e.

Full Storybook manager (simulated UI proof)

Built Storybook manager showing the neutral sample theme and the nine theming stories

Loading preview (simulated UI proof)

Neutral themed console showing the visible loading state

Missing authentication (simulated UI proof)

Neutral themed console shows no authentication source and disables deployment

Human-approved verification exception:

  • On 2026-10-20, the PR author explicitly approved skipping real model-runtime QA for this theming change and requested ready-for-review status. The waived scope is Compose and Helm model-ui, for both OpenClaw and Codex presets. This change affects console presentation and theme mounting; its HTTP/browser integration, deployment UI walkthrough, full Storybook build, and visual checks passed. Real model turns and native model-response execution remain unverified; the waiver does not represent passing runtime QA.

Load and validate operator-mounted console branding at API startup. Apply product names, logos, icons, and semantic colors across public and authenticated UI surfaces, with API-only Compose and Helm mounts.

Add HTTP and browser integration coverage, themed Storybook scenarios, QA workflow wiring, and operator documentation.

Signed-off-by: Russell Bryant <rbryant@redhat.com>
@clawsweeper

clawsweeper Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

ClawSweeper review complete

ClawSweeper finished reviewing this revision. The review result is being finalized.

View the workflow run.

Signed-off-by: Russell Bryant <rbryant@redhat.com>
@russellb
russellb marked this pull request as ready for review October 20, 2026 19:56
@russellb
russellb requested a review from a team as a code owner October 20, 2026 19:56
@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Oct 20, 2026
@clawsweeper

clawsweeper Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge.

What this changes

This PR adds startup-loaded theme bundles for the console’s name, images, and semantic colors, with Compose and Helm mounting support.

Example: An operator mounts the example theme and restarts the API.

  • Before: Sign-in and navigation display OpenClaw Enterprise with the default accent color.
  • After: They display Example Agents with accent color #2457C5.

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) Useful approved capability with shipped-console visual evidence, focused integration coverage, preserved defaults, and no actionable findings.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): Current-revision screenshots show default and custom branding through the local controller’s sign-in, desktop, and mobile console on Linux with Node 24 and Chromium; supplied browser checks cover sign-in, Agent navigation, computed color, and sign-out. Recording decoding was unavailable in this review environment. No existing persisted format is migrated or rewritten, and absent configuration retains bundled defaults.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Product

Kind: Feature · Worth it: Yes · Fix scope: Complete
User problem: Operators cannot apply deployment branding while retaining the upstream controller image.
Reason: Maintainer direction is recorded, and the implementation provides a focused deployment-wide capability while preserving default branding.

Merge readiness

✅ Ready for maintainer review

Keep open: this PR delivers useful, maintainer-approved deployment branding that current main lacks; no actionable correctness or security defects were found.

Priority: P2
Reviewed head: 977d73857af727250981566134810b0529aa0e52

Before merge

None.

Findings

None.

Agent review details

How this fits together

The controller loads trusted deployment files before listening, then serves their validated presentation data through the existing public console asset handler.

flowchart LR
  A[Operator bundle] --> B[Startup validation]
  B --> C[Theme snapshot]
  C --> D[Console asset handler]
  E[Bundled console assets] --> D
  D --> F[Browser console]
Loading

Technical review

Best possible solution:

Land the optional startup snapshot through the existing console owner with its validated asset boundary and documented restart recovery.

Do we have a high-confidence way to reproduce the issue?

This is a new capability; current-main source confirms that deployment theme bundles are not already supported.

Is this the best way to solve the issue?

The implementation extends the existing console asset and composition owners without introducing platform resources, persistence, or arbitrary executable theme content.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning medium; reviewed against 4f848ea4c8fc.

Provenance checked

Testing

Proof path: shipped entry point.

Security

None.

Evidence

What I checked:

Likely related people:

  • Free Wortley: Raw commit 8eea656 adds apps/controller/src/console/console.css:33 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 8eea656c0ae6; files: apps/controller/src/console/console.css)
  • kevinlin-openai: Raw commit 835b1cc adds apps/controller/src/console/shell.mjs:1 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: high; commits: 835b1cc9b775; files: apps/controller/src/console/shell.mjs)
  • Russell Bryant: Raw commit 3935a45 adds apps/controller/src/console/shell.mjs:233 relative to its recorded parents. This identifies author metadata, not feature responsibility or a PR merger. (role: source-line author; confidence: medium; commits: 3935a4545342; files: apps/controller/src/console/shell.mjs)

Labels

Label changes:

No label changes.

Label justifications:

  • P2: Useful deployment customization with limited blast radius and no demonstrated urgent user regression.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR.
  • proof: sufficient: Contributor real behavior proof is sufficient.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence.

Rating scale

6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior.

Workflow

ClawSweeper edits this one comment on every review. Comment @clawsweeper re-review for a fresh review only. Repair and merge execution lanes are retired.

History

Review history (1 earlier review cycle)
  • reviewed 2026-10-20T20:10:53.232Z sha 3a0527e :: needs maintainer review before merge. :: none

Reviewed October 21, 2026, 7:12 PM ET / 23:12 UTC (Revision 2).

@freeqaz

freeqaz commented Oct 21, 2026

Copy link
Copy Markdown
Collaborator

Free's clanker here (an AI agent working on Free's behalf). Heads-up about a conflict coming from main: #3111 moved the body of apps/controller/src/server.mjs unchanged into a new apps/controller/src/api-startup.mjs, as startApi(env). server.mjs is now a thin wrapper that calls startApi(process.env) and prints the same startup-error line on failure.

This PR edits the old body of server.mjs, so its next merge of main will conflict there. To resolve it, apply the same edits to the matching code in api-startup.mjs, and read settings from the env argument rather than process.env, so the in-process startup checks see them. Production behaviour is the same either way, because server.mjs passes process.env. I'm happy to do the port and push it if that helps.

@freeqaz-openai

Copy link
Copy Markdown
Collaborator

(human here) I'm doing some UI cleanup work as well so gonna get this landed. Thanks @russellb 🙏

@freeqaz-openai

Copy link
Copy Markdown
Collaborator

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

🦞👀
Exact review queued.

Re-review progress:

@clawsweeper clawsweeper Bot added clawsweeper:intake:feature Preliminary submission classification; full source review pending. and removed clawsweeper:intake:feature Preliminary submission classification; full source review pending. labels Oct 21, 2026

@freeqaz-openai freeqaz-openai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maintainer review performed with Codex on 977d738. I reviewed the startup and public asset boundary, default and custom branding, QA selection, and typed test discovery. The final local controller/browser proof and Claw review show no actionable findings. The trusted-administrator filesystem requirement and the earlier model-runtime QA exception are documented; no live provider or cluster qualification is claimed for this revision.

@freeqaz-openai
freeqaz-openai merged commit 9d67782 into openclaw:main Oct 21, 2026
56 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P2 Normal priority bug or improvement with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants