# Meditation Libraries — Architecture

> Platform-agnostic meditation engine libraries. Consumed by the Tara domain but
> designed for reuse by any meditation application.

---

The meditation libraries are eight TypeScript packages that live under
`libs/meditation/` and form the engine layer for any meditation application in
the Oshun monorepo. They handle everything a meditation app does — playing
audio, running timers, guiding breathing exercises, managing sessions, tracking
user progress, working offline, and recording analytics — without being tied to
any particular UI framework, database, or application.

The core design decision is a clean separation between **logic** and
**application**. The `libs/meditation/` packages contain logic that is identical
regardless of how or where the app runs: timing algorithms, audio playback,
streak calculation, content versioning. The application layers — `apps/tara/`,
`libs/tara/`, and wherever Lilith consumes them — supply the parts that vary by
platform: REST endpoints, push notifications, database schemas, UI components,
and app store metadata.

A new engineer working on Tara's meditation features will mostly interact with
these eight libraries. Understanding their boundaries, shared patterns, and
dependency structure makes it much easier to know where to add a new capability
or trace a bug.

---

## 1. Domain Summary

The `libs/meditation/` directory contains eight platform-agnostic libraries that
implement all core capabilities a meditation app needs. They are **not an
application domain** — they have no API, no database, and no UI. They are an
engine layer designed to be consumed by Tara and Lilith and any future
meditation applications in the Oshun monorepo.

The key design decision is the separation of concerns:

- **`libs/meditation/`** handles all logic that is the same regardless of
  platform: timing, audio management, breathing guidance, session tracking,
  progress calculation, and offline management.
- **`apps/tara/`** and **`libs/tara/`** handle everything platform-specific: API
  endpoints, UI components, database persistence, push notifications, app store
  integration.

---

## 2. Library Architecture

The diagram below shows how data and control flow through the eight packages
during a typical meditation session. `meditation-core` anchors the bottom of the
stack as the shared type layer; the engine packages (player, timer, session,
breathing, progress, offline) form the middle; and `meditation-analytics` sits
alongside as a standalone tracking concern.

```
            @oshun/meditation-core
        (branded types, content/session models,
         duration/date/format/validation utilities)

                @oshun/meditation-player
              (audio playback, mixing, streaming,
               caching, visualization, background)
                        |
                        |   plays audio for
                        v
            @oshun/meditation-session
          (session lifecycle, persistence,
           analytics tracking, scheduling)
          /           |            \
         /            |             \
@oshun/meditation-   @oshun/meditation-   @oshun/meditation-
    timer                breathing             offline
 (countdown,          (patterns,          (download queue,
  bells, ambient,      guidance,           storage, versioning,
  presets, haptics)    visualization,       suggestions, network)
                       haptics, history)
         \            |             /
          \           |            /
            @oshun/meditation-progress
          (streaks, statistics, achievements,
           milestones, export, sync)

            @oshun/meditation-analytics
        (privacy-conscious event tracking,
         consent gating, session summaries)
```

The diagram shows **conceptual data flow** within an application.
`meditation-core` is the shared type/utility layer; `meditation-analytics` is a
small standalone event-tracking layer. At the **package level**, the libraries
do not import each other — they share only the `eventemitter3` runtime
dependency (six of the eight packages) and an optional `react` peer dependency.
The `meditation-player` package additionally depends on `@oshun/contracts` for
its shared playback-rate policy. Integration between meditation packages happens
at the application layer. `meditation-core` and `meditation-analytics` use
neither `eventemitter3` nor a React peer dependency.

---

## 3. Library Descriptions

Each library has a well-defined responsibility. The descriptions below give a
sense of what each package owns and which classes an engineer will encounter
first.

### `@oshun/meditation-core`

Shared primitives consumed conceptually by every meditation package (the
dependency is logical, not a package import):

- Branded identifier and value types (`SessionId`, `TrackId`, `ContentId`,
  `DurationSeconds`, `Timestamp`, `Percentage`, `ByteSize`, …)
- Content and session models (`ContentItem`, `AudioTrack`, `MeditationSession`,
  `SessionResult`, `InterruptionRecord`)
- Literal-union vocabularies (`MeditationCategory`, `SessionType`,
  `SessionState`, `PlaybackState`, `ContentKind`, `Platform`)
- Utility modules: `duration`, `dates`, `format`, `validation`

**Build**: `@nx/js:tsc` | **Runtime dep**: none

### `@oshun/meditation-player`

The most feature-rich library. Provides the complete audio playback engine with:

- `MeditationPlayer` — event-driven player with load/play/pause/seek/stop
- `PlaybackQueue` — ordered queue with shuffle and repeat
- `AudioMixer` — multi-layer mixing with ducking and volume automation
- `AudioVisualizer` — real-time frequency analysis and beat detection
- `StreamingManager` — adaptive bitrate streaming with network monitoring
- `AudioCacheManager` + `AudioPreloader` — local cache with Service Worker
- Platform-abstracted background audio and audio session management

**Build**: `@nx/js:tsc` | **Runtime dep**: `eventemitter3`

### `@oshun/meditation-timer`

Cross-platform countdown timer with three phases (preparation, meditation,
wind-down):

- `MeditationTimer` — event-driven countdown with phase management and
  wall-clock drift correction
- `PresetManager` — 12 built-in presets across quick/standard/extended/pomodoro/
  sleep categories, plus custom presets and favorites
- `BellPlayer` — six built-in bell-sound constants (drawn from an 11-value
  `BellType` union) with start/end/interval/warning/preparation-end triggers
- `AmbientPlayer` — seven built-in ambient-sound constants (drawn from a
  27-value sound-type union) and three curated mixes
- Platform-abstracted background operation (Wake Lock, Notifications, Web Locks)
  and haptics

**Build**: `@nx/js:tsc` | **Runtime dep**: `eventemitter3`

### `@oshun/meditation-session`

Complete session management solution:

- `SessionManager` — full lifecycle with interruption and completion tracking
- `SessionPersistenceManager` — three storage backends with auto-save
- `SessionAnalyticsManager` — event recording and aggregate computation
- `SessionScheduler` — recurring sessions with iCal export

**Build**: `@nx/esbuild:esbuild` (dual ESM + CJS output) | **Runtime dep**:
`eventemitter3`

### `@oshun/meditation-progress`

Progress tracking, streaks, and gamification:

- `ProgressTracker` — records sessions, updates streaks, unlocks achievements
- `StreakCalculator` — timezone-aware with forgiveness days and freeze tokens
- `StatisticsCalculator` — aggregations over configurable date ranges
- `AchievementManager` — built-in definitions with unlock evaluation
- `MilestoneManager` — significant marker tracking with notifications
- `ProgressExporter` — multi-format data export
- `ProgressSyncManager` — multi-device sync with conflict resolution

**Build**: `@nx/js:tsc` | **Runtime dep**: `eventemitter3`

### `@oshun/meditation-breathing`

Breathing exercise engine with 10 built-in patterns and custom builder:

- `BreathingExercise` — event-driven exercise runner (inhale/hold/exhale/rest)
- `BreathingPatternBuilder` — fluent API for custom pattern construction
- `VisualizationProvider` — real-time easing and color data for UI animation
- `GuidancePlayer` — phase-synchronized audio cues
- `BreathingHapticManager` — phase-timed haptic feedback
- `SessionHistoryManager` — persist breathing session records

**Build**: `@nx/js:tsc` | **Runtime dep**: `eventemitter3`

### `@oshun/meditation-offline`

Offline content management with download queue and smart suggestions:

- `OfflineManager` — orchestrates downloads, storage, versioning, suggestions
- `DownloadQueue` — priority queue with retry, concurrency limits, and cancel
- `StorageManager` — three backends with automatic cleanup
- `ContentVersionManager` — manifest-based versioning with update policies
- `SuggestionEngine` — behavioral scoring for download recommendations
- Network detection with WiFi-only and metered-connection policies

**Build**: `@nx/js:tsc` | **Runtime dep**: `eventemitter3`

### `@oshun/meditation-analytics`

A small, dependency-free privacy-conscious event-tracking package:

- `AnalyticsClient` — event tracking gated on `enabled && consentGranted`, with
  an 11-value `AnalyticsEventName` union
- `AnalyticsProvider` interface — `identify` / `track` / `flush`, with a
  pluggable backend (Segment, Mixpanel, custom)
- `MemoryAnalyticsProvider` — in-memory provider for testing
- `summarizeSession` / `trackSessionSummary` — derive completion ratios and emit
  session-summary events; only behavioural fields, keyed by an `anonymousId`

**Build**: `@nx/js:tsc` | **Runtime dep**: none (no `eventemitter3`)

---

## 4. Common Architectural Patterns

The six engine libraries (player, timer, breathing, session, progress, offline)
share the design patterns described below, making them consistent and
predictable to work with. `meditation-core` is a pure type/utility package and
`meditation-analytics` is a standalone tracking package, so they participate
only where noted.

### 4.1 Event-Driven Core

Rather than polling state or using callbacks directly, every engine library's
primary class extends `EventEmitter` from `eventemitter3` and is parameterized
by a typed event map — one named property per event with its payload type. This
lets consumers subscribe to exactly the events they care about and receive
fully-typed payloads without casting.

```typescript
interface MeditationPlayerEvents {
  stateChange: { previousState: PlaybackState; currentState: PlaybackState };
  progress: PlaybackProgress;
  trackChange: { previousTrack: MeditationTrack | null /* ... */ };
  error: { error: PlayerError };
  // ...
}
class MeditationPlayer extends EventEmitter<MeditationPlayerEvents> {
  /* ... */
}
```

### 4.2 Platform Abstraction (Three-Tier)

Some features — background audio, haptics, lock screen controls — require
different OS APIs on web, iOS, and Android. Rather than scattering
`if (platform === 'web')` checks through business logic, each capability is
defined as an abstract base class. Three implementations are provided, plus a
factory that picks the right one at runtime:

```
Abstract base class (interface definition)
  └── Web implementation (uses Web APIs)
  └── Noop implementation (for testing/SSR)
  └── Factory function (selects implementation by environment detection)
```

Here is a concrete example from the player package:

```typescript
abstract class BackgroundAudioHandler {
  /* ... */
}
class WebBackgroundAudioHandler extends BackgroundAudioHandler {
  /* ... */
}
class NoopBackgroundAudioHandler extends BackgroundAudioHandler {
  /* ... */
}

// The factory takes an optional config object and picks Web vs Noop by
// detecting `window` / `navigator`.
function createBackgroundAudioHandler(
  config?: BackgroundAudioConfig
): BackgroundAudioHandler;
```

Native (React Native) implementations are provided by the consuming app, which
extends the abstract base class. This means adding React Native support never
requires modifying the core library.

### 4.3 Storage Backend Interchange

Libraries needing persistence use an interface-based storage abstraction. The
same business logic works against any backend — you swap it at the construction
site, not throughout the code:

- `InMemory*` — for testing and SSR
- `LocalStorage*` — for simple browser use
- `IndexedDB*` — for larger datasets

```typescript
// Switch backends without changing business logic
const persistence = new SessionPersistenceManager({
  storage:
    process.env.NODE_ENV === 'test'
      ? new InMemorySessionStorage()
      : new IndexedDBSessionStorage('sessions-db'),
});
```

### 4.4 React Hook Factories

React is an optional peer dependency — these libraries must also work in React
Native, Vue adapters, and vanilla JavaScript environments. To avoid a hard
dependency on React, the player, timer, breathing, session, progress, and
offline libraries export `createUse*` factory functions rather than direct
hooks. This pattern enables React dependency injection:

```typescript
// Register React once at app startup
import { useState, useEffect, useCallback, useMemo, useRef } from 'react';
setReactHooks({ useState, useEffect, useCallback, useMemo, useRef });

// Build bound hooks from a factory (the combined factory takes the hooks object)
const hooks = { useState, useEffect, useCallback, useMemo, useRef };
export const { useBreathingExercise, useBreathingState } =
  createBreathingHooks(hooks);
```

The breathing, timer, and progress packages additionally export pre-bound
convenience hooks (`useBreathingExercise`, `useMeditationTimer`, `useStreak`, …)
that resolve hooks registered through their `setReactHooks` function, for apps
that prefer the simpler import style.

### 4.5 Branded Types

Raw strings and numbers are easy to mix up accidentally — passing a `TrackId`
where a `SessionId` is expected, or seconds where milliseconds belong.
`meditation-core`, `meditation-session`, `meditation-progress`, and
`meditation-offline` use TypeScript branded types to catch these mistakes at
compile time rather than at runtime:

```typescript
// meditation-core uses a shared Brand helper
type SessionId = Brand<string, 'SessionId'>;
type DurationSeconds = Brand<number, 'DurationSeconds'>;
type ByteSize = Brand<number, 'ByteSize'>;

// session/progress/offline inline the same pattern
type ContentId = string & { readonly __brand: 'ContentId' };
```

`meditation-player` and `meditation-timer` use plain `type` aliases instead
(`type TrackId = string`, `type DurationSeconds = number`).

---

## 5. Dependency Graph

At the package level, the libraries do not import each other. The diagram below
shows their external runtime and peer dependencies:

```
eventemitter3  (runtime dependency of six packages)
   |
   +-- @oshun/meditation-player    (peer: react ^18.0.0; also dep @oshun/contracts)
   +-- @oshun/meditation-timer     (peer: react ^18.0.0)
   +-- @oshun/meditation-session   (peer: react >=18.0.0)
   +-- @oshun/meditation-progress  (peer: typescript catalog:)
   +-- @oshun/meditation-breathing (peer: react >=18.0.0)
   +-- @oshun/meditation-offline   (peer: react >=18.0.0)

(no eventemitter3, no react peer)
   @oshun/meditation-core      — pure types and utilities
   @oshun/meditation-analytics — standalone event tracking
```

`meditation-player` is the only package with a workspace dependency
(`@oshun/contracts`, for the shared playback-rate policy). `meditation-progress`
declares `typescript` rather than `react` as its peer dependency, though its
hooks still follow the React factory pattern. Integration between libraries
occurs at the application layer (Tara's and Lilith's apps).

---

## 6. Technology Stack

| Layer                  | Technology                                                |
| ---------------------- | --------------------------------------------------------- |
| Language               | TypeScript (ESM)                                          |
| Event system           | eventemitter3 (six of eight packages)                     |
| Build (seven packages) | `@nx/js:tsc`                                              |
| Build (session)        | `@nx/esbuild:esbuild` (ESM output with declaration files) |
| Testing                | Vitest                                                    |
| React integration      | Optional peer dependency, hook factory pattern            |

---

## 7. Test Coverage

Each package ships its own Vitest spec files. The table below maps packages to
their covered areas — this is the first place to look when tracing a test
failure back to its library.

| Library     | Test files                                                                  | Covered areas                                                                    |
| ----------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| `core`      | `core.spec.ts`                                                              | Branded constructors, duration/date/format/validation utilities                  |
| `player`    | `player.spec.ts`, `queue.spec.ts`, `mixer.spec.ts`, `playback-rate.spec.ts` | Playback lifecycle, queue operations, mixing, playback-rate policy               |
| `timer`     | `timer.spec.ts`                                                             | Timer lifecycle, phases, bell/ambient events                                     |
| `breathing` | `exercise.spec.ts`, `haptics.spec.ts`                                       | Exercise lifecycle, pattern execution, vibration pacing                          |
| `session`   | 8 spec files                                                                | Lifecycle, storage backends, analytics, scheduling CRUD/iCal/recurrence/triggers |
| `progress`  | `tracker.spec.ts`                                                           | Progress recording, streak calculation, achievements                             |
| `offline`   | 5 spec files                                                                | Manager, download queue, storage, suggestions, versioning                        |
| `analytics` | `analytics.spec.ts`                                                         | Event tracking, consent gating, session summaries                                |

---

## 8. Relationship to Tara Domain

The boundary between the meditation engine libraries and the Tara application
domain exists because the meditation logic is genuinely reusable — any future
meditation app in the monorepo (including Lilith's consciousness-exploration
surfaces) can consume `libs/meditation/` without taking on any of Tara's
application concerns. Tara owns the App Store-safe meditation product; Lilith
owns its broader experience surfaces. The engine lives in neither domain.

Data that crosses the boundary: session records and progress data flow upward
from the engine libraries into Tara's Prisma database. Tara's API layer wraps
the engine's session lifecycle, persisting results to PostgreSQL and dispatching
push notifications that the engine libraries themselves cannot send. The engine
libraries receive configuration from Tara (content URLs, user preferences) and
return results (session results, streak data, achievement unlocks) which Tara
then stores and exposes via its REST API.

```
libs/meditation/          libs/tara/             apps/tara/
(engine, platform-agnostic)  (Tara-specific libs)    (Tara apps)
         |                         |                     |
   core ────────────────────────────────────────────→  web (Next.js)
   player ─────────────────────────────────────────→  mobile (Expo)
   timer  ──────────────────── database (Prisma) ───→  api (Hono)
   session ─────────────────── content (hooks) ─────→
   progress ─────────────────────────────────────────→
   breathing ────────────────────────────────────────→
   offline ──────────────────────────────────────────→
   analytics ────────────────────────────────────────→
```

Tara's applications use the meditation engine libraries for all core logic and
add platform-specific concerns on top: API endpoints, UI components using
`@tara/ui`, database access through `@tara/database`, and analytics wiring.

---

## 9. Related Domains

| Domain  | Relationship                                                                                          |
| ------- | ----------------------------------------------------------------------------------------------------- |
| Tara    | Primary consumer; provides the application layer (API, UI, database) that wraps the meditation engine |
| Arete   | Personal development domain; meditation progress could feed into `@arete/habits` habit tracking       |
| Kuanyin | Compassion and ethics domain; wellness frameworks complement meditation content                       |
