01The codebase
Two brands, one codebase
Two brands had two rewards apps, both built by an outside vendor on a no-code platform, neither owned by the company paying for them. Rebuilding twice, once per brand, would have meant maintaining two of everything forever.
So brand became data rather than a fork. One codebase, two shells, and a third brand costs a token file rather than a repo.
Shared, one copy
- The API
- The auth
- The data model
- The core component library
Seattle Sun Tan
Per brand
- Design tokens
- Copy
- Store listing
- A brand scope on every row
Desert Sun Tan
Per brand
- Design tokens
- Copy
- Store listing
- A brand scope on every row
Identity
Supabase with passwordless email-code login, so one customer account can later cover the app, the website and booking, and nobody has to reset a password the old vendor never exported.
Ledger
Balances are the sum of an append-only ledger. The old system stored a single balance per customer and no transaction history.
Booking
Reachable from the app through a deliberately swappable seam, so the app never contains a booking engine of its own.
02The accounts
Owning the accounts
Both apps were live under the vendor’s developer accounts. A transfer needs somewhere to transfer to.
Both apps under the vendor’s developer accounts.
Each brand has its own Apple Developer organisation and its own Google Play account.
Both were stood up from scratch through Apple’s and Google’s organization verification. They own their listings and their developer accounts for the first time.
03The listings
Shipping under the existing listings
A store app ID is permanent. Publishing the rebuild under a new one would have created a second listing with no installs and no reviews, and existing customers would never have seen it. So each brand’s build overrides its identifiers and pins the existing App Store app ID, and the release reaches current users as an update.
- App Store reviewApple rejected the first upload until the app supported iPad.
- VersionThe version number had to jump to 2.0.0.
- AndroidThe release is waiting on a key handover from the old vendor.
04Status
Where it stands
Both store listings still serve the old vendor’s builds. The switchover runs in a fixed order.
- Freeze the old system
- Re-export
- Release
The app has no automated tests of its own. The repo’s tests cover the API and the shared packages.