Case study
Loyoh
Digital Loyalty Cards for Coffee Shops
Role
Scope
Stack
What I built.
- 01
Built the part of Loyoh that puts a shop’s loyalty card into Apple Wallet and Google Wallet in one tap, and keeps it updated.
- 02
Each card carries the shop’s name and colours, the customer’s name, their stamp count and a QR code for the barista to scan.
- 03
When a stamp is added, the card on the customer’s phone updates within seconds, with nothing to open or refresh.
- 04
Cards show how many stamps are left, switch to “Free coffee ready!” when full, and reset after redemption.
- 05
Only the real customer can download their card, and only Apple’s servers can request updates, so cards can’t be faked or copied.
- 06
Stamping keeps working even when Apple or Google is slow or down; the card catches up afterwards.
- 01
Signed storeCard .pkpass generation with passkit-generator v3, per-shop colours, and certificates loaded from environment variables in production.
- 02
The full Apple PassKit Web Service (register, unregister, serials, latest pass, log), authenticated with a per-serial HMAC token compared in constant time.
- 03
Silent APNs updates over one persistent HTTP/2 provider, pushing per token with Promise.allSettled so one bad token never blocks the rest.
- 04
A Google Wallet Loyalty Class per shop and a Loyalty Object per customer, a signed RS256 save link, and object patches after every stamp and redemption, with an in-memory class cache.
- 05
Pass download links protected by hour-windowed HMAC tokens; a Firestore transaction stops one QR scan from awarding two stamps.
- 06
Wallet hooks wired into sign-up, rotating-QR stamps and manual stamps, all fire-and-forget so the barista never waits on Apple or Google.