---
path: /
surface: customer
domain: home
auth: signed-in (anonymous → redirected to /welcome)
source: apps/oshun/web/src/app/page.tsx
status: walked
last_walked:
  '2026-06-27 automated coverage reconciliation — existing Playwright and
  component coverage mapped for authenticated and anonymous entry, PWA relaunch,
  warm offline route availability, domain-unavailable routing, Home workspace
  regions, Tara/Arete/Veritas/Nyx/Nisaba/Metis continuations, daypart journeys,
  direct domain launches, quick actions, mixed recommendations, companion
  bridges, multi-device sync, and activity feed. Earlier 2026-05-29 runtime walk
  verified render, /v1 data (2xx), console/page-errors, expected content, and
  screenshot. Remaining gaps are listed below.'
---

# Home

## Purpose

Today's start. Tara-centered, with recommendations across all six domains, the
user's domain launch list, daypart-aware journey rails, and a shell-wide search
affordance. See [`V1/features.md`](../../../V1/features.md) for the home surface
scope.

## Entry points

- **Shell nav: Home (`g h` / index `1`)** — primary entry from any other route
- **Mobile bottom nav: Home tab** — index 0
- **Cold-start signed-in** — middleware lands here after sign-in if no `?next=`
- **PWA relaunch target** — when no other target persisted
- **Domain unavailable redirect** —
  `?unavailableDomain=<id>&unavailableReason=<reason>` surfaces a notice inline
- **Direct URL / bookmark** — yes (auth required)

## Layout regions

`page.tsx` mounts `ShellLayout` with `active="home"` and a single breadcrumb.
Inside, `HomeWorkspace` composes the home surface.

- **Header**: shell header — Home active
- **Resume banner**: `OnboardingResumeBanner` when user has unfinished
  onboarding
- **Anchor context rail**: `HomeAnchorContextRail`
- **Tara ritual continuation**: `HomeTaraRitualContinuationSection`
- **Veritas briefing**: `HomeVeritasBriefingSection`
- **Nisaba continuation**: `HomeNisabaContinuationSection`
- **Metis study continuation**: `HomeMetisStudyContinuationSection`
- **Daypart rail**: `DaypartJourneyRail`
- **Domain launch list**: `HomeDomainLaunchList`
- **Quick actions rail**: `HomeQuickActionsRail`
- **Mixed recommendations**: `MixedDomainRecommendationsLane`
- **Multi-device continuity**: `HomeMultiDeviceContinuityPanel`
- **Companion bridge**: `HomeCompanionBridgeRail`
- **Companion sections**: `HomeCompanionSections`
- **Footing summary strip**: `HomeFootingSummaryStrip`
- **Activity feed**: `ActivityFeed`
- **Continuation telemetry bridge**: `HomeContinuationTelemetryBridge` (no UI,
  instrumentation)

> The legacy `KpiGrid` component itself is **not** mounted by `HomeWorkspace`.
> The live home KPI surface is `HomeFootingSummaryStrip`, which emits
> `[data-kpi-grid]` under the Daily footing region. `DomainCardGrid` remains
> preview/scaffolding-only rather than part of the live home composition.

## States

- [ ] **Loading** — skeletons for each rail; no CLS; preserves layout
- [x] **Anonymous user** — middleware redirects to `/welcome` (never sees `/`).
      Covered by `apps/oshun/web/e2e/pwa-smoke.spec.ts` public root coverage.
- [x] **First-time signed-in user** — `OnboardingResumeBanner` visible if
      onboarding incomplete. Covered at component level by
      `apps/oshun/web/src/components/home/__tests__/OnboardingResumeBanner.test.tsx`.
- [x] **Returning user, full data** — all live V1 rails populate. Covered by
      `apps/oshun/web/e2e/home-dashboard-flow.spec.ts`.
- [ ] **Returning user, sparse data** — selected empty/fallback states are
      covered, but an all-rails sparse fixture still needs a route-level pass.
- [x] **Domain unavailable** —
      `?unavailableDomain=<id>&unavailableReason=<reason>` keeps Home usable,
      filters blocked recommendations, marks launch cards/switcher entries, and
      routes status-first. Covered by `home-tara-centering-continuity.spec.ts`,
      `shell-domain-unavailable-fallback.spec.ts`, and the Home continuation
      component tests.
- [x] **Error (recoverable)** — rail/API failures render honest fallback,
      unavailable, or partial-outage states instead of fabricated data. Covered
      by `home-arete-practice.spec.ts`, `home-veritas-briefing.spec.ts`,
      `home-nyx-perspective.spec.ts`, `home-nisaba-continuation.spec.ts`,
      `home-mixed-domain-recommendations.spec.ts`, and `ActivityFeed.test.tsx`.
- [ ] **Error (unrecoverable)** — `error.tsx` at segment level catches; reset
      button works
- [x] **Offline (warm cached shell)** — after authenticated warmup, `/` remains
      route-available offline. Covered by
      `apps/oshun/web/e2e/offline-shell-routes.spec.ts`.
- [ ] **Offline rail placeholders / cold Home load** — uncached rail behavior
      and cold offline Home boot still need route-specific assertions.
- [x] **Standalone PWA** — authenticated standalone relaunch restores the last
      route; unauthenticated standalone relaunch goes through welcome with the
      saved redirect. Covered by `apps/oshun/web/e2e/pwa-smoke.spec.ts`.
- [x] **PWA cold start with relaunch target** — `pendingLaunchTarget` resolves
      and redirects. Covered by `pwa-smoke.spec.ts`.
- [ ] **Reduced motion** — component-level animation guards exist on several
      rails, but Home still needs a route-level reduced-motion pass.

## Interactions

### Header / shell

Covered globally in [`shell/01-app-shell.md`](../../shell/01-app-shell.md);
home-specific interactions only here.

### Onboarding resume banner

- [x] **"Resume onboarding"** (button)
  - Function: navigates to `/onboarding?mode=resume`
  - Keyboard: Enter activates; included in tab order
  - Screen reader: button label is "Resume onboarding"; copy identifies the last
    saved step
  - Touch target: ≥ 44×44 px
  - Mobile: full-width banner; no horizontal scroll
  - Disabled when: onboarding complete (banner hidden, not disabled)
  - Offline behavior: routes to cached onboarding if available
  - Covered by `OnboardingResumeBanner.test.tsx`
- [ ] **"Dismiss"** (icon button)
  - Not part of the current V1 component; add only if product wants a
    session-scoped dismiss affordance.

### Tara ritual continuation section

- [x] **Primary ritual action** (native link)
  - Function: opens the recent Tara session when continuity exists; otherwise
    opens the daypart preset.
  - Keyboard / SR / touch: native anchor semantics; route-level keyboard
    activation covered.
  - Offline behavior: route-level offline cached shell is covered; pinned
    transcript/audio behavior remains a Tara-player concern.
  - Telemetry: `home_continuation_clicked` through shared continuation
    attributes.
  - Covered by `HomeTaraRitualContinuationSection.test.tsx`,
    `home-tara-centering-continuity.spec.ts`, and
    `home-continuation-analytics.spec.ts`.
- [x] **"Browse sessions"** (secondary link)
  - Function: navigates to
    `/domains/tara?origin=home&path=%2Fmeditate%2Fsessions`.
  - Covered by `HomeTaraRitualContinuationSection.test.tsx`.
- [x] **Unavailable-domain primary action** — preserves status-first routing
      with `unavailable=1`, reason, `path`, and `ref`. Covered by
      `HomeTaraRitualContinuationSection.test.tsx` and
      `home-tara-centering-continuity.spec.ts`.

### Veritas briefing section (`HomeVeritasBriefingSection`, `aria-label="Veritas briefing"`)

- [x] **Live briefing primary reader action** — opens the grounded reader from
      Home. Covered by `HomeVeritasBriefingSection.test.tsx` and
      `apps/oshun/web/e2e/home-veritas-briefing.spec.ts`.
- [x] **Endpoint outage fallback / Ask action** — shows honest unavailable copy
      with no fabricated claim and routes to Veritas Ask. Covered by
      `HomeVeritasBriefingSection.test.tsx` and `home-veritas-briefing.spec.ts`.
- [x] **Unavailable-domain primary action** — preserves status-first routing
      with `unavailable=1`, reason, reader `path`, and `ref`. Covered by
      `HomeVeritasBriefingSection.test.tsx` and `home-veritas-briefing.spec.ts`.
- [ ] **Trending / claims / sources full action sweep** — component renders
      these action targets, but the route-level Home spec currently clicks only
      the primary reader and fallback Ask paths.

### Nisaba continuation section (`HomeNisabaContinuationSection`, `aria-label="Nisaba continuation"`)

- [x] **Live primary / library / notebook / support actions** — each
      `router.push(...)` to its Nisaba action href. Covered by
      `apps/oshun/web/e2e/home-nisaba-continuation.spec.ts`, which primes the
      authenticated shell, seeds a real `/v1/nisaba/notebooks` record through
      the BFF, verifies the browser reads that exact notebook card from
      `/v1/nisaba/notebooks?status=active`, and clicks the notebook, library,
      support, and primary passage actions.
- [x] **Unavailable-domain primary action** — preserves status-first routing
      with `unavailable=1`, reason, passage `path`, and `ref`. Covered by
      `home-nisaba-continuation.spec.ts` with the same real BFF notebook seed.
- [x] **Endpoint outage fallback** — daily passage and notebook endpoint
      failures render the curated fallback thread and route to the fallback
      passage. Covered by `home-nisaba-continuation.spec.ts`.
- [ ] **Real daily-passage seed writer** — not exposed for this Home scenario;
      the spec keeps a deterministic `GET /v1/nisaba/passages/daily` fixture for
      `Yoga Sutra 1.2` while the notebook continuation uses real BFF write/read
      infrastructure.

### Metis study continuation section

- [x] **Primary resume action** — opens the strongest saved Metis return.
      Covered by `HomeMetisStudyContinuationSection.test.tsx`; the browser route
      handoff from Home into `/domains/metis?origin=home&path=%2Fcourses` is
      covered by `metis-lesson-completion.spec.ts`.
- [x] **Curated course/assessment fallback** — routes to the curated assessment
      path when there are no saved Metis items. Covered by
      `HomeMetisStudyContinuationSection.test.tsx`.
- [x] **Unavailable-domain primary action** — preserves status-first routing
      with `unavailable=1`, reason, assessment `path`, and `ref`. Covered by
      `HomeMetisStudyContinuationSection.test.tsx`.

### Daypart journey rail

`DaypartJourneyRail.tsx`

- [x] **Current daypart summary** — resolves the active arc from local hour or
      onboarding routine preference and exposes the current action. Covered by
      `DaypartJourneyRail.test.tsx` and
      `apps/oshun/web/e2e/daypart-journey-home.spec.ts`.
- [x] **Journey cards/list** — renders the canonical morning, midday, and
      evening journeys and marks the active one. Covered by
      `DaypartJourneyRail.test.tsx` and `daypart-journey-home.spec.ts`.
- [x] **Journey step actions** — route and assistant actions hand off to
      concrete shell/domain destinations; one route handoff is clicked at E2E
      level. Covered by `DaypartJourneyRail.test.tsx`,
      `daypart-journey-home.spec.ts`, and `home-continuation-analytics.spec.ts`.
- [ ] **Keyboard roving / tablist behavior** — not applicable to the current
      list implementation, but no explicit keyboard traversal spec exists yet.
- [ ] **Reduced motion route check** — no autoplay is present, but a
      `prefers-reduced-motion` Home route assertion is still pending.

### Domain launch list

- [x] **Each domain item** (button-like card)
  - Function: navigates to canonical domain route
  - Keyboard: Enter / Space route through the same handler
  - SR: `aria-label` combines the domain label with the launch summary
  - Covered by `HomeDomainLaunchList.test.tsx`, `home-dashboard-flow.spec.ts`,
    and `home-domain-narrative-order.spec.ts`.
- [x] **Unavailable domain item** — marks the card, shows the reason, and routes
      status-first. Covered by `HomeDomainLaunchList.test.tsx` and
      `shell-domain-unavailable-fallback.spec.ts`.
- [ ] **Reorder handle** — not present in current Home V1; personalized ordering
      comes from onboarding/preferences rather than in-place drag-and-drop.
- [ ] **Add/remove domain** — not present in current Home V1; settings/profile
      domain preference management is outside this surface.

### Domain card grid (preview-only)

`DomainCardGrid` is not rendered on the live home surface (preview scaffolding
only); direct domain launches ship via `DomainSwitcherEntryPanel` and
`HomeDomainLaunchList`. Documented here for the preview/skeleton state:

- [x] **Six cards**: Tara, Arete, Veritas, Nyx, Nisaba, Metis
  - Each navigates to its domain root
  - SR announces domain + tagline
  - Marks unavailable domains with `data-domain-unavailable`, removes the
    engagement/actions preview, and routes status-first
  - Covered by `DomainCardGrid.test.tsx`; live Home route launch behavior is
    covered through `HomeDomainLaunchList` instead.

### Quick actions rail

`HomeQuickActionsRail.tsx`

- [x] **Each action button** — six fixed journeys render in Tara, Arete,
      Veritas, Nyx, Nisaba, Metis order with daypart-aware hrefs and
      status-first unavailable routing. Covered by
      `HomeQuickActionsRail.test.tsx` and
      `apps/oshun/web/e2e/home-quick-actions.spec.ts`.

> `CrossDomainQuickActionsMenu` is **not** rendered by the home quick-actions
> rail — it lives in `ShellLayout` and `ExploreDashboard`.

### Mixed recommendations lane

- [x] **Recommendation cards** (link) — live and fallback slates render in
      Tara-centered, onboarding-guided, preference-aware, or Tara-theme order;
      primary links route through hydrated domain paths. Covered by
      `MixedDomainRecommendationsLane.test.tsx`,
      `CrossDomainRecommendations.test.tsx`,
      `home-mixed-domain-recommendations.spec.ts`, and
      `home-mixed-domain-recommendations-analytics.spec.ts`.
- [x] **Why copy / reason badges** — cards render explanation copy,
      source-context labels, fit tiers, and reason badges such as Good timing,
      Practice handoff, Grounded context, Perspective handoff, Passage
      companion, Source lineage, Study companion, Sky to text, and Because you
      saved. Covered by the recommendation unit and E2E specs.
- [x] **Feedback controls** — "More like this", "Less like this", and "Hide"
      preserve the current card, show future-feedback copy, emit telemetry, and
      POST feedback. Covered by `CrossDomainRecommendations.test.tsx`.
- [x] **End of lane** — "Show more" / "Show fewer" expands from four to six
      cards. Covered by recommendation unit tests and
      `home-mixed-domain-recommendations.spec.ts`.

### Multi-device continuity panel

- [x] **Sync health signals** — shows profile/preference sync status and phone +
      web continuity copy without advertising unbuilt watch/glance capability.
      Covered by `HomeMultiDeviceContinuityPanel.test.tsx` and visible in
      `home-dashboard-flow.spec.ts`.
- [x] **"Open sync controls"** — links to `/profile` as the control surface.
      Covered by `HomeMultiDeviceContinuityPanel.test.tsx`.
- [x] **"Refresh sync"** — appears when sync is delayed and calls
      `refresh({ force: true })`. Covered by
      `HomeMultiDeviceContinuityPanel.test.tsx` and the Home panel status case
      in `multi-device-handoff-deepening.spec.ts`.
- [ ] **Active device session management** — handled under Profile/auth flows,
      not the Home panel.
- [ ] **Offline disabled state** — Home panel sync-delay behavior is covered; a
      Home-specific offline disabled-state assertion is still pending.

### Companion bridge rail

- [x] **Domain companion bridge cards** — renders Arete, Veritas, Nyx, Nisaba,
      and Metis in canonical/current-preference order with journey-aware action
      hrefs. Covered by `HomeCompanionBridgeRail.test.tsx`,
      `home-tara-centering-continuity.spec.ts`, and
      `home-domain-narrative-order.spec.ts`.
- [x] **Unavailable companion bridge** — marks unavailable domains and routes to
      status-first launches with reason/ref. Covered by
      `HomeCompanionBridgeRail.test.tsx` and
      `home-tara-centering-continuity.spec.ts`.
- [ ] **Mobile app / Telegram CTAs** — not part of the current Home companion
      bridge rail; `/welcome/download` is covered by PWA install smoke instead.

### Activity feed

- [x] **Item list** — recent cross-domain activity renders with domain tags,
      icon, color strip, relative timestamp, and empty state. Covered by
      `ActivityFeed.test.tsx` and `home-dashboard-flow.spec.ts`.
- [x] **Item action click** → source surface. Covered by
      `home-dashboard-flow.spec.ts`.
- [ ] **Filter (all / mentions / system)** — no filter tablist exists in the
      current V1 Home feed.
- [x] **"View all"** → `/activity`. Covered by `ActivityFeed.test.tsx`.
- [ ] **Realtime updates** — the current feed fetches once and refreshes
      relative timestamps every 30s; new-item push/polling is not implemented
      here.
- [x] **Hydration-safe timestamps** — timestamp rendering starts from an
      SSR-safe sentinel and then updates on the client. Covered by
      `ActivityFeed.test.tsx` relative timestamp assertions.

## Automated Coverage

- **Route-level Home workspace**:
  `apps/oshun/web/e2e/home-dashboard-flow.spec.ts`,
  `home-tara-centering-continuity.spec.ts`, `home-quick-actions.spec.ts`,
  `daypart-journey-home.spec.ts`, `home-domain-narrative-order.spec.ts`, and the
  Arete / Veritas / Nyx / Nisaba Home continuation specs cover the populated
  authenticated surface, direct launches, daypart routes, continuation actions,
  companion order, and domain-unavailable status-first behavior.
- **Recommendation lane**: `home-mixed-domain-recommendations.spec.ts`,
  `home-mixed-domain-recommendations-analytics.spec.ts`,
  `MixedDomainRecommendationsLane.test.tsx`, and
  `CrossDomainRecommendations.test.tsx` cover live/fallback ordering,
  suppression rules, saved-source labels, Show more, primary route taps,
  impressions, taps, and feedback POSTs.
- **PWA/offline/auth shell**: `pwa-smoke.spec.ts`,
  `offline-shell-routes.spec.ts`, and
  `shell-domain-unavailable-fallback.spec.ts` cover anonymous root redirect,
  standalone relaunch, warm offline Home availability, real SW fallback, and
  Home continuity when a domain is unavailable.
- **Component rails**: Home component tests cover onboarding resume, Tara,
  Veritas, Metis, quick actions, daypart journeys, domain launch list, companion
  bridge rail, multi-device continuity, and activity feed behavior.

## Data & contracts

- **Reads**: `ActivityFeed` calls
  `buildOshunBffUrl('/v1/activity', { limit: 5 })`. Home domain rails also fetch
  their own BFF endpoints; verified examples include Nisaba's real
  `/v1/nisaba/notebooks?status=active` browser read in
  `home-nisaba-continuation.spec.ts` after the test seeds a BFF notebook. The
  daily Nisaba passage remains fixture-backed in that spec because no
  deterministic daily-passage writer is exposed for Home setup.
- **Writes**: recommendation feedback posts to `/v1/recommendations/feedback`;
  continuation clicks/impressions emit browser analytics. No Home-level
  onboarding dismiss, domain reorder, or "not for me" write exists in the
  current V1 surface.
- **Realtime**: activity feed fetches once on mount and refreshes relative
  timestamps every 30s; live new-item push/polling is not implemented on Home.
- **Caching**: SSR'd with `dynamic = 'force-dynamic'` (per `page.tsx`);
  individual rails SWR within client
- **Auth/role check**: middleware redirects anonymous to `/welcome`

## Cross-references

- Shell: [`shell/01-app-shell.md`](../../shell/01-app-shell.md),
  [`shell/04-auth-session.md`](../../shell/04-auth-session.md)
- Sibling routes:
  - [`explore.md`](./explore.md) — full discovery view
  - [`activity.md`](./activity.md) — full activity history
  - [`library.md`](./library.md) — saved content
  - [`messages.md`](./messages.md) — inbox
  - [`switcher.md`](./switcher.md) — domain switcher
- Domain entries:
  - [`../03-tara/tara.md`](../03-tara/tara.md)
  - [`../04-arete/`](../04-arete/), [`../05-veritas/`](../05-veritas/),
    [`../06-nyx/`](../06-nyx/), [`../07-nisaba/`](../07-nisaba/),
    [`../08-metis/`](../08-metis/)
- Journey:
  [`../../journeys/install-as-pwa.md`](../../journeys/install-as-pwa.md)
- Feature spec: [`V1/features.md`](../../../V1/features.md)
- Architecture:
  [`V1/ARCHITECTURE.md`](../../../V1/ARCHITECTURE.md#customer-web--appsoshunweb)

## Open questions / known gaps

- [x] Confirm exact set of rails that ship on day-1 vs. behind feature flag.
      `HomeWorkspace` currently mounts the V1 rail set documented above, and
      `home-dashboard-flow.spec.ts` asserts the explicit region model.
- [ ] Document the recommendation engine's surface contract (input + ranking
      signals). The Home lane has strong behavioral coverage, but the contract
      itself still needs a canonical architecture note.
- [ ] Snapshot expected layout at each breakpoint (320 / 390 / 640 / 1024 /
      1440). Current automation covers 375 / 768 / 1180 / 1440 plus
      desktop/laptop topography, but not the exact breakpoint matrix listed
      here.
