V1 Web PWA · Surface walkthrough

Atelier · XII · Cinematheque

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

walked
9sections5 minread

On this page

Context. surface customer · domain atelier · route /atelier/video · auth signed-in · source apps/oshun/web/src/app/atelier/video/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; refreshed 2026-06-28 in apps/oshun/web/e2e/atelier-video-render-queue.spec.ts: route anchors, 12 storyboard panels, render queue, selected shot card, disabled-placeholder Cut action, read-only interaction contract, reduced-motion static state, offline-stable loaded markup, and 390 px no-overflow stack; refreshed 2026-06-30 in apps/oshun/web/e2e/atelier-motion-to-cinematheque.spec.ts for optional motion handoff query context and inbound panel rendering.

Purpose#

Video atelier — "a short film, storyboarded." Five-step workflow: treatment → twelve-panel storyboard → shot list → render queue → final cut. Server-rendered by apps/oshun/web/src/app/atelier/video/page.tsx via getAtelierVideo()<AtelierVideo data>.

Entry points#

  • Atelier index (/atelier) — third room card
  • Lilith index (/lilith) — section VIII card 44 "XII · Cinematheque"
  • Motion handoff (/atelier/motion) — "Open in Cinematheque" sends /atelier/video?from=motion&shot=sh-03&take=take-02&voice=foundry-take-03&light=forms-cream-north and renders the inbound motion context panel
  • Direct URL / bookmark — yes (signed-in)

Layout regions#

AtelierVideo (apps/oshun/web/src/components/lilith/atelier.tsx) renders inside LWebShell with LCustomerNav active="explore".

The route root exposes data-atelier-video-page with data-atelier-video-shot-count="12", data-atelier-video-render-queue-count="3", data-atelier-video-current-shot="sh 06", and data-atelier-video-render-progress="64". Its body exposes data-atelier-video-layout; below 980 px it stacks to one column and the 390 px Playwright path verifies no horizontal overflow.

  • Plate head (LAPlateHead no="XII"):
    • kicker: "The atelier · cinematheque"
    • title: A short film, <em>storyboarded</em>.
    • right chips: "04 : 38 / 06 : 00", "9 of 12 shots", "Rendering · take 02" (accent)
  • Three-column body (230px 1fr 320px):
    • Left rail (LAStepRail, current=3): five steps — "Treatment · written", "Storyboard · twelve panels", "Shot list · cameras, lenses", "Render · queue running", "Cut · final edit"
    • Center:
      • Storyboard grid (data-atelier-video-storyboard): 4×3 desktop grid of 12 16:9 panels with procedural SVG illustrations + per-panel state (rendered for sh 01–05, rendering · 64% for sh 06, queued overlay for sh 07–10, drafted overlay for sh 11–12); panel sh 06 exposes data-atelier-video-shot-selected="true" and an accent border
      • Each panel footer shows sh NN + time from data.shotTimes + the title from data.shotTitles
      • Render queue (data-atelier-video-render-queue): three rows from data.renderQueue — sh 06 (rendering, 64%, eta 02:14, accent treatment), sh 07 (queued, eta 04:42), sh 08 (queued, eta 06:18)
    • Right:
      • Motion handoff (conditional): when the URL includes the exact motion handoff query, a compact panel exposes data-atelier-video-inbound-handoff, data-atelier-video-inbound-source="motion", data-atelier-video-inbound-state="url-context", data-atelier-video-inbound-shot="sh 03", data-atelier-video-inbound-take="take 02", data-atelier-video-inbound-voice="foundry · take 03", and data-atelier-video-inbound-light="forms · cream-north"
      • Shot · sh 06 card (accent border): 16:9 SVG render + T+00:48 · 24fps watermark + LAProgress value=0.64 eta="02:14"
      • LField rows: Camera "Locked, slow tilt up", Lens "35 mm · ƒ2.8", Frame rate "24 fps", Length "00:12", Light "North window, single source", Engine "Lilith Cine · v1.4", Sound "From foundry · 02:14 stem"
      • "Open in Cut · timeline" button (ghost, full)

States#

  • Loading boundary absence — no segment loading.tsx exists under apps/oshun/web/src/app/atelier/video; getAtelierVideo() currently returns the synchronous fixture through the server component
  • Populated — fixture provides 12 shot titles/times + 3 render-queue entries, asserted via data-atelier-video-shot-count="12" and data-atelier-video-render-queue-count="3"
  • Mid-render — sh 06 shows rendering · 64% pill, selected state, and shot-card progress 64
  • Queued shots — sh 07/08/09/10 expose data-atelier-video-shot-state="queued" and queued overlays; queue rows sh 07 and sh 08 expose queued state + eta
  • Drafted shots — sh 11/12 expose data-atelier-video-shot-state="drafted" and drafted overlays
  • Error boundary absence — no route-local error.tsx exists; failures fall through the inherited app boundary
  • Offline — after the route is loaded, browser offline mode keeps the static storyboard, render queue, selected shot, and action markup visible
  • Reduced motion — progress visual is rendered as a static bar with no animation declared
  • Mobile stack — 390 px viewport stacks rail → storyboard/queue → shot card/action with no horizontal overflow
  • Inbound motion handoff — exact whitelisted query context renders the Motion handoff panel; bare /atelier/video remains the static Cinematheque route without inbound context

Interactions#

Storyboard panels#

  • Each panel (12, sh 01–sh 12) — read-only; tapping sh 10 does not select it, mutate the selected shot card, or navigate
  • Highlighted panel (sh 06, accent border) — current selection exposed by data-atelier-video-shot-selected="true"
  • State pills/overlays — read-only; rendering/queued/drafted states are asserted from DOM attributes and visible labels

Render queue rows#

  • sh 06 row (rendering, accent) — read-only with progress bar and data-atelier-video-queue-progress="64"
  • sh 07 row (queued, eta 04:42)
  • sh 08 row (queued, eta 06:18)

Right column#

  • Motion handoff panel — read-only URL context from /atelier/motion, with target shot, source take, inherited voice, and inherited light
  • Shot card — read-only metadata; SVG preview click does not change the selected shot or navigate
  • "Open in Cut · timeline" button (ghost, full) — placeholder LBtn with aria-disabled="true", data-placeholder="true", tooltip No handler wired — placeholder, and no navigation

Data & contracts#

  • Reads: getAtelierVideo() from apps/oshun/web/src/lib/lilith-data/atelier-depth.ts — returns AtelierVideoData with shotTimes, shotTitles, renderQueue (planned BFF at /atelier/plates/video)
  • Optional URL context: from=motion&shot=sh-03&take=take-02&voice=foundry-take-03&light=forms-cream-north maps to AtelierMotionHandoffData and renders the inbound panel. Other values are ignored.
  • Writes: none in current static composition
  • Realtime: render queue would update via subscription in production; none in current code
  • Caching: server fetch
  • Auth/role check: middleware enforces signed-in

Cross-references#

E2E coverage#

Spec: apps/oshun/web/e2e/atelier-video-render-queue.spec.ts (4 tests)

Coverage depth: deep for the current static/read-only route contract: fixture-derived storyboard rendering, coherent render queue state, selected shot metadata, disabled-placeholder Cut action, read-only non-mutation, mobile no-overflow, reduced-motion static state, and offline-stable loaded markup. apps/oshun/web/e2e/atelier-motion-to-cinematheque.spec.ts also covers the motion handoff URL and inbound panel. Remaining gaps are product gaps rather than test gaps: no route-local loading/error boundaries, no live render-progress subscription, no storyboard selection/reorder/edit flow, and no Cut timeline target.

Open questions / known gaps#

  • Confirm whether the render queue auto-updates progress or is static — current route is static; progress remains 64% in the loaded DOM
  • Document the "Open in Cut · timeline" target — is /cut a planned route or does it open a modal editor here?
  • Verify whether storyboard panels support drag-reordering (no affordance shown in code) — current panels are read-only visual cells