V1 Web PWA · Surface walkthrough

Studio Aja · Fitness Animation

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

walked
8sections3 minread

On this page

Context. surface studio · domain aja · route /studio/aja/fitness-animation · auth signed-in + studio entitlement · source apps/oshun/web/src/app/studio/aja/fitness-animation/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#

Admin lane console for the real @aja/fitness-animation calculateJointAngle metric. The operator names a joint and enters its proximal / joint / distal points (each an x,y,z triple); the lane measures the proximal–joint–distal flexion angle in degrees — the range-of-motion metric behind fitness form analysis (e.g. knee flexion at squat depth).

Entry points#

  • Direct URL / bookmark/studio/aja/fitness-animation; metadata canonical to this path
  • Studio nav — Domain-bridge studios section of /studio
  • Breadcrumb parent/studio/aja/fitness-pipeline (declared in the page.tsx breadcrumb <ol>)
  • Sibling quick-actions on this page: Fitness Pipeline, Sports Pipeline, Yoga Pipeline, Dance Pipeline, Martial Arts Pipeline, Back to Studio
  • Operator surfacing — see ../../studio-overview.md

Layout regions#

page.tsx renders inside <ShellLayout active="studio">:

  • Breadcrumb panel (data-aja-fitness-animation-breadcrumbs): <nav aria-label="Aja Fitness Animation breadcrumbs">Studio / Aja Fitness Pipeline / Fitness Animation
  • Workspace (<StudioAjaFitnessAnimationWorkspace />, archetype: LEAF):
    • <h1> (WorkspaceHeading) "Aja Fitness Animation Workspace"
    • Summary <p data-aja-fa-summary> — measure a joint's flexion angle from its proximal / joint / distal points
    • A data-aja-fa-metric catalog line (metric · unit · range) and the angle form
  • Route Map panel (data-aja-fitness-animation-route-map): <h2>Route Map</h2> listing 6 entries from STUDIO_AJA_FITNESS_ANIMATION_ROUTE_MAP (primary, programs, sessions, outputs, parity, governance)
  • Quick-action panel: six Link.quickAction anchors — Fitness Pipeline, Sports Pipeline, Yoga Pipeline, Dance Pipeline, Martial Arts Pipeline, Back to Studio

States#

  • Loading — GETs the metric catalog on mount; renders <p data-aja-fa-loading> "Loading joint-angle metric…"
  • Unauthorized — 401/403 renders data-aja-fa-unauthorized ("Access restricted." + admin-scope message, default "Aja workspace scope required to view fitness animation.")
  • Error — non-OK / malformed / unreachable renders data-aja-fa-error ("Could not load fitness animation." + reason)
  • Ready (form) — success renders data-aja-fa-metric and the data-aja-fa-angle-form
  • Result — a successful POST renders data-aja-fa-result with data-aja-fa-angle (joint name + flexion degrees)
  • Validation / measure error — client guards (joint name required; each point a 3-number triple) and POST failures render data-aja-fa-angle-error
  • Empty / Standalone PWA / offline — N/A beyond the above; shell SSR, lane is a client fetch on mount

Interactions#

Workspace lane (data-aja-fa-angle-form)#

  • Joint name (data-aja-fa-field-name, input, label "Joint name")
  • Proximal point (data-aja-fa-field-proximal, input, label "Proximal point (x,y,z)")
  • Joint point (data-aja-fa-field-joint, input, label "Joint point (x,y,z)")
  • Distal point (data-aja-fa-field-distal, input, label "Distal point (x,y,z)")
  • "Measure angle" (data-aja-fa-angle-submit, submit) — fires POST /v1/admin/aja/fitness-animation/joint-angles with { joints: [{ name, proximal, joint, distal }] }

Route Map panel#

  • Route entries (6 × <article>) — non-interactive path+purpose

Quick-action panel#

  • "Open Aja Fitness Pipeline workspace"/studio/aja/fitness-pipeline
  • "Open Aja Sports Pipeline workspace"/studio/aja/sports-pipeline
  • "Open Aja Yoga Pipeline workspace"/studio/aja/yoga-pipeline
  • "Open Aja Dance Pipeline workspace"/studio/aja/dance-pipeline
  • "Open Aja Martial Arts Pipeline workspace"/studio/aja/martial-arts-pipeline
  • "Back to Studio workspace index"/studio

Data & contracts#

  • Reads: GET /v1/admin/aja/fitness-animation on mount — catalog { metric, unit, range: number[] }
  • Writes: POST /v1/admin/aja/fitness-animation/joint-angles{ angles: [{ name, angleDegrees }] }
  • Realtime: none
  • Caching: client fetch on mount with cache: 'no-store' and buildBffAuthHeaders(); SSR shell only
  • Auth/role check: BFF endpoints admin-scoped + fail-closed (401/403 → unauthorized render); route behind the signed-in + studio proxy gate

Cross-references#

Open questions / known gaps#

  • Route-map sub-routes are advertised but have no page.tsx in V1