iPhone card list + Watch complication + Apple Wallet pass — three surfaces in one composed frame. Show the card auto-surfacing via geofence notification.
Hopscotch
Three platforms. Three weeks. Zero dependencies.
My Role
Solo designer-developer. User research (field observation), product strategy, UX/UI design, SwiftUI + watchOS implementation, serverless backend, marketplace business model.
3 platforms
iOS + Watch + Wallet
Solo
Design + Dev
3 weeks
Timeline
0
Dependencies
“I watched someone fumble through their wallet for a punch card at a coffee shop. Then I saw the paper punch card taped to the counter. That's not nostalgia — it's a market failure.”
Key Design Decisions
The moments that shaped the product.
Flow diagram: two flows side-by-side. Left: 'Existing model' — cashier scans customer phone (burden on business). Right: 'Hopscotch model' — customer scans business QR (burden on motivated party). Arrows showing who carries each step.
Customer scans business — not vice versa
Most digital loyalty puts burden on the cashier. Hopscotch inverts it: the business places a static QR at the register. The customer scans it. No hardware, no cashier training, no app on the business side. The customer is the motivated party and self-serves. This interaction model serves both sides of a two-sided marketplace simultaneously.
Three-screen flow: explanation screen → When In Use prompt → Always prompt. Linear progression with the 'Save Anyway' escape hatch visible at each stage.
Progressive location permissions with an escape hatch
iOS gives you one shot at the system prompt. I built a three-stage escalation: explain → request When In Use → request Always. The 'Save Anyway' escape hatch means users who decline location access aren't blocked from the core product. Respects user autonomy while maximizing the value of the permission.
The circular complication in three states: default (outline icon, teal fill), nearby (outline icon, category subtitle), geofence active (filled icon, teal ring border). 40pt size, shown on a watch face.
Watch complications: outline = available, filled = relevant now
A 40pt circular complication has room for exactly one piece of information. The outline/filled icon distinction uses Apple's own visual grammar (tab bars, SF Symbols) to encode whether a card is nearby or just exists. When you enter a geofenced location, the complication fills and gets a relevance boost in Smart Stack — the right card surfaces without scrolling.
Watch barcode detail shown in dark mode (unreadable by scanner) vs. forced light mode (scannable). Annotation: 'Forced light regardless of Watch face setting — functional, not aesthetic.'
watchOS is not small iOS — forced light mode for barcode scanning
CoreImage doesn't exist on watchOS, so iPhone pre-renders barcodes as PNGs and sends them via WatchConnectivity. The Watch barcode view forces .colorScheme(.light) regardless of the user's Watch face setting — because barcode scanners expect dark bars on a light background. This is a functional requirement, not an aesthetic choice.
Small, medium, and large widgets side-by-side showing consistent visual padding despite different system margin baselines. Code snippet overlay showing the one-line formula.
Adaptive widget margins that future-proof against new devices
The formula max(0, targetPadding - systemMargins.top) reads system-provided margins (which vary by widget size and device) and adds only the delta needed. If Apple ships new widget sizes tomorrow, the padding adapts automatically without a code change. This is the correct response to a variable design constraint.
Process
Paper punch card at a coffee shop — a market failure hiding as nostalgia.
Zero-dependency stack: SwiftData, CoreLocation, PassKit, WatchConnectivity. Apple frameworks only.
4 phases: card management → geofencing → Watch companion → widgets.
Multi-target XcodeGen project, TestFlight with 4 targets across 2 operating systems.
What Shipped
3
Platforms
0
Dependencies
4
Widget families
7
Barcode formats
iOS app, Apple Watch app, Apple Wallet passes, and 4 widget families — all from zero third-party dependencies. In TestFlight now. Business-side marketplace platform in active development.
- 3 platforms shipped: iPhone, Apple Watch, Apple Wallet
- 4 widget families + 4 watch complications
- 7 barcode formats supported
- 0 third-party dependencies (Apple frameworks only)
What I Learned
watchOS is not small iOS. It shares SwiftUI syntax but has different navigation rules, different available frameworks, and different interaction conventions. Four of the eleven bugs I fixed in the final push were platform assumption bugs — things that work on iPhone and silently break on Watch.
Signals for Recruiters