Epic: Native iOS app (chat_ios) mirroring Hesychia web #112

Open
opened 2026-08-05 04:25:08 -07:00 by westfarn · 0 comments
Owner

Goal

Spike + plan a true native iOS Hesychia client in a new repo chat_ios (org: ai_ml_operations), feature-parity with chat_web_app / llm-fe, while reusing chat_backend APIs.

Follow-on to Android epic: chat_web_app#111 (chat_android). This epic lives here because product/UX/API contracts and the existing Capacitor shell are owned by chat_web_app. Implementation work for the native iOS app lands in chat_ios once that repo exists.

Current state (do not ignore)

Layer Today
Mobile ship path Capacitor 7 WKWebView wrapping CRA build/ (llm-fe/ios/, bundle id ai.hesychia.chat) — see IOS.md / #21
Auth JWT REST + OAuth redirect flows; native SSO redirects still weak
Chat REST + WebSocket (REACT_APP_BACKEND_*)
Billing (web) Stripe Checkout + Customer Portal
Billing (Capacitor native) RevenueCat via @revenuecat/purchases-capacitorMONETIZATION.md, #100
UI React + MUI 5 + Emotion; tokens in llm-fe/src/llm-fe/ui-kit/assets/theme/
Android twin Native Compose client scaffolding in chat_android (see #111)

Decision to force early: keep Capacitor as interim App Store / TestFlight track vs migrate users to a native IPA under the same (or new) bundle id. Bundle-id / App Store continuity matters for IAP and reviews.

Why native (vs Capacitor)

Capture explicit rationale (mirror Android epic):

  • Performance / streaming UX gaps in WKWebView (keyboard, scroll, markdown, charts)
  • StoreKit / IAP reliability or App Review friction with WebView (guideline 4.2)
  • Native navigation, notifications, document pickers, offline
  • Long-term cost of dual Capacitor + web vs one SwiftUI client + web
  • Align architecture decisions with chat_android where sensible (API contracts, tokens, RC appUserID)

Proposed repo: chat_ios

Create under ai_ml_operations:

  • Swift + SwiftUI + iOS 16+ (preferred default unless spike says otherwise; align minimum with Capacitor deployment target)
  • Same backend base URLs / env flavours as .env.mobile / beta / prod
  • CI: unit tests on Linux where possible; archive / TestFlight builds require macOS (Gitea Actions macOS runner or manual Xcode until hosted)
  • Secrets: signing certs / profiles / App Store Connect API key outside repo

Out of scope for v1 unless justified: full offline-first sync; rewriting Android in a cross-platform framework.


Workstream A — Discovery & architecture

  • Reuse screen inventory from chat_android/docs/SCREEN_INVENTORY.md (parity with App.tsx)
  • Map FE → chat_backend REST + WS contracts (share notes with Android)
  • Choose architecture: single target vs packages; networking (URLSession); WS client; DI (Swift Observation / TCA / vanilla); navigation
  • Decide bundle id / App Store track strategy vs existing Capacitor ai.hesychia.chat
  • Write ADR in chat_ios covering Capacitor sunset / coexistence + relationship to chat_android
  • Share design tokens (chat_android/design-tokens/hesychia.tokens.json or export from ui-kit)

Exit: architecture note + screen inventory + open questions list.


Workstream B — Visual parity / design system

  • Consume shared design tokens (colors, typography, radii) from JSON/YAML
  • Implement SwiftUI HesychiaTheme (light/dark + palette variants: blue/green/purple/orange/red)
  • Parity bar: brand + layout rhythm; allow UIKit/SwiftUI platform patterns for nav/keyboard
  • Side-by-side QA checklist for Sign-in, Chat compose, Account/Billing
  • Package brand assets (hesychia-mark, icons, splash) from llm-fe/assets/

Exit: token-backed theme + screenshot comparison for 3 core screens.


Workstream C — Auth & session

  • JWT storage (Keychain) parity with web / Android session helpers
  • Email/password sign-in + sign-up against existing endpoints (token/obtain/, etc.)
  • Password reset via ASWebAuthenticationSession / Universal Links
  • Google / Microsoft SSO + Sign in with Apple (App Store expectation when other social SSO offered)
  • Session restore, 401 handling, logout (incl. RevenueCat logOut when IAP wired)

Exit: authenticated user can open chat and survive process death.


Workstream D — Chat parity

  • Conversation list + create/select
  • Message history pagination / scroll
  • WebSocket connect / reconnect / background lifecycle (learn from FE #23 + Android twin)
  • Streaming partial tokens UI
  • Markdown / code blocks / citations strategy (native AttributedString / libraries vs WKWebView islands)
  • Message actions parity where product still needs them

Exit: end-to-end chat on simulator + physical device matching web happy path.


Workstream E — In-app purchases (required)

Native App Store must not use Stripe Checkout for digital subscriptions (Apple policy). Align with RevenueCat path.

  • Integrate RevenueCat iOS SDK (prefer RC for parity with Capacitor + Android + backend webhooks)
  • Same appUserID rules as MONETIZATION.md (Django user pk string)
  • Offerings / packages mapped to plan slugs (founders, etc.) — share product ids with Capacitor / Android RC dashboard
  • Purchase, restore, entitlement refresh → /monetization/... APIs
  • UI: native Billing section; no Stripe portal for App Store subs; badge revenuecat + APP_STORE
  • Sign-up path: after account create, trigger store purchase
  • App Store Connect: products, subscriptions, sandbox testers, App Privacy, account deletion

Exit: TestFlight sandbox purchase + restore + entitlement visible in Account; web Stripe path unchanged.


Workstream F — Platform & store ops

  • Create chat_ios repo + README + local run docs (Xcode)
  • Signing / TestFlight pipeline (manual Mac first; automate when macOS CI available)
  • Versioning policy (CFBundleShortVersionString / CFBundleVersion) aligned with Android versionName / versionCode + web package.json
  • Push notifications? (defer unless product requires)
  • Crash reporting / analytics decision
  • Plan for Capacitor iOS app: freeze, dual-ship, or replace listing
  • App Review 4.2 readiness (enough native value)

Workstream G — Cross-repo coordination

Repo Likely needs
chat_ios All native iOS implementation
chat_android Shared tokens, API contract notes, RC product id alignment
chat_web_app Token export, Capacitor deprecation notes, shared brand assets
chat_backend SSO redirect URIs, Sign in with Apple / Universal Link support, monetization gaps
server-infra Only if new public mobile-specific endpoints / docs hosts

Suggested child issues (cut after discovery)

  1. Spike: SwiftUI vs keep Capacitor — decision record
  2. Create chat_ios repo scaffolding (Xcode project, schemes, flavors/configs)
  3. Import design tokens + SwiftUI theme
  4. Auth + Keychain JWT session
  5. Chat REST + WebSocket MVP
  6. RevenueCat IAP + Account billing UI
  7. SSO + Sign in with Apple + Universal Links
  8. TestFlight checklist + App Store listing
  9. Capacitor coexistence / migration plan (coordinate with Android ADR-002)

Acceptance criteria (epic done when)

  1. Written decision: proceed / defer native iOS, with cost estimate (eng weeks) and Capacitor fate
  2. If proceed: chat_ios exists, builds on macOS, and completes auth → chat → IAP purchase/restore on TestFlight sandbox
  3. Visual parity bar met for core screens (documented screenshots)
  4. Monetization consistent with MONETIZATION.md (RC on App Store, Stripe on web)
  5. Remaining parity gaps filed as prioritized backlog, not hidden
  6. Bundle-id strategy documented relative to Capacitor ai.hesychia.chat and Android twin

References

  • Sibling Android epic: #111 / repo chat_android
  • llm-fe/IOS.md, llm-fe/MONETIZATION.md, llm-fe/ios/README.md
  • Capacitor iOS: #21, RevenueCat: #100
  • Backend: chat_backend
  • Product: Hesychia / hesychia.ai
## Goal Spike + plan a **true native iOS** Hesychia client in a **new repo** `chat_ios` (org: `ai_ml_operations`), feature-parity with `chat_web_app` / `llm-fe`, while reusing `chat_backend` APIs. **Follow-on to Android epic:** [chat_web_app#111](https://git.aimloperations.com/ai_ml_operations/chat_web_app/issues/111) (`chat_android`). This epic lives here because product/UX/API contracts and the existing Capacitor shell are owned by `chat_web_app`. Implementation work for the native iOS app lands in `chat_ios` once that repo exists. ## Current state (do not ignore) | Layer | Today | |-------|--------| | Mobile ship path | Capacitor 7 WKWebView wrapping CRA `build/` (`llm-fe/ios/`, bundle id `ai.hesychia.chat`) — see `IOS.md` / `#21` | | Auth | JWT REST + OAuth redirect flows; native SSO redirects still weak | | Chat | REST + WebSocket (`REACT_APP_BACKEND_*`) | | Billing (web) | Stripe Checkout + Customer Portal | | Billing (Capacitor native) | RevenueCat via `@revenuecat/purchases-capacitor` — `MONETIZATION.md`, `#100` | | UI | React + MUI 5 + Emotion; tokens in `llm-fe/src/llm-fe/ui-kit/assets/theme/` | | Android twin | Native Compose client scaffolding in `chat_android` (see #111) | **Decision to force early:** keep Capacitor as interim App Store / TestFlight track vs migrate users to a native IPA under the same (or new) bundle id. Bundle-id / App Store continuity matters for IAP and reviews. ## Why native (vs Capacitor) Capture explicit rationale (mirror Android epic): - [ ] Performance / streaming UX gaps in WKWebView (keyboard, scroll, markdown, charts) - [ ] StoreKit / IAP reliability or App Review friction with WebView (guideline 4.2) - [ ] Native navigation, notifications, document pickers, offline - [ ] Long-term cost of dual Capacitor + web vs one SwiftUI client + web - [ ] Align architecture decisions with `chat_android` where sensible (API contracts, tokens, RC `appUserID`) ## Proposed repo: `chat_ios` Create under `ai_ml_operations`: - **Swift + SwiftUI + iOS 16+** (preferred default unless spike says otherwise; align minimum with Capacitor deployment target) - Same backend base URLs / env flavours as `.env.mobile` / beta / prod - CI: unit tests on Linux where possible; **archive / TestFlight builds require macOS** (Gitea Actions macOS runner or manual Xcode until hosted) - Secrets: signing certs / profiles / App Store Connect API key **outside** repo Out of scope for v1 unless justified: full offline-first sync; rewriting Android in a cross-platform framework. --- ## Workstream A — Discovery & architecture - [ ] Reuse screen inventory from `chat_android/docs/SCREEN_INVENTORY.md` (parity with `App.tsx`) - [ ] Map FE → `chat_backend` REST + WS contracts (share notes with Android) - [ ] Choose architecture: single target vs packages; networking (URLSession); WS client; DI (Swift Observation / TCA / vanilla); navigation - [ ] Decide **bundle id** / App Store track strategy vs existing Capacitor `ai.hesychia.chat` - [ ] Write ADR in `chat_ios` covering Capacitor sunset / coexistence + relationship to `chat_android` - [ ] Share design tokens (`chat_android/design-tokens/hesychia.tokens.json` or export from `ui-kit`) **Exit:** architecture note + screen inventory + open questions list. --- ## Workstream B — Visual parity / design system - [ ] Consume shared design tokens (colors, typography, radii) from JSON/YAML - [ ] Implement SwiftUI `HesychiaTheme` (light/dark + palette variants: blue/green/purple/orange/red) - [ ] Parity bar: brand + layout rhythm; allow UIKit/SwiftUI platform patterns for nav/keyboard - [ ] Side-by-side QA checklist for Sign-in, Chat compose, Account/Billing - [ ] Package brand assets (`hesychia-mark`, icons, splash) from `llm-fe/assets/` **Exit:** token-backed theme + screenshot comparison for 3 core screens. --- ## Workstream C — Auth & session - [ ] JWT storage (Keychain) parity with web / Android session helpers - [ ] Email/password sign-in + sign-up against existing endpoints (`token/obtain/`, etc.) - [ ] Password reset via ASWebAuthenticationSession / Universal Links - [ ] Google / Microsoft SSO + **Sign in with Apple** (App Store expectation when other social SSO offered) - [ ] Session restore, 401 handling, logout (incl. RevenueCat `logOut` when IAP wired) **Exit:** authenticated user can open chat and survive process death. --- ## Workstream D — Chat parity - [ ] Conversation list + create/select - [ ] Message history pagination / scroll - [ ] WebSocket connect / reconnect / background lifecycle (learn from FE `#23` + Android twin) - [ ] Streaming partial tokens UI - [ ] Markdown / code blocks / citations strategy (native AttributedString / libraries vs WKWebView islands) - [ ] Message actions parity where product still needs them **Exit:** end-to-end chat on simulator + physical device matching web happy path. --- ## Workstream E — In-app purchases (required) Native App Store must **not** use Stripe Checkout for digital subscriptions (Apple policy). Align with RevenueCat path. - [ ] Integrate **RevenueCat iOS SDK** (prefer RC for parity with Capacitor + Android + backend webhooks) - [ ] Same `appUserID` rules as `MONETIZATION.md` (Django user pk string) - [ ] Offerings / packages mapped to plan slugs (`founders`, etc.) — share product ids with Capacitor / Android RC dashboard - [ ] Purchase, restore, entitlement refresh → `/monetization/...` APIs - [ ] UI: native Billing section; **no** Stripe portal for App Store subs; badge `revenuecat` + `APP_STORE` - [ ] Sign-up path: after account create, trigger store purchase - [ ] App Store Connect: products, subscriptions, sandbox testers, App Privacy, account deletion **Exit:** TestFlight sandbox purchase + restore + entitlement visible in Account; web Stripe path unchanged. --- ## Workstream F — Platform & store ops - [ ] Create `chat_ios` repo + README + local run docs (Xcode) - [ ] Signing / TestFlight pipeline (manual Mac first; automate when macOS CI available) - [ ] Versioning policy (`CFBundleShortVersionString` / `CFBundleVersion`) aligned with Android `versionName` / `versionCode` + web `package.json` - [ ] Push notifications? (defer unless product requires) - [ ] Crash reporting / analytics decision - [ ] Plan for Capacitor iOS app: freeze, dual-ship, or replace listing - [ ] App Review 4.2 readiness (enough native value) --- ## Workstream G — Cross-repo coordination | Repo | Likely needs | |------|----------------| | `chat_ios` | All native iOS implementation | | `chat_android` | Shared tokens, API contract notes, RC product id alignment | | `chat_web_app` | Token export, Capacitor deprecation notes, shared brand assets | | `chat_backend` | SSO redirect URIs, Sign in with Apple / Universal Link support, monetization gaps | | `server-infra` | Only if new public mobile-specific endpoints / docs hosts | --- ## Suggested child issues (cut after discovery) 1. Spike: SwiftUI vs keep Capacitor — decision record 2. Create `chat_ios` repo scaffolding (Xcode project, schemes, flavors/configs) 3. Import design tokens + SwiftUI theme 4. Auth + Keychain JWT session 5. Chat REST + WebSocket MVP 6. RevenueCat IAP + Account billing UI 7. SSO + Sign in with Apple + Universal Links 8. TestFlight checklist + App Store listing 9. Capacitor coexistence / migration plan (coordinate with Android ADR-002) --- ## Acceptance criteria (epic done when) 1. Written decision: proceed / defer native iOS, with cost estimate (eng weeks) and Capacitor fate 2. If proceed: `chat_ios` exists, builds on macOS, and completes **auth → chat → IAP purchase/restore** on TestFlight sandbox 3. Visual parity bar met for core screens (documented screenshots) 4. Monetization consistent with `MONETIZATION.md` (RC on App Store, Stripe on web) 5. Remaining parity gaps filed as prioritized backlog, not hidden 6. Bundle-id strategy documented relative to Capacitor `ai.hesychia.chat` and Android twin ## References - Sibling Android epic: `#111` / repo `chat_android` - `llm-fe/IOS.md`, `llm-fe/MONETIZATION.md`, `llm-fe/ios/README.md` - Capacitor iOS: `#21`, RevenueCat: `#100` - Backend: `chat_backend` - Product: Hesychia / `hesychia.ai`
westfarn self-assigned this 2026-08-05 04:25:08 -07:00
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ai_ml_operations/chat_web_app#112