iOS App
apps/ios — the native customer companion: book a stay, pre-check-in, follow the pet live, pay, and message the front desk. Universal SwiftUI for iPhone/iPad targeting iOS 26, with macOS planned. It is the native twin of the Client Portal.
Stack & posture
- Swift 6.2 with strict concurrency (
SWIFT_STRICT_CONCURRENCY: complete) and@MainActordefault actor isolation. - SwiftUI + Observation: one
@Observable final class AppStore(Sources/Services/AppStore.swift) is the single source of truth, injected via.environment(store). - xcodegen:
xcodegen generateproduces the (uncommitted)Pawdentity.xcodeprojfromproject.yml. Two targets:Pawdentity(app, bundle idcom.pawdentity.client) andPawdentityUITests. Code signing disabled for simulator/CI builds.
Shell & navigation
PawdentityApp(@main) builds the store;RootViewbranches onstore.isSignedInbetweenSignInViewandMainTabView.MainTabViewuses.tabViewStyle(.sidebarAdaptable)— a tab bar on iPhone, sidebar on iPad, macOS-ready. Five tabs: Home, Visits, Pets, Inbox (unread badge fromstore.unreadMessageCount), Account.
Screens
| Feature | Views | What it does |
|---|---|---|
| Home | HomeView | live "in house" hero card, check-in prompt, vaccine/agreement/balance alerts, latest photos, upcoming visits |
| Check-in | CheckInFlowView, ExpressPassView | multi-step pre-check-in + a QR express pass scanned at the front desk |
| Visits | VisitsView, VisitDetailView, BookVisitFlowView | booking flow: service → pets → dates → add-ons → review with deposit |
| Pets | PetsView, PetDetailView | profiles, vaccine tracking, notes, gallery, history |
| Inbox | InboxView | two-way threads with unread badges |
| Account | AccountView, BillingViews | invoices/receipts, pay balance, payment methods, agreements, notification prefs |
The mock store mirrors the Convex schema
This is the app's defining architectural decision. Models in Sources/Models/Models.swift are explicitly customer-facing projections of packages/backend/convex/schema.ts:
- IDs are opaque
Strings so real Convex document ids slot in unchanged. - Enums use the exact backend raw values:
VisitStatus(planned,due_in,in_house,overdue,completed,cancelled,no_show),PaymentStatus(deposit_due,deposit_met, …),CareEventType,ServiceKind,Species. - Money is integer cents (
Int.asCurrency), matching the backend convention. - Structs:
Facility,Client,Pet/Vaccine,PetPhoto,Visit,CareEvent,Order/OrderItem,PaymentMethod/PaymentReceipt,MessageThread/Message,Agreement,ServiceProduct/AddOn.
AppStore hydrates from MockData.snapshot() — a seeded demo world anchored to "now", including a simulated live care-event stream (an event every 25s while a pet is in house, standing in for a Convex subscription on careEvents) and staff auto-replies to messages after 4s.
Every intent method is annotated with the Convex mutation it maps 1:1 to: completeCheckIn → visits.checkIn, bookVisit → orders.create + visits.create, recordPayment → payments.charge, sendMessage → messages.send, signAgreement → signatures.create. Swapping in a Convex HTTP/WebSocket client changes AppStore internals only.
Demo & testing
DEBUG-only launch args (Sources/App/DemoLaunch.swift):
| Arg | Effect |
|---|---|
-demo-signed-in | skip sign-in |
-demo-tab <0-4> | open Home/Visits/Pets/Inbox/Account |
-demo-checkin | open Home with the check-in flow presented |
PawdentityUITests/DemoJourneyTests.swift scripts a paced end-to-end walkthrough (sign-in → live stay timeline → full check-in including drawing on the signature-pad element and "Simulate Front Desk Scan" → book → pet profile → message → pay), designed to run under xcrun simctl io … recordVideo for demo capture.
Roadmap
Convex client replacing the mock store · Live Activities & widgets · push notifications · Apple Pay (PassKit) + a Wallet pass for the express QR · a macOS target reusing the adaptive shell.