feat(ui): Phase 26 — customer SPA island integration (hero:theme + hero:route postMessage + X-Forwarded-Prefix) #11

Open
opened 2026-05-06 17:47:10 +00:00 by mik-tf · 0 comments
Owner

Why

The customer-facing SPA (_ui_wasm) is currently designed for two delivery modes:

  1. Standalone via _app Dioxus desktop binary
  2. _ui --dist <path> direct browser access

Missing: integration with Hero OS shell as an archipelago island. Per web_embed + hero_ui_routes skills, every UI mounted in hero_os must:

  • Implement hero:theme postMessage protocol — receive theme changes from shell
  • Implement hero:route postMessage protocol — push nav state into host window's floating header (breadcrumbs + actions + deep-link URL)
  • Honor X-Forwarded-Prefix header for base-path routing (hero_router mounts services at /hero_assistance/...)
  • NOT render its own breadcrumb bar or close button when running inside Hero OS shell

What

A. postMessage protocols

  • hero:theme receiver — listen for {type: "hero:theme", theme: "dark"|"light"} messages from parent; update data-bs-theme
  • hero:route sender — on every nav change, post {type: "hero:route", route: {...}, breadcrumbs: [...], actions: [...]} to parent

Per web_embed skill drop-in helper hero-window-route.js.

B. X-Forwarded-Prefix base-path

_ui Axum reads X-Forwarded-Prefix from request headers; threads BASE_PATH into SPA via <meta name="base-path"> tag. SPA reads BASE_PATH and uses it for all /rpc, /events, asset URLs.

Per hero_web_prefix skill.

C. Archipelago slot — D-23

Pick one:

  • Communication archipelago (alongside room, call, voice, collab) — recommended; hero_assistance is support communication
  • Tools archipelago (alongside whiteboard, slides, inspector)

Rationale in D-23. Register in external hero_archipelagos repo: new island spec referencing the WASM dist URL via hero_router.

D. Conditional chrome

When ?embedded=1 or running inside iframe (detect window.parent !== window), suppress:

  • Top-level breadcrumb bar (host window owns this)
  • Close button (host owns)
  • Window title (host owns)

Keep visible: tab strip, ticket list, composer, presence sidebar.

Acceptance

  • hero:theme postMessage updates SPA theme without page reload
  • hero:route postMessage fires on every nav change with current route + breadcrumbs
  • X-Forwarded-Prefix: /hero_assistance causes SPA to use prefixed URLs for all requests
  • Embedded mode hides top-level chrome (breadcrumbs + close button)
  • D-23 written
  • Archipelago island spec PR opened against lhumina_code/hero_archipelagos
  • Manual smoke: open hero_os shell, navigate to hero_assistance island, verify embedding works

Files to touch

  • crates/hero_assistance_ui_wasm/src/lib.rs — postMessage send/receive
  • crates/hero_assistance_ui_wasm/src/components/ — conditional chrome rendering
  • crates/hero_assistance_ui/src/main.rs — X-Forwarded-Prefix handling, BASE_PATH meta tag injection
  • New: decisions/D-23-archipelago-slot.md
  • External PR: lhumina_code/hero_archipelagos — new island spec

Out of scope

  • hero_proc lifecycle (Phase 24)
  • Admin dashboard (Phase 25)
  • hero_demo provisioning (Phase 27)

References

  • Skill web_embed
  • Skill hero_ui_routes
  • Skill hero_web_prefix
  • External: lhumina_code/hero_archipelagos repo island spec format
  • External: lhumina_code/hero_os shell (consumes islands)
## Why The customer-facing SPA (`_ui_wasm`) is currently designed for two delivery modes: 1. Standalone via `_app` Dioxus desktop binary 2. `_ui --dist <path>` direct browser access Missing: integration with **Hero OS shell** as an archipelago island. Per `web_embed` + `hero_ui_routes` skills, every UI mounted in `hero_os` must: - Implement `hero:theme` postMessage protocol — receive theme changes from shell - Implement `hero:route` postMessage protocol — push nav state into host window's floating header (breadcrumbs + actions + deep-link URL) - Honor `X-Forwarded-Prefix` header for base-path routing (`hero_router` mounts services at `/hero_assistance/...`) - NOT render its own breadcrumb bar or close button when running inside Hero OS shell ## What ### A. postMessage protocols - `hero:theme` receiver — listen for `{type: "hero:theme", theme: "dark"|"light"}` messages from parent; update `data-bs-theme` - `hero:route` sender — on every nav change, post `{type: "hero:route", route: {...}, breadcrumbs: [...], actions: [...]}` to parent Per `web_embed` skill drop-in helper `hero-window-route.js`. ### B. X-Forwarded-Prefix base-path `_ui` Axum reads `X-Forwarded-Prefix` from request headers; threads `BASE_PATH` into SPA via `<meta name="base-path">` tag. SPA reads BASE_PATH and uses it for all `/rpc`, `/events`, asset URLs. Per `hero_web_prefix` skill. ### C. Archipelago slot — D-23 Pick one: - **Communication** archipelago (alongside `room`, `call`, `voice`, `collab`) — recommended; hero_assistance is support communication - **Tools** archipelago (alongside `whiteboard`, `slides`, `inspector`) Rationale in D-23. Register in external `hero_archipelagos` repo: new island spec referencing the WASM dist URL via hero_router. ### D. Conditional chrome When `?embedded=1` or running inside iframe (detect `window.parent !== window`), suppress: - Top-level breadcrumb bar (host window owns this) - Close button (host owns) - Window title (host owns) Keep visible: tab strip, ticket list, composer, presence sidebar. ## Acceptance - [ ] `hero:theme` postMessage updates SPA theme without page reload - [ ] `hero:route` postMessage fires on every nav change with current route + breadcrumbs - [ ] `X-Forwarded-Prefix: /hero_assistance` causes SPA to use prefixed URLs for all requests - [ ] Embedded mode hides top-level chrome (breadcrumbs + close button) - [ ] D-23 written - [ ] Archipelago island spec PR opened against `lhumina_code/hero_archipelagos` - [ ] Manual smoke: open hero_os shell, navigate to hero_assistance island, verify embedding works ## Files to touch - `crates/hero_assistance_ui_wasm/src/lib.rs` — postMessage send/receive - `crates/hero_assistance_ui_wasm/src/components/` — conditional chrome rendering - `crates/hero_assistance_ui/src/main.rs` — X-Forwarded-Prefix handling, BASE_PATH meta tag injection - New: `decisions/D-23-archipelago-slot.md` - External PR: `lhumina_code/hero_archipelagos` — new island spec ## Out of scope - hero_proc lifecycle (Phase 24) - Admin dashboard (Phase 25) - hero_demo provisioning (Phase 27) ## References - Skill `web_embed` - Skill `hero_ui_routes` - Skill `hero_web_prefix` - External: `lhumina_code/hero_archipelagos` repo island spec format - External: `lhumina_code/hero_os` shell (consumes islands)
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_assistance#11
No description provided.