---
path: /domains/tara/search
surface: customer
domain: tara
auth: signed-in
source: apps/oshun/web/src/app/domains/tara/search/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'
  '2026-06-28 focused automated walk (Playwright + real dev infra) — idle,
  recent-memory, debounce/loading, synonym expansion, spelling suggestion, empty
  result, reduced-motion CSS, back navigation, Enter persistence, clear/remove
  controls, and routed course/teacher/collection result opens verified. Evidence:
  apps/oshun/web/e2e/tara-scoped-search.spec.ts'
---

# Tara — search

## Purpose

A Tara-scoped full-text search that complements the shell-wide `/search` view.
Searches inside the Tara content set with debounced input, spelling suggestions
("Did you mean…?"), highlighted snippets, trending queries, recent-query memory,
and result sections for Meditations / Courses / Teachers / Collections.

## Entry points

- **Tara hub** — verify the search affordance on `/tara` that links here
- **Direct URL / bookmark** — yes
- **Domain back-stack** — `router.back()` wired into `onBack`

## Layout regions

`page.tsx` is a `'use client'` thin wrapper that renders
`<TaraSearchEngine onBack={() => router.back()} />`.

Inside `TaraSearchEngine` (`TaraSearchEngine.tsx`):

- **Header** — back button + Search icon header
- **Search input** — text input with `DEBOUNCE_MS = 250`, clear button (×)
- **Spelling suggestion banner** — "Did you mean …?" when `SpellingSuggestion`
  is produced
- **Trending searches** — `TrendingSearch[]` chips (up / stable / new
  indicators)
- **Recent searches** — from `localStorage['tara-recent-searches']` (max
  `MAX_RECENT_SEARCHES = 10`)
- **Result sections** — Meditations / Courses / Teachers / Collections, each
  with highlighted matches (`SEARCH_STYLES` `tse-highlight-pulse` keyframe,
  disabled under `prefers-reduced-motion: reduce`)
- **Empty / loading / error states** — `Loader2` spinner, `AlertCircle` error,
  empty-query landing

## States

- [x] **Idle (no query)** — trending + recent searches visible; no result
      sections
- [x] **Typing (debounce)** — `Loader2` spinner; shimmer skeleton via
      `tse-shimmer` keyframe
- [x] **Results populated** — sections render in declared order
- [x] **Spelling suggestion** — banner offers a corrected query; tapping it
      replaces the input
- [x] **Empty result** — landing copy advising to try different keywords
- [ ] **Error state** — no implemented runtime error branch exists in
      `TaraSearchEngine`; `AlertCircle` is used for spelling suggestions, not a
      failed-search error
- [x] **Recent persisted** — query strings stored in
      `localStorage['tara-recent-searches']`
- [x] **Synonym expansion** — `SYNONYM_MAP` expands terms (meditation,
      mindfulness, session, practice, …) — verify hits are highlighted

## Interactions

### Header

- [x] **Back** (button) — `router.back()` via `onBack`

### Search input

- [x] **Input** (text)
  - Function: updates query; 250 ms debounce before computing results
- [x] **Clear (×)** (button) — clears query
- [x] **Submit on Enter** — persists the current query to recent searches;
      results still follow the 250 ms debounce

### Spelling suggestion banner

- [x] **Apply suggestion** — replaces query with suggested string

### Trending chip

- [x] **Chip click** — populates query

### Recent chip

- [x] **Chip click** — populates query
- [x] **Clear recent** — "Clear all" empties
      `localStorage['tara-recent-searches']`

### Result row (per section)

- [ ] **Open — meditation** — search IDs (`med-001` … `med-012`) still do not
      map to a real Tara sitting/player route, so rows expose no href
- [x] **Open — course** — `crs-001` … `crs-006` map to
      `/domains/tara/courses/tara-course-001` …
      `/domains/tara/courses/tara-course-006`
- [x] **Open — teacher** — `tch-001` … `tch-006` map to
      `/domains/tara/teachers/tara-teacher-001` …
      `/domains/tara/teachers/tara-teacher-006`
- [x] **Open — collection** — collection rows map to
      `/domains/tara/collections?collection=<id>`
- [x] **Highlighted match span** — `tse-highlight-pulse` keyframe; honors
      reduced motion (verify)

## Data & contracts

- **Reads**:
  - Tara fixture data (`@/lib/tara/tara-simulation-data`)
  - `localStorage['tara-recent-searches']`
- **Writes**:
  - `localStorage['tara-recent-searches']` — bounded to 10 entries
- **Realtime**: _None._
- **Caching**: client-only
- **Auth/role check**: shell middleware
- **Telemetry**: _None observed in this view._

## Automation Evidence

- `apps/oshun/web/e2e/tara-scoped-search.spec.ts`
  - `walks idle, recent-memory, debounce, synonym, suggestion, empty, and reduced-motion states`
  - `routes mapped result rows into real Tara destination pages and preserves the back affordance`
- `apps/oshun/web/src/components/domains/tara/TaraSearchEngine.tsx`
  - stable `data-tara-search-*` hooks for states, controls, result sections,
    rows, route hrefs, and reduced-motion assertions

## Cross-references

- Sibling Tara routes:
  - [`tara.md`](./tara.md),
    [`domains-tara-analytics.md`](./domains-tara-analytics.md),
    [`domains-tara-collections.md`](./domains-tara-collections.md),
    [`domains-tara-courses-id.md`](./domains-tara-courses-id.md),
    [`domains-tara-programs.md`](./domains-tara-programs.md),
    [`domains-tara-sounds.md`](./domains-tara-sounds.md),
    [`domains-tara-teachers.md`](./domains-tara-teachers.md),
    [`domains-tara-teachers-id.md`](./domains-tara-teachers-id.md)
- Shell-wide search:
  [`../02-home-discovery/search.md`](../02-home-discovery/search.md)
- Component sources:
  - `apps/oshun/web/src/components/domains/tara/TaraSearchEngine.tsx`
- Feature spec: [`V1/features.md#tara`](../../../V1/features.md#tara)

## Open questions / known gaps

- [ ] Confirm whether `/domains/tara/search` should route through the same
      `/v1/search?domain=tara` BFF endpoint that `/search` uses, or remain a
      local fixture-driven engine
- [x] Trending-search calculation is hard-coded in `TRENDING_SEARCHES`; no BFF
      trending endpoint is read by this route
- [x] Reduced-motion handling is covered for highlighted matches and animated
      search rows via `prefers-reduced-motion: reduce`
- [x] Tara-scoped recents intentionally use `tara-recent-searches`; shell-wide
      search continues to use `oshun-search-recent-v1`
- [ ] Meditation results need a canonical player-route mapping before their row
      click can open a real destination
