## Summary - The Capacitor shell buys through StoreKit (iOS 15) and Play Billing instead of RevenueCat. - After the store sheet succeeds, the app POSTs the signed transaction or Play purchase token to `/monetization/store/confirm/`. - Restore reads current store entitlements and confirms each one. Web checkout stays on Stripe. - The store account token from `GET /monetization/subscription/` is sent as `appAccountToken` / `obfuscatedAccountId`. Depends on the `chat_backend` PR for issue #78 (`feat/78-native-store-purchases`). ## Test plan - [x] `storeBilling`, `revenueCat`, `finance`, and `BillingSection` unit tests - [ ] iOS sandbox purchase and restore against a backend with `APPLE_IAP_BUNDLE_ID` set - [ ] Play license-test purchase and restore against a backend with `GOOGLE_PLAY_SERVICE_ACCOUNT_JSON` set - [ ] Web billing still opens Stripe Checkout Reviewed-on: #122
Hesychia — iOS
Native Capacitor project for ai.hesychia.chat. Web UI comes from the CRA
build/ output in the parent llm-fe/ package (synced with npx cap sync).
Broader Capacitor notes (env files, icons, QA, TestFlight): ../IOS.md.
Prerequisites
- macOS + Xcode 15+
- Node.js 20
- CocoaPods (
pod --version) - Open
App.xcworkspace(not.xcodeproj)
Build the web bundle and sync
From the npm root (llm-fe/, one level up):
cd ..
npm ci
npm run build:mobile # .env.mobile → react-scripts build → cap sync
Open in Xcode:
npm run ios:open
# or: npx cap open ios
Re-sync after changing web code (with an existing build/):
npm run ios:sync
Backend URLs are baked in at web-build time via ../.env.mobile (prod by default).
After cloning, if Pods are missing:
cd App
pod install
Run on a simulator / device
- Open
App/App.xcworkspacein Xcode. - Pick a simulator or a paired iPhone (Signing & Capabilities → your Team).
- Product → Run (⌘R).
CLI (optional):
xcodebuild -workspace App/App.xcworkspace \
-scheme App \
-destination 'platform=iOS Simulator,name=iPhone 16' \
build
Version before a store release
Edit target App → General, or App.xcodeproj build settings:
| Field | Build setting | Rule |
|---|---|---|
| Version | MARKETING_VERSION |
Keep in sync with ../package.json version + Android versionName |
| Build | CURRENT_PROJECT_VERSION |
Integer; must increase for every TestFlight / App Store upload |
Currently: version 0.1.0, build 1.
Signing
Do not commit .p12, .mobileprovision, or export option files with secrets.
Debug / simulator: Automatic signing with a personal team is enough.
Distribution: App Store Connect + distribution certificate + profile — credentials live outside this repo. CI/TestFlight automation is a follow-on ticket.
Useful paths
| Path | Purpose |
|---|---|
App/App/AppDelegate.swift |
Disables WKWebView rubber-band bounce |
App/App/Info.plist |
Display name Hesychia, version keys |
App/App/Assets.xcassets |
App icon + splash (regenerate via npm run assets:generate) |
App/Podfile / Podfile.lock |
CocoaPods (commit lockfile; Pods/ is gitignored) |