# 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](03-match-service-distributed-ranking.md) — 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](12-technical-documentation.md) 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