
Highlights5
- Scan → itemize → split → settle: receipt scanning extracts the merchant, items, tax, and tip, while each item supports equal, percentage, share-based, or exact splits.
- A Postgres RPC ledger keeps bill creation, settlement, and balance calculations transactional; integer-cent arithmetic prevents rounding drift.
- Debt-edge reduction algorithm minimizes the number of settlement transactions inside a group.
- Offline-aware core: idempotency keys and MMKV persistence underneath real-time Supabase subscriptions.
- Maestro E2E flows and enforced coverage thresholds guard every release build.
Build notes22
- Shipped a web target alongside the native app: 116 .web.tsx surfaces sharing the same stores and services, with keyboard focus rings, pointer affordances and claim-link visitors kept out of signed-in chrome.
- Built the insights surface: personal and group spend charts computed server-side through Postgres RPCs (get_user_insights, versioned to v3), a ranked people list that replaced a balance bar chart, an activity heatmap, a category breakdown, a spending radar and a trend line.
- Wrote the insights copy to describe what happened rather than grade the reader, after a pass that removed every word implying fault.
- Held charts to one currency per axis and a net position line over Friends and Spaces, so a balance that mixes currencies cannot be drawn as if it were one number.
- Gated multi-payer bills and raised free-tier limits behind versioned Supabase migrations, with a quota system surfacing usage and a blocked-state sheet rather than a silent failure.
- Ran a pre-launch audit across app, web and charts: contrast and theme tokens, an adaptive-ink rule for conditional fills with a validator enforcing the class, keyboard and tap targets, font scaling, and visible focus on every control including auth.
- Added settlement claims awaiting confirmation to the activity feed, and made the settle screen state what the settlement leaves behind rather than reporting a bare success.
- Built one search model across the tabs with recents as the resting state, and versioned every persisted store so a cache written by an older build cannot crash a screen.
- Architected feature-sliced Zustand state (billsStore/activityStore/networkStore/uiStore/alertStore) split into actions/selectors for testability; normalized billsById index killing O(n) lookups on detail screens.
- Built idempotency-key + MMKV persistence layer as foundation for offline writes and conflict resolution; real-time Supabase channel subscriptions with lifecycle-aware cleanup.
- Wrote Postgres RPC functions (Supabase migrations) for atomic bill creation, settlement, and group-balance compute - multi-table writes stay transactional.
- Renamed Group → Space across schema, RPCs, store, and UI via versioned migrations with zero data loss.
- Implemented direct-ledger clustering algorithm minimizing settlement transactions between users (graph reduction over debt edges); integer-cent money/currency module eliminating float drift in splits.
- Unified reportError reporting system replacing scattered console.error - severity-tagged, routed to logging sink, wired through every catch; screen-level React ErrorBoundary surfacing recovery UI.
- Added Android release-build preflight (npm run preflight) + Maestro E2E flows catching ProGuard/native/env regressions Jest can't; authored explicit ProGuard keep rules for Google Sign-In, Firebase, and other native SDKs after diagnosing release-only silent failures.
- Perf: memoization audits, Tamagui style hoisting, dead-code removal, batched activity subs, selective balance invalidation on bill mutation, deferred non-critical fetches, Android build-flag tuning, spring → 250ms cubic easing for low-end Android frame-time wins.
- Designed 4-font typography system (Sora/Space Grotesk/Outfit/SpaceMono) enforced via Title/Body/Label/Numeric wrappers; useThemeColors() hook with light/dark token sets (lavender primary, peach secondary).
- Built LedgerItemRow - focus-driven expand/collapse row replacing modal-based item editing; auto-advance Enter, validate-on-blur, integer-only qty.
- Receipt-scan pipeline UI (scan → processing → review → create) with draft persistence surviving app kill; reusable primitives: ModernAlert, ConfirmDialog, EmptyState, Avatar, Skeleton, ListItem, SplitModeSelector.
- Lifted test coverage from near-zero to enforced thresholds: unit tests across stores/services/actions/helpers/UI; interaction tests for LedgerItemRow (focus, expand, validation); full action-suite tests for billsStore (create, update, delete, item toggle); shared render helpers + store mocks + fixture factories.
- Product: AI receipt scanning with reviewable OCR drafts; deep-linked friend-add flow with auto profile fetch from invite code; Privacy/ToS/OSS-Licenses screens; lightweight i18n helpers (interpolation + pluralization) without a full runtime.
- DX: EAS configured with .easignore slimming build uploads; UI strings extracted to constants module; centralized URL config; long-press dev-only /experiment route for pre-port UI prototyping.
Tools
- React Native
- Expo
- TypeScript
- Zustand
- Supabase
- Postgres
- Tamagui
- MMKV
- Maestro
- Jest
- EAS