V1 Web PWA · Surface walkthrough

Lilith Studio · Tara venue authoring

A per-surface walkthrough of the V1 Web PWA customer surface: layout, states, interactions, data, and cross-references.

walked + e2e-covered
9sections7 minread

On this page

Context. surface customer · domain lilith · route /lilith-studio/scenes · auth signed-in + role:v1_editorial_producer (default) · source apps/oshun/web/src/app/lilith-studio/scenes/page.tsx

Last walked. 2026-05-29 automated runtime walk (Playwright headless) — render, /v1 data (2xx), console/page-errors, expected content, screenshot verified; live screen-reader, touch, offline, and telemetry-delivery checks pending a manual AT pass. Evidence: WALKTHROUGH/results/runtime-sweep-2026-05-29.md; content re-verified 2026-06-03 against current source. 2026-07-01 deep browser coverage added in apps/oshun/web/e2e/lilith-scene-editor-deep.spec.ts for every editor control, drag/drop, graph selection, provenance selection, publish readiness, real-BFF publish, draft reset, real-service-worker offline replay, and mobile standalone overflow.

Purpose#

Author Tara venue scenes — place V1 library assets, tune lighting, select a rights-cleared sound bed, bind room interactions, simulate a 4,096-attendee stadium load, pass color/motion/caption accessibility checks, and publish through the V1 editorial release branch. The page (apps/oshun/web/src/app/lilith-studio/scenes/page.tsx) returns <TaraSceneEditor /> directly; the <ShellLayout active="studio"> wrapper and the editorial scope gate are supplied by the route's apps/oshun/web/src/app/lilith-studio/layout.tsx.

Entry points#

  • Lilith Studio shell (/lilith-studio) — "Scene authoring" surface tab → "Open Scene authoring" link
  • Direct URL / bookmark — yes (signed-in)

Layout regions#

TaraSceneEditor (apps/oshun/web/src/app/lilith-studio/scenes/TaraSceneEditor.tsx):

  • Header: eyebrow "Lilith Studio / Scene editor", title "Tara venue authoring", lede, two header actions — "Lilith shell" → /lilith-studio, "V1 workflow" → /studio/review-approval-workflows
  • Three-column grid:
    • Asset lane (aria-label="Scene asset library"):
      • Panel header: "Asset tray" + "Drag assets into a venue zone or place them in the selected zone."
      • Asset list — four scene assets from TARA_SCENE_EDITOR_ASSETS: cedar-altar, lotus-canopy, lantern-path, chime-cluster — each with a draggable grip button (data-testid="lilith-scene-asset-<id>", data-lilith-scene-asset=<id>) and a "Place in selected zone" inline action button (data-lilith-scene-place-asset=<id>)
    • Stage panel (<main>):
      • Stage header: "Tara garden venue", selected zone label, status pill (data-lilith-scene-release-state) — "Draft branch" or "Release edition published"
      • Stage (data-testid="lilith-scene-stage") — four zone buttons from TARA_SCENE_EDITOR_ZONES: threshold, mandala, north-grove, sound-corner — each data-testid="lilith-scene-zone-<id>" with anchor, tone, and placement list ("Drop asset here" when empty)
      • Scene graph panel (data-lilith-scene-graph-editor): node count / edge count summary; node button list (aria-label="Scene graph nodes", data-lilith-scene-graph-node=<id>); detail panel with selected node's scope and edges in/out
    • Control lane (aria-label="Scene controls"):
      • Lighting (data-lilith-scene-lighting-panel): kelvin/intensity readout; segmented buttons for TARA_SCENE_EDITOR_LIGHTING (data-lilith-scene-lighting-preset=<id>) — dawn-soft, twilight- amber, moonlit-blue
      • Audio (data-lilith-scene-audio-panel): rights/loudness readout; segmented buttons for rights-cleared TARA_SCENE_EDITOR_ AUDIO (none filtered out) — forest-drone, singing-bowl, rain- texture (data-lilith-scene-audio-bed=<id>)
      • Interaction binder (data-lilith-scene-interaction-binder): Trigger select (data-lilith-scene-trigger-select, options INTERACTION_TRIGGERS: approach-altar, touch-chimes, enter-grove), Action select (data-lilith-scene-action-select, options INTERACTION_ACTIONS: open-breath-primer, play-mantra-preview, dim-room), "Add binding" primary button (data-lilith-scene-add-binding), binding list (data-lilith-scene-binding-list)
      • Capacity and sharding (data-lilith-scene-capacity-panel): Capacity tier segmented (TARA_SCENE_CAPACITY_TIERS: studio, salon, festival, stadium; data-lilith-scene-capacity-tier=<id>), Sharding profile segmented (TARA_SCENE_SHARDING_PROFILES: single-room, regional-fanout, interest-management; data-lilith-scene-sharding-profile=<id>), "Run 4,096 attendee simulation" primary button (data-lilith-scene-run-attendee-simulation), simulation stats <dl> (Accepted / Shards / Interest cells; data-lilith-scene-attendee-simulation, data-simulation-state)
      • Accessibility checker (data-lilith-scene-accessibility- checker): color profile segmented (TARA_SCENE_COLOR_PROFILES: low-contrast-dusk, wcag-aa-cedar), motion segmented (TARA_SCENE_MOTION_PROFILES: full-sweep, comfort-reduced), caption segmented (TARA_SCENE_CAPTION_PROFILES: ambient-only, full-spatial-captions), check list per id (color / motion / caption) with data-check-passed, remediation list
  • Release panel (aria-label="Scene publish controls"):
    • Readiness grid: Focal asset placed / Lighting preset selected / Rights-cleared audio selected / Interaction binding added / Stadium simulation passed / Accessibility checker passed
    • "Publish Tara venue" release button (data-lilith-scene-publish)
    • Publish status (data-lilith-scene-publish-status)
    • Publish manifest textarea (read-only, data-lilith-scene-publish-manifest)
  • LilithProvenanceInspector — surface ID tara-scene-editor, assets = TARA_SCENE_PROVENANCE_ASSETS

States#

  • Loading — client component; no route-local skeleton state. Browser coverage waits for the hydrated editor after the signed-in layout gate.
  • Draft (default)publishState='draft', data-publish-ready depends on readiness flags
  • Asset placedplacements.length > 0; deep coverage places all four assets and asserts the editor placement count.
  • Zone selectedselectedZoneId updates; data-selected="true" on the zone
  • Asset dragged into zone — drop handler adds placement; browser test dispatches a real DataTransfer drag/drop from cedar-altar to mandala.
  • Interaction binding added — binding list grows
  • Stadium tier + interest-management profile + simulation rundata-interest-management-ready="true"
  • Accessibility passingdata-accessibility-ready="true"
  • Publish blockedcanPublish === false
  • Publish readycanPublish === true
  • Publisheddata-publish-state="published" after the real /v1/admin/studio/scenes/publish BFF route returns the persisted publish id and release stream
  • Any change after publish — returns to draft (setPublishState('draft'))
  • Offline/lilith-studio/scenes is an exact service-worker shell route; focused coverage warms the real sw.js cache and replays the editor offline without shell fallback.

Interactions#

  • "Lilith shell" link — href /lilith-studio
  • "V1 workflow" link — href /studio/review-approval-workflows

Asset lane#

  • Each asset drag handle (4 — cedar-altar, lotus-canopy, lantern-path, chime-cluster)
  • Each "Place in selected zone" inline action button

Stage / zones (4 buttons)#

  • threshold zone (data-lilith-scene-zone="threshold")
  • mandala zone
  • north-grove zone
  • sound-corner zone
  • Drop handler — accepts dragged asset and calls placeAsset(assetId, zoneId)

Scene graph#

  • Each node button — sets selectedGraphNodeId
  • Edge list (read-only)

Lighting#

  • Three preset buttons (dawn-soft, twilight-amber, moonlit-blue)

Audio#

  • Three sound-bed buttons (forest-drone, singing-bowl, rain-texture)

Interaction binder#

  • Trigger select
  • Action select
  • "Add binding" button (primary)
  • Binding list (read-only)

Capacity and sharding#

  • Four capacity tier buttons (studio, salon, festival, stadium)
  • Three sharding profile buttons (single-room, regional-fanout, interest-management)
  • "Run 4,096 attendee simulation" button
    • Function: runAttendanceSimulation() populates accepted attendees, shard count, interest cells

Accessibility checker#

  • Two color profile buttons
  • Two motion profile buttons
  • Two caption profile buttons
  • Check results list — per check with pass/fail
  • Remediation list — empty state "Accessibility checks passed for scene publish." when none

Release panel#

  • Six readiness rows — read-only
  • "Publish Tara venue" release button (data-lilith-scene-publish)
    • Function: POSTs to /v1/admin/studio/scenes/publish; sets publishState='published' only after the BFF returns a publish id and release stream.
    • Disabled when canPublish === false
  • Publish manifest textarea (read-only)

Provenance inspector#

  • LilithProvenanceInspector — deep coverage asserts asset count, selects the singing-bowl audio provenance row, and verifies the bundle route contract.

Data & contracts#

  • Reads: in-file constants TARA_SCENE_EDITOR_ASSETS, TARA_SCENE_EDITOR_ZONES, TARA_SCENE_EDITOR_LIGHTING, TARA_SCENE_EDITOR_AUDIO, INTERACTION_TRIGGERS, INTERACTION_ACTIONS, TARA_SCENE_CAPACITY_TIERS, TARA_SCENE_SHARDING_PROFILES, TARA_SCENE_COLOR_PROFILES, TARA_SCENE_MOTION_PROFILES, TARA_SCENE_CAPTION_PROFILES, TARA_SCENE_PROVENANCE_ASSETS
  • Writes: client state for authoring edits; publish POSTs to the real /v1/admin/studio/scenes/publish BFF route and surfaces the persisted publishId / releaseStream response. The current BFF store is the scoped V1 release-stream persistence for this route.
  • Realtime: none
  • Caching: client bundle plus exact service-worker shell route /lilith-studio/scenes for warmed offline document replay
  • Auth/role check: proxy enforces signed-in session; the /lilith-studio/* layout enforces studio:editorial / admin:* scope

Cross-references#

E2E coverage#

  • apps/oshun/web/e2e/lilith-scene-editor-deep.spec.ts — granular browser coverage for all header links, assets, zone selection, drag/drop, graph selection, lighting/audio controls, binding, capacity/sharding, accessibility, readiness rows, provenance selection, real-BFF publish, draft reset, real service-worker offline replay, and mobile standalone overflow.
  • apps/oshun/web/e2e/lilith-scene-editor-smoke.spec.ts — primary Tara venue authoring/publish flow plus blocked accessibility, non-interest-management, access-denied, and shell-entry checks.
  • apps/oshun/web/e2e/lilith-scene-publish.spec.ts — direct BFF route contract for publish/list/error cases and UI publish persistence through the route.
  • apps/oshun/web/e2e/lilith-studio-shell-smoke.spec.ts — Lilith Studio shell route contract and /lilith-studio/scenes advertised surface link.

Resolved questions#

  • Drag-and-drop has a keyboard-accessible equivalent: each asset card has a keyboard-focusable "Place in selected zone" button, and the focused deep spec verifies all four inline placement actions.
  • The stadium simulation passes only when capacity is stadium, sharding is interest-management, the simulated attendance is 4,096, shard count is within the profile max, at least three assets are placed, and at least one interaction binding exists.
  • Publish destination is traced to /v1/admin/studio/scenes/publish and verified against the BFF publish/list contract; this is no longer a local-only setPublishState('published') transition.