16 — Dating: Swipe Deck & Discovery UI
UI project 3 of 5 · IOS/TheOne/Dating, app/web-platform/app/dating
Stack: SwiftUI + gesture-driven card stack, Next.js/React web tier, MatchService backend
Scope: iOS 147 files · 90,161 lines — the largest single mode in the app
Where this sits. The swipe deck is the most recognizable interaction pattern in consumer software, and it is a harder engineering problem than it looks: gesture physics, prefetch, optimistic state, and an undo that has to survive a network failure. It also carries the portfolio's most useful negative finding.
The surface
Containers/MatchSwipeStack.swift the card stack and its gesture layer
MatchService/MatchDeck.swift deck state, prefetch, exhaustion
MatchService/DatingMatchCard.swift card model
Components/components/MatchSwipeCard.swift the rendered card
Types/SwipeAction.swift like / pass / super, as a type
Beacon/ Inbox/ Profile/ Engines/ ViewModels/ Views/
Plus discovery, profile, prompts, favorites, an inbox, and a web counterpart in
app/web-platform/app/dating.
What is actually hard here
The deck is a distributed-systems problem wearing a UI costume
A swipe deck is a client-side cache of a server-ranked candidate stream. It has to prefetch ahead of the user, survive exhaustion mid-gesture, exclude already-seen profiles, and stay consistent with a ranking pipeline that is concurrently rewriting scores. That pipeline is Match Service — and the phantom-partition bug documented there surfaced here, as nameless cards in a real user's deck.
That is the connection worth drawing in an interview: the UI is where the distributed-systems defect became visible, and the fix was three inference steps upstream in a Cassandra partition key.
Optimistic swipe, and what happens when the write fails
A swipe must feel instantaneous, so the card leaves the stack before the server
has agreed. If the write then fails, the options are all bad: silently drop the
action, resurrect the card mid-session, or reconcile later. SwipeAction being
a type rather than a boolean is what makes that reconciliation expressible.
Gesture physics
Rotation proportional to horizontal displacement, a velocity-aware release threshold, and a stack that renders the next two cards with scale/offset so the deck reads as physical. Getting the threshold wrong makes an app feel either sticky or trigger-happy.
The honest finding
The Dating mode audit is blunt about this mode, and the write-up is worth more than a clean claim would be:
- iOS swipe paths were dead — the loop was not wired end to end.
- Dual match backends — MatchService ("Highlander") and the gateway both claimed to be the match entry point.
- A three-way identity split across services.
- Three parallel chat table families.
- Credentials committed to a repository.
DATING_REMEDIATION.md records 49 findings (F-01…F-49) with file:line,
severity, and evidence, plus five ready-to-run fix plans. Every architectural
claim cites a real path and line; anything unconfirmable is marked
UNVERIFIED.
Bringing a document that says "the flagship interaction in my largest module was not wired, here is the line, here is the fix plan" is a stronger signal than a portfolio with no defects in it. Nobody believes the second one.
Interview surface this opens
- Client-side caching of a server-ranked stream: prefetch depth, exhaustion, exclusion sets
- Optimistic UI and reconciliation when the write loses
- Why the same entity had two backends, and how you would consolidate without downtime
- Auditing your own code and publishing the findings with severities