The problem
Collectors of trading and sports cards needed listing, search, auctions, chat, escrow payments, seller payouts and pricing in one app — web and mobile from a single codebase.
Decisions
- Pricing: active eBay asks mix bait listings and typo anchors, and 81% of samples have n ≤ 9, so medians and weighted means say little. The rule trims one listing from each end and takes the minimum; under three samples, no price is shown.
- Auto-confirm comes 7 days after shipment is registered, always ahead of the payment gateway’s 6 days. The 10-day unshipped auto-cancel stayed, on e-commerce refund-law grounds — argued through with the client.
- Fees are calculated on the total including shipping.
What broke — and the fix
- A pre-launch check of auctions found no way to pay for an escrow-mode winning bid, so a dedicated winning-bid payment RPC was added.
- Tapping a notification went nowhere: a route with the same name lived in both a tab and a stack, and the nested navigation was dropped without a warning. Unified on full root paths — 10 of 10 real taps.
Results
- 74 tables · 99 foreign keys · 34 triggers · 242 functions · 8 views
- 119 Deno tests gate every commit (30 money-path signatures)
- Each migration dry-runs 4–11 scenarios inside BEGIN…ROLLBACK on production
- 270+ migrations · 18 admin screens
- Every defect the client reported from web and app confirmed and fixed