Case study, 2026

A loyalty platform for a 17-location retailer

Native iOS and Android apps, an API, an admin dashboard, and a point-of-sale integration that keeps every member’s points balance current. Built, shipped through both app stores, and handed off.

iOS
Swift, SwiftUI
Android
Kotlin, Jetpack Compose
API
Node, Express
Database
PostgreSQL: 21 tables, ~126k member records, ~20k menu rows
Admin
React dashboard
Infrastructure
nginx, PM2
Push
APNs and FCM

The hard part: points that are always right

The point-of-sale vendor's public REST API didn't expose the identity and loyalty fields the app needed. Polling it harder wouldn't fix that.

So I designed a two-speed integration and got the vendor to approve it:

GraphQL bulk sync

Builds the login index: who each member is and how to find them, synced in bulk.

Live REST

Reads spendable points at the moment a member looks, so the balance is always current.

Identity changes slowly, so it syncs in bulk. Balances change at the register, so they're read live. Members always see a current balance, and login never silently goes stale.

Built to grow without re-shipping

Tiers, milestones, and order-ahead are built but dark behind feature flags, ready to switch on when the business is. Marketing push is consent-gated from the start, over APNs and FCM.

Through both app stores

Both apps passed Apple and Google review. Google Play initially rejected the Android build: R8 obfuscation had renamed serialized fields. I tracked it down, fixed it, and shipped.

Handed off properly

The engagement ended with a full operational handoff packet, so the people running the platform have everything they need to operate it.

Scale

PostgreSQL across 21 tables, holding about 126,000 member records and about 20,000 menu rows, behind a Node and Express API served with nginx and PM2, with a React admin dashboard for staff.