Context. surface studio · domain isis · route /studio/isis/3d-generation/turntable-viewer · auth signed-in + studio entitlement (parent segment 3d-generation is AAA-gated; nested route inherits — verify per-segment behavior in middleware.ts) · source apps/oshun/web/src/app/studio/isis/3d-generation/turntable-viewer/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; body re-derived 2026-06-03 from current source (lane-console architecture)
Purpose#
Hybrid surface: the load-bearing, real-backed element is the Orbit Frame
Planner lane, which calls the Isis turntable orbit frame-plan generator to step
azimuth evenly across 360°, place the camera on the orbit circle per frame, and
report duration, azimuth step, and per-frame x/y/z positions via
/v1/admin/isis/turntable-viewer. The page also retains a legacy in-browser 3D
inspection shell (BrowserMeshTurntableViewer) driven entirely from local demo
scenes — orbit/pan/zoom, progressive mesh streaming, PBR channel isolation,
UV/wireframe overlays, variant comparison, and AR Quick Look — with no BFF call.
Entry points#
- Breadcrumb in
/studio/isis/3d-generation:Studio→Isis 3D Generation→Turntable Viewer - Sibling quick-actions:
/studio/isis/3d-generation,/studio/isis/3d-post-processing - Direct URL / bookmark (AAA entitlement applies via parent gate)
Layout regions#
page.tsx mounts <ShellLayout active="studio"> and four panels: a breadcrumb
panel, the StudioIsisTurntableViewerWorkspace, the Route Map, and sibling
quick-actions.
- Header: shell header
- Breadcrumb panel (
data-isis-turntable-viewer-breadcrumbs): Studio → Isis 3D Generation → Turntable Viewer (aria-current="page") - Workspace panel (
data-isis-turntable-viewer-workspace):- Orbit Frame Planner lane (
data-tt-lane,<h2 data-tt-heading>Orbit Frame Planner</h2>) — the wired lane, rendered first - Eyebrow "Viewer Surface",
<h1>(WorkspaceHeading) "Isis Turntable Viewer", summary paragraph, and anAuto turntable: {autoState}pill (running|paused|off) - Legacy capability summary grid (
data-isis-turntable-capability-summary,data-isis-turntable-capability=<id>), stage shell (data-isis-turntable-stage-shell/data-isis-turntable-stage,aria-label="Interactive 3d turntable viewport") with ~40 state data-attributes, a control rail, and section panels — all local/demo-driven
- Orbit Frame Planner lane (
- Route Map panel (
data-isis-turntable-viewer-route-map):<h2>Route Map</h2>overSTUDIO_ISIS_TURNTABLE_VIEWER_ROUTE_MAP(4 entries) - Sibling quick-actions panel:
/studio/isis/3d-generation,/studio/isis/3d-post-processing,/studio
States#
Orbit Frame Planner lane (wired)#
- Loading —
outcome === null;data-tt-loading"Loading turntable planner…" - Unauthorized — 401/403 admin-scope fail-closed;
data-tt-unauthorized("Isis workspace scope required to plan the turntable.") - Error — non-OK catalog response;
data-tt-error - Ready (form) —
outcome.status === 'ready'; the JSON payload form renders - Result —
data-tt-resultwithdata-tt-headline(frames · duration · azimuth step) anddata-tt-framestable; plan failure →data-tt-plan-error
Legacy viewer shell (local/demo only)#
- Auto turntable running / paused / off —
data-isis-turntable-auto-state - Single / overlay / side-by-side comparison,
progressive streaming, AR supported / fallback — all driven from
BrowserMeshTurntableViewerstate, not the BFF - Gated — inherited AAA gate via parent route
Interactions#
Orbit Frame Planner lane (data-tt-form)#
- Orbit JSON payload (
data-tt-payload, textarea,aria-label="turntable orbit json"; defaults{ frameCount, fps, radius, elevationDeg, startAzimuthDeg }) - Plan orbit (
data-tt-submit, submit) —POST /v1/admin/isis/turntable-viewer/plan; renders summary + per-frame table (data-tt-frame-row,data-tt-frame-azimuth,data-tt-frame-x,data-tt-frame-z,data-tt-step)
Breadcrumb#
- Studio →
/studio - Isis 3D Generation →
/studio/isis/3d-generation - Turntable Viewer (
aria-current="page")
Legacy viewer shell#
- Orbit/pan drag + wheel zoom; comparison-mode, PBR, pointer-mode, overlay,
auto-turntable, restart-streaming, fit-asset controls; view presets
(
data-isis-turntable-preset); hero-asset chips (data-isis-turntable-hero-asset) — all in-memory, backed by local demo scenes (DEMO_SCENE/CANDIDATE_SCENE)
Sibling quick-actions#
- Open Isis 3D Generation workspace →
/studio/isis/3d-generation - Open Isis 3D Post Processing workspace →
/studio/isis/3d-post-processing - Back to Studio workspace index →
/studio
Data & contracts#
- Reads:
GET /v1/admin/isis/turntable-viewer(lane catalog probe; gates the form). The legacy viewer reads only local demo scenes. - Writes:
POST /v1/admin/isis/turntable-viewer/plan(orbit frame plan). The legacy viewer's AR Quick Look uses a same-origin USDZ handoff, not the BFF. - Realtime: none
- Caching: lane client fetch on mount,
cache: 'no-store',buildBffAuthHeaders() - Auth/role check: lane is admin-scoped, fail-closed (401/403); route gated
via the parent
3d-generationAAA segment - Component sources:
apps/oshun/web/src/components/studio/StudioIsisTurntableViewerWorkspace.tsxapps/oshun/web/src/components/studio/StudioIsisTurntableViewerRouteMap.ts
Cross-references#
- Studio overview:
../../studio-overview.md - Parent route:
studio-isis-3d-generation.md - Sibling routes:
Open questions / known gaps#
- Hybrid surface: only the Orbit Frame Planner lane is BFF-wired; the
large 3D viewer shell remains local/demo-driven (
DEMO_SCENE/CANDIDATE_SCENE, hero asset chips from a local list) — confirm whether the shell should consume a real asset registry or be retired - Confirm the nested route inherits AAA gating from
3d-generation - Route-map sub-paths (
/captures,/reviews,/presets) are declared but not yet implemented as separate pages