V1 Web PWA · Surface walkthrough

Topic Hub Workspace · Veritas (by topicId)

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

walked
8sections3 minread

On this page

Context. surface customer · domain veritas · route /domains/veritas/topics/[topicId] · auth signed-in · source apps/oshun/web/src/app/domains/veritas/topics/[topicId]/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

Purpose#

The Veritas Topic Hub workspace, parameterised by a topicId route param. Renders the same VeritasTopicHubWorkspace as /domains/veritas/topics, but the topicId is taken from the URL — this is the canonical, shareable address for a topic hub.

Entry points#

  • Direct URL / bookmark — yes (auth required); the topicId segment carries topic identity (e.g., /domains/veritas/topics/renewable-energy)
  • Linked from /domains/veritas/story/[id] — the story workspace builds a topic-hub href to /topics/<STORY_TOPIC.slug>
  • Linked from /domains/veritas/topics — the topic follow-up "Topics" link in the default-topic workspace points back here
  • Linked from /explore — topic discovery cards may target by id
  • Linked from /library — verify whether saved topics restore via this route

Layout regions#

page.tsx is a 'use client' component:

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

The component contents are identical to /domains/veritas/topics. See domains-veritas-topics.md for the full layout breakdown (top toolbar with follow toggle, hero, two-column main+aside grid with current read / timeline / clusters / claim posture / sources / alert controls / follow-ups, plus the inspection overlay).

The topicId is resolved by getTopicKey(topicId):

tsx
function getTopicKey(topicId?: string): TopicKey | null {
  if (topicId === undefined) {
    return 'renewable-energy';
  }
  return isKnownTopicKey(topicId) ? topicId : null;
}

KNOWN_TOPIC_KEYS is ['renewable-energy', 'quantum-computing']. A known id resolves to its key; only an absent id defaults to 'renewable-energy'; an unknown id returns null, and the workspace renders VeritasTopicNotFoundPanel ("Topic not found", data-veritas-topic-not-found, ~329-352). The code comment (~359-360) is explicit: "Earlier builds silently rerouted unknown topic IDs to renewable-energy; that behaviour is gone."

States#

Same as domains-veritas-topics.md. Route- specific notes:

  • topicId = 'renewable-energy' — renewable energy topic loads
  • topicId = 'quantum-computing' — quantum topic loads
  • topicId = <any other>getTopicKey returns nullVeritasTopicNotFoundPanel renders ("Topic not found", data-veritas-topic-not-found) listing the known hubs, not a silent reroute to renewable energy
  • No id — Next routing prevents this for [topicId] segments

Interactions#

Same as domains-veritas-topics.md. The route param flows through into telemetry:

  • Follow toggletrackVeritasTopicFollowed / trackVeritasTopicUnfollowed payloads include topicId: topic.topicId and topicTitle: topic.title; these come from the resolved TOPIC_HUBS[topicKey], not the raw URL param
  • Alert frequency changetrackVeritasTopicAlertFrequencyUpdated payloads carry the same topicId and topicTitle derived from the resolved topic
  • Inspection telemetrytrackVeritasInspectionOpened includes workspace: 'topic-hub'; the topic context lives implicitly in the itemId of the claim/source being inspected

Data & contracts#

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

  • Route param: topicId is captured via useParams<{ topicId: string }>() and passed into the workspace
  • getTopicKey mapping: returns TopicKey | null — a known id (renewable-energy / quantum-computing) resolves to its key, an undefined id defaults to renewable-energy, and an unknown id returns null → not-found panel

Cross-references#

Open questions / known gaps#

  • getTopicKey recognises renewable-energy and quantum-computing; an unknown id already surfaces VeritasTopicNotFoundPanel rather than a reroute. Confirm V1 plan to expand the topic dictionary when real data is wired (and whether the not-found panel should be a true 404)
  • No loading.tsx or error.tsx co-located; the workspace renders synchronously today
  • Library items resume via topic slug (STORY_TOPIC.slug) — verify the slug values match the expected topicId URL shape
  • No deep-link parameters for opening a specific claim/source inspection in the overlay on first render (compare with the Sophia bundle inspection)
  • When V1 wires real data, decide whether unknown topic ids should 404 or redirect to a default topic