All Work

iPhone card list + Watch complication + Apple Wallet pass — three surfaces in one composed frame. Show the card auto-surfacing via geofence notification.

February 2025iOSwatchOSApple WalletIn TestFlight

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.

Product Strategy

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.

Interaction Model

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.

Information Design

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.'

Platform Constraint

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.

Systems Thinking

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

1
Observation

Paper punch card at a coffee shop — a market failure hiding as nostalgia.

2
Architecture

Zero-dependency stack: SwiftData, CoreLocation, PassKit, WatchConnectivity. Apple frameworks only.

3
Build

4 phases: card management → geofencing → Watch companion → widgets.

4
Ship

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

Multi-platform systems thinking (iPhone + Watch + Wallet + Widgets)Business model design (two-sided marketplace, pricing strategy)Field observation → product insight → shipped product pipelinePlatform-specific craft (not just responsive — truly native per surface)