---
path: /tara
surface: customer
domain: tara
auth: signed-in
source: apps/oshun/web/src/app/tara/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. 2026-06-27 Codex Tara hub
  addendum — signed-in /tara render against the real BFF room model, canonical
  metadata, presentational Lilith subnav, default here/next sitting links, begin
  CTA to /tara/sit/[id], static teacher rows, breathwork + Nisaba handoffs,
  live-class booking reference, and standalone PWA relaunch are covered by the
  E2E references below.
---

# Tara · sit

## Purpose

The Tara domain hub. "A few minutes, seated." Today's sit, the course, and the
teachers. The experiential and thematic center of V1. Built on the Lilith design
system (`TaraRoom`) backed by `getTara()`.

## Entry points

- **Domain card on `/`** (`DomainCardGrid`) — primary cold-entry from home
- **Tara ritual continuation rail** on `/` — direct to last ritual or domain hub
- **Domain switcher** in shell header / `/switcher`
- **Shortcut `g`-chord** (if mapped to Tara) — verify in
  `shell/06-keyboard-a11y.md`
- **PWA shortcut** (if defined in `manifest.json` `shortcuts[]`)
- **Direct URL / bookmark** — yes (auth required)
- **Deep link from notification** — Tara ritual reminder push
- **Search result** — domain card surfaces in `/search` for relevant queries

## Layout regions

`page.tsx` is a thin server component: `await getTara()` → `<TaraRoom>`. The
`TaraRoom` is a Lilith design-system room composition
(`apps/oshun/web/src/components/lilith/rooms.tsx`, `TaraRoom`, lines 61–337).

- **Header**: `LCustomerNav active="explore"`, then `LSubNav active="today"`
  with items **Today · Courses · Teachers · Library** (lines 67–75). These four
  `LSubNav` items have no `href` in source — they render as presentational tabs.
- **Masthead row**: eyebrow "Tara · sit", display title "A few minutes,
  _seated_.", and an `LAIDisclosure` "Curated · by editor + signal" (lines
  90–104)
- **Body grid** (`1.4fr 1fr` desktop; one-column mobile stack):
  - **Left column** — **today's sit card**: eyebrow "Today's sit · 12 min",
    `LDisplay` title (`data.todaysSit.title`), italic description, a circular
    play `Link` to `/tara/sit/<id>` (`aria-label="Begin sitting · {title}"`,
    `data-telemetry-event="tara_sit_started"`,
    `data-telemetry-surface="tara_hub"`), and a text `Link` "Begin · {N} min"
    plus a byline eyebrow (teacher · narrated · pathLabel · session NN of M) and
    an `LDots` progress strip (lines 109–170). Then a rule and **"The course ·
    sittings"** list — one `Link` per `data.sittings[]` row to `/tara/sit/<id>`,
    aria-labelled "Replay/Begin/Preview sitting {index}: {title}" by row state
    (lines 174–224).
  - **Right column** — **Teachers** grid: one row per `data.teachers[]` (initial
    avatar, name, "{sittings} sittings · {tone}", decorative `↗` glyph) — the
    rows are presentational `<div>`s, not links (lines 231–281). Its responsive
    left border replaces the former standalone vertical rule and becomes a
    horizontal rule before Teachers on mobile. Then a rule + **"Breath ritual ·
    daily"** `LCard` with the ritual title, duration/pattern chips, and a
    "Begin" chip `Link` to `/meditate/breathwork` (built via
    `buildHydratedWebDomainRoutePath('tara', …)`,
    `aria-label="Begin daily breath ritual: {title}"`, lines 287–306). Then,
    when `data.nisabaPassageCue` is present, a **"Read deeper in Nisaba"** cue
    `Link` to `nisabaPassageCue.href`
    (`aria-label="Read the related passage in Nisaba"`, lines 307–330).
- **Below the grid**: `<TaraLiveClassBookingCard />` (line 333)
- **Footer**: legal / status links per shell

## States

- [x] **Loading** — `getTara()` is awaited server-side and no local
      `loading.tsx` exists at this segment; the route blocks until the room
      model is ready
- [ ] **First-time visitor to Tara** — onboarding overlay or domain primer
- [x] **Returning, daily sit available** — today's sit is prominent and matches
      the real `/v1/tara/room` model
- [ ] **Returning, no sit today** — calm empty state with course continuation
- [ ] **Streak active** — streak chip visible
- [ ] **Streak broken** — recovery copy ("welcome back"); no shaming
- [ ] **Error (recoverable)** — Tara data fetch fails; retry; sibling rails
      still load
- [ ] **Offline** — last-loaded Tara view rendered from BFF cache;
      transcripts/audio pinned for current sit if user opted in
- [ ] **Gated** — if Tara content requires Lilith policy approval, gated content
      marked clearly with reason
- [x] **Standalone PWA** — cold-launch lands here cleanly if relaunch target was
      `/tara`

## Interactions

Current E2E evidence:

- `apps/oshun/web/e2e/tara-hub.spec.ts` — `/tara` signed-in hub render, real BFF
  room read, metadata, presentational subnav, default fresh-path sitting links
  (`here` + `next`), begin CTA into `/tara/sit/[id]`, static teacher rows,
  breathwork handoff, Nisaba handoff, standalone PWA relaunch, and mobile
  overflow safety
- `apps/oshun/web/e2e/tara-live-class-booking.spec.ts` — web live-class booking
  card, lineage disclosure, payment receipt, calendar entry, and lineage-fund
  receipt route
- `apps/oshun/bff/src/tara/room.test.ts` — BFF overlay rules for completed
  sittings (`done`/Replay), first unfinished (`here`/Begin), skipped completion,
  teachers, ritual, and Nisaba cue

### Sub-nav (`LSubNav`)

- [x] **Today / Courses / Teachers / Library** (tabs)
  - Function: presentational tabs with `active="today"`; the four items have no
    `href` in source (lines 67–75) — they do not navigate today
  - Keyboard: tab order matches DOM source order
  - Screen reader: announces label only

### Today's sit card

- [x] **Begin play button** (circular `Link`)
  - Function: navigates to `/tara/sit/<data.todaysSit.id>` (lines 128–149)
  - Screen reader: `aria-label="Begin sitting · {title}"`
  - Touch target: 56×56 (circular)
  - Telemetry: `data-telemetry-event="tara_sit_started"`,
    `data-telemetry-surface="tara_hub"`
- [x] **"Begin · {N} min" text link** (`Link`)
  - Function: same target — `/tara/sit/<data.todaysSit.id>` (lines 152–157);
    `N = Math.round(durationSeconds / 60)`
- [x] **Byline eyebrow** — non-interactive; teacher · narrated · pathLabel ·
      session NN of M
- [x] **`LDots` progress strip** — presentational; `count = pathTotal`,
      `current = sessionIndex − 1`

### "The course · sittings" list

- [x] **Sitting row** (`Link` per `data.sittings[]`)
  - Function: navigates to `/tara/sit/<row.id>` (lines 189–221)
  - Screen reader: `aria-label` is state-dependent — "Replay sitting {index}:
    {title}" (done), "Begin sitting {index}: {title}" (here), or "Preview
    sitting {index}: {title}" (locked)
  - Glyph: `✓` done · `▸` here · `○` locked; the "here" row gets a tinted
    background
  - Browser E2E covers the default fresh-path `here` and `next` states. The
    `done`/Replay overlay is covered at the real BFF room-model layer and should
    get a seeded browser-progress slice when completion seeding is made
    deterministic for `/tara`.

### Teachers grid

- [x] **Teacher row** (presentational `<div>`, **not a link**)
  - Function: visually shows initial avatar, name, "{sittings} sittings ·
    {tone}", and a decorative `↗` glyph (lines 233–280) — there is **no**
    `/tara/teacher/<id>` link from the hub
  - Screen reader: announces as static text

### Breath ritual · daily

- [x] **"Begin" chip** (`LChip` inside a `Link`)
  - Function: navigates to `/meditate/breathwork` (href built via
    `buildHydratedWebDomainRoutePath('tara', '/meditate/breathwork', { origin: 'home' })`,
    lines 296–304)
  - Screen reader: `aria-label="Begin daily breath ritual: {title}"`
- [x] **Duration / pattern chips** — presentational `LChip`s

### Read deeper in Nisaba (cross-domain cue)

- [x] **Passage cue** (`Link`, only when `data.nisabaPassageCue` is set)
  - Function: navigates to `data.nisabaPassageCue.href` (lines 313–328)
  - Screen reader: `aria-label="Read the related passage in Nisaba"`
  - Label: `data.nisabaPassageCue.label`

### Live-class booking

- [x] **`<TaraLiveClassBookingCard />`** (line 333) — see the component for its
      own booking interactions

### Cross-domain bridges

Verify presence and behavior of any link/quick-action that hops into another
domain (e.g., a Tara session that ends with a Nisaba reading).

- [x] **Cross-domain CTA** (if present)
  - Function: navigates to other domain
  - Telemetry: cross*domain*<from>\_<to>

## Data & contracts

- **Reads**: `getTara()` from `@/lib/lilith-data/tara`
- **Writes**: ritual start events flow to Psyche session envelope
- **Realtime**: session envelope for active sit (separate route)
- **Caching**: server fetch; revalidate per `getTara` policy; SW caches the
  rendered HTML for offline reload
- **Auth/role check**: middleware enforces signed-in

## Cross-references

- Shell: [`shell/01-app-shell.md`](../../shell/01-app-shell.md)
- Sibling Tara routes (one file per route in this folder):
  - (list grows as files are authored)
- Domains-namespace alternate: `/domains/tara/*` — see
  [`coverage`](../../matrix/coverage.md)
- Cross-domain partners:
  - [`../04-arete/`](../04-arete/) — Arete streak/recovery interplay
  - [`../07-nisaba/`](../07-nisaba/) — Nisaba reading hand-off
  - [`../06-nyx/`](../06-nyx/) — Nyx perspective bridge from contemplation
- Feature spec: [`V1/features.md`](../../../V1/features.md#tara)
- Architecture: [`V1/ARCHITECTURE.md`](../../../V1/ARCHITECTURE.md#tara)
- E2E coverage:
  - `apps/oshun/web/e2e/tara-hub.spec.ts`
  - `apps/oshun/web/e2e/tara-live-class-booking.spec.ts`
  - `apps/oshun/web/e2e/home-tara-centering-continuity.spec.ts`
- BFF/unit coverage:
  - `apps/oshun/bff/src/tara/room.test.ts`
  - `apps/oshun/bff/src/routes/domain-stubs-postgres.test.ts`
- Journeys traversing Tara:
  - [`../../journeys/install-as-pwa.md`](../../journeys/install-as-pwa.md)
    (touches Tara via PWA cold-start)

## Open questions / known gaps

- [ ] Enumerate every sub-route under `/tara/*` and `/domains/tara/*`; verify
      which surfaces are V1-shipping vs. internal
- [ ] Add a seeded browser-progress slice for completed Tara sittings so
      `done`/Replay rows are proven in the web hub, not only in BFF room-model
      tests
- [ ] Confirm whether streak data is read from Arete or Tara — affects the
      cross-domain bridge story
- [ ] Document the practice-picker flow (separate file if it's a route)
- [ ] Confirm Lilith tone policy gates that apply to Tara teacher/practice
      content (see [`V1/features.md#lilith-persona-policy`](../../../V1/features.md#lilith-persona-policy))
