V1 Web PWA · Surface walkthrough

Story Workspace · Veritas (by id)

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

walked
9sections3 minread

On this page

Context. surface customer · domain veritas · route /domains/veritas/story/[id] · auth signed-in · source apps/oshun/web/src/app/domains/veritas/story/[id]/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 2026-06-28 Codex addendum — expanded apps/oshun/web/e2e/veritas-story-workspace.spec.ts to cover canonical /domains/veritas/story/story-renewables-capacity, unknown-id static fallback, requested/canonical story data hooks, Library save state, shell hydration, PWA restore, offline mobile interaction, and no-horizontal-overflow checks.

Purpose#

The Veritas Story Workspace, parameterised by an id route param. Renders the same VeritasStoryWorkspace component as /domains/veritas/story, but the storyId prop is taken from the URL. The route parameter is what makes a story shareable, bookmarkable, and reachable from other surfaces with a canonical address.

Entry points#

  • Direct URL / bookmark — yes (auth required); the id segment carries the story identity (e.g., /domains/veritas/story/<storyId>)
  • Linked from /explore — story cards in discovery may target this route
  • Linked from /library — saved Veritas stories store resumePath: /story/<effectiveStoryId> (see buildVeritasStoryLibraryItem in the workspace)
  • Linked from /domains/veritas/topics/[topicId] — topic hub story rows link to this route by id
  • Linked from /d/... cross-domain handoffs — Metis explainer flow, Nisaba source-lineage trail, etc. may target a specific story id

Layout regions#

page.tsx is a 'use client' component:

tsx
const params = useParams<{ id: string }>();
<VeritasStoryWorkspace
  storyId={params.id}
  onClose={() => router.back()}
  origin="explore"
/>;

The component contents are identical to /domains/veritas/story. See domains-veritas-story.md for the full layout breakdown (hero, correction notes, retraction notices, editorial frame, claim detail lane, source inspection, evidence trail, Metis study continuity, assistant explainers, Tara metabolization, Arete next actions, reading stance, evidence sidebar, inspection overlay).

States#

Same as domains-veritas-story.md. The only route-level difference is the id parameter and how the workspace resolves it:

  • id matches a canonical story — workspace renders that story (currently the imported STORY fixture is static, so the workspace effectively shows the renewables story regardless — verify the V1 plan)
  • id is unknown — workspace falls back to the default STORY fixture; no 404 surface is rendered in the page (verify whether the shell handles missing stories at the BFF layer)
  • No id (impossible in App Router for a [id] segment) — Next routing guarantees this is unreachable

Interactions#

Same as domains-veritas-story.md. Notable identifiers preserved through the route param:

  • Library resume pathbuildVeritasStoryLibraryItem sets resumePath: /story/${effectiveStoryId}; verify the library-store replay restores this route correctly. E2E verifies the saved/unsaved transition and requested story id preserved in the route-state hooks; full Library replay remains covered by the Library dashboard specs.
  • Story-level data hooksdata-veritas-story-headline, data-veritas-story-claim-detail-lane, data-veritas-story-counterclaims, data-veritas-story-source-inspection, data-veritas-story-claim-card="primary", data-veritas-story-claim-card="open-question", etc. — see the sibling file for the full list

Data & contracts#

Same as domains-veritas-story.md. Additionally:

  • Route param: id is captured via useParams<{ id: string }>() and passed as storyId into the workspace
  • effectiveStoryId: inside the workspace, effectiveStoryId = storyId ?? STORY.objectId — so an undefined or unknown id silently falls back to the default story

Current E2E Evidence#

The shared story-workspace E2E now proves the route-param behavior directly:

  • Canonical id route: /domains/veritas/story/story-renewables-capacity exposes data-veritas-story-id, data-veritas-story-requested-id, data-veritas-story-canonical-id, and data-veritas-story-route-state.
  • Unknown id route: /domains/veritas/story/story-not-in-canonical-set preserves the requested id while rendering the canonical renewables story and exposes data-veritas-story-route-state="static-fallback".
  • PWA restore uses the dynamic story route as the relaunch target and verifies mobile/offline interaction without horizontal overflow.

Cross-references#

Open questions / known gaps#

  • The workspace currently ignores storyId for content selection (the imported STORY constant is static); confirm the V1 plan to swap to a real getStoryById(id) fetch and to surface a 404 when id is unknown. The current static fallback is now explicitly documented and covered.
  • No loading.tsx or error.tsx exist in apps/oshun/web/src/app/domains/veritas/story/[id]/; verify which boundary catches the as-yet-nonexistent fetch failure
  • When V1 wires real data, decide whether the route should redirect to a canonical slug if the id does not match (and whether the Library resume path should use slug or numeric id)
  • No telemetry on route-param resolution (e.g., no trackVeritasStoryOpened)