---
path: /domains/veritas/topics/[topicId]
surface: customer
domain: veritas
auth: signed-in
source: apps/oshun/web/src/app/domains/veritas/topics/[topicId]/page.tsx
status: walked
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'
---

# Topic Hub Workspace · Veritas (by topicId)

## 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`](./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`](./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 `null` →
      `VeritasTopicNotFoundPanel` 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`](./domains-veritas-topics.md). The route
param flows through into telemetry:

- [ ] **Follow toggle** — `trackVeritasTopicFollowed` /
      `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 change** — `trackVeritasTopicAlertFrequencyUpdated`
      payloads carry the same `topicId` and `topicTitle` derived from the
      resolved topic
- [ ] **Inspection telemetry** — `trackVeritasInspectionOpened` 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`](./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

- Component:
  `apps/oshun/web/src/components/domains/veritas/VeritasTopicHubWorkspace.tsx`
  (shared with the default route)
- Default-route counterpart:
  [`domains-veritas-topics.md`](./domains-veritas-topics.md)
- Story workspace target:
  [`domains-veritas-story-id.md`](./domains-veritas-story-id.md) (links to topic
  via `STORY_TOPIC.slug`)
- Claim detail handoff:
  [`domains-veritas-claims-claimId.md`](./domains-veritas-claims-claimId.md)
- Customer-facing alternate: [`veritas-topic.md`](./veritas-topic.md)
- Feature spec: [`V1/features.md`](../../../V1/features.md#veritas)

## 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
