Skip to content

Architecture

github-actions[bot] edited this page Aug 11, 2026 · 1 revision

Enjoy Player uses a feature-first architecture under lib/features, with shared application infrastructure in lib/core and persistence/API code in lib/data. Feature modules generally separate domain models, application orchestration, data access, and presentation.

flowchart LR
  UI[Presentation] --> App[Riverpod application layer]
  App --> Repo[Repositories]
  Repo --> DAO[Drift DAOs]
  DAO --> DB[(SQLite)]
  DAO --> Repo
  Repo --> App
  App --> UI
Loading

Module layout

  • lib/core: routing, theme, logging, errors, platform helpers, recovery, caching, and interaction primitives
  • lib/data: Drift database, DAOs, tables, migrations, API clients, and service wrappers
  • lib/features: auth, player, transcript, library, vocabulary, sync, discover, settings, AI, and related product capabilities

State and data flow

Riverpod 3 providers and notifiers are the standard orchestration mechanism. Drift is the local source of truth; repositories expose watched queries, while distinctBy helpers suppress no-op database emissions. Generated providers use @riverpod or @Riverpod; selected Drift stream providers remain handwritten where generator type resolution is unsuitable.

Routing and media surfaces

GoRouter uses a ShellRoute so navigation and the global transport remain persistent. RootShell owns one permanent PlayerSurfaceHost, which moves the active native/WebView surface between registered targets. This prevents duplicate players and keeps native surfaces below dialogs and sheets.

See docs/architecture.md.