All docs

Architecture

Architecture

v0.2 plan in progress. See IMPLEMENTATION_PLAN.md for the admin portal + Supabase content catalog rollout (chapters, translations, RLS roles). The diagrams below describe v0.1 (current); the planned v0.2 layout is at the bottom.

Stack (v0.1)

Layer Technology
Client Expo + TypeScript + Expo Router
Local DB expo-sqlite
Business logic @umikora/shared
Content content/packs/official-v1.json

Stack (v0.2 — planned)

Layer Technology
Admin portal Next.js 16.x (App Router) + shadcn/ui + Tailwind
Admin hosting Vercel (preview on staging, prod on main)
Content store Supabase Postgres (modules → chapters → cards, pathways, translations)
Mobile client Expo + TypeScript + Expo Router (unchanged)
Mobile cache expo-sqlite mirror of Supabase content
Auth (admin) Supabase Auth (magic link) + RLS roles
Auth (mobile) Anonymous (anon key); RLS enforces is_active=true reads
Offline fallback content/packs/official-v1.json seed (legacy modules only)

Layer diagram

┌─────────────────────────────────────────────────┐
│  app/ (screens) + src/components/               │
│  AppContext · SocialMenuContext                 │
└────────────────────┬────────────────────────────┘
                     │ repositories / useApp()
┌────────────────────▼────────────────────────────┐
│  src/data/localRepository.ts                    │
│  ContentRepository · ProgressRepository ·       │
│  StatsRepository                                │
└────────┬───────────────────────────┬────────────┘
         │                           │
┌────────▼────────┐         ┌─────────▼──────────┐
│  database.ts    │         │  @umikora/shared  │
│  SQLite schema  │         │  sm2 · radar ·     │
│  migrations     │         │  types · constants │
└────────┬────────┘         └────────────────────┘
         │
┌────────▼────────┐
│  official-v1    │
│  .json          │
└─────────────────┘

Repository interfaces

Defined in apps/mobile/src/data/repositories.ts:

  • ContentRepository — modules, pathways, cards (read-only catalog)
  • ProgressRepository — profile, study list, due cards, review submit
  • StatsRepository — radar, summary, subscription tier (getSubscriptionTier / setSubscriptionTier), reset

localRepository.ts implements all three. v1.1 will add SupabaseRepository behind the same interfaces.

App bootstrap

  1. AppProvider calls initializeDatabase() on mount
  2. database.ts runs migrations and seeds from JSON if needed
  3. ready === true → screens read sync data via repositories
  4. refresh() bumps tick → context recomputes profile/stats/radar

Review lifecycle

  1. getDueCards() from progress repo
  2. User answers → checkAnswer() → rating → submitReview()
  3. submitReview updates SRS state via sm2.ts, logs review, updates XP/streak
  4. Radar/stats recomputed on next refresh() or context read

Freemium & mock subscription (v0.1)

Study-list and daily-new-card limits are driven by user_profile.subscription_tier (SQLite SCHEMA_VERSION 3). Tier limits live in @umikora/shared (getTierLimits()); plan names and HKD pricing live in apps/mobile/src/mocks/subscription.ts.

Tier 顯示名稱 Study items Daily new cards
explorer 探索者 2 10
scholar 學者 5 30
philosopher 哲人 unlimited unlimited

Enforced in localRepository.ts: canAddStudyItem(), getDueCards(). Users tab provides mock subscribe/upgrade UI (Alert confirm, no RevenueCat). Legacy is_pro=1 rows migrate to philosopher. v1.1 replaces mock with RevenueCat — see TODO.md.

Content model (v0.2 — planned)

Three-level hierarchy, with all human-readable text split into translation tables:

Module (學科 / 書 / 考試)
  └── Chapter (篇章 / 單元)
       └── Card (閃卡: MCQ / Cloze)

Pathway (學習路徑)
  └── module_slugs[]   (ordered list of module slugs)
  └── metadata: difficulty, estimated_days, prerequisite_slugs, subject_tags

Translations (one row per [entity, locale])
  ├── module_translations    (zh-TW required, en optional)
  ├── chapter_translations
  ├── card_translations
  └── pathway_translations

Supported locales: zh-TW (required) and en (optional). Adding a locale = update CHECK constraints + UI.

Full SQL, RLS policies, and audit triggers: IMPLEMENTATION_PLAN.md §3–§4.

v0.2 layer diagram (planned)

┌──────────────────────────────────────────────────┐
│  Admin Portal (Next.js, apps/admin/)             │
│  Server Actions use signed-in user JWT (RLS)     │
└──────────────────────┬───────────────────────────┘
                       │ writes
                       ▼
┌──────────────────────────────────────────────────┐
│  Supabase Postgres                               │
│  modules / chapters / cards / pathways           │
│  + *_translations + content_revisions (audit)    │
│  + featured_items / featured_events              │
│  + Edge Functions: featured-feed, set-user-role  │
└──────────────────────┬───────────────────────────┘
                       │ anon read (RLS: is_active=true)
                       ▼
┌──────────────────────────────────────────────────┐
│  Mobile App (Expo)                               │
│  supabaseContentClient → SQLite mirror           │
│  Reads resolve title/description by preferred    │
│  locale (user_profile.preferred_locale)          │
└──────────────────────────────────────────────────┘

Related docs