Building kardfolio from a fuzzy problem to a live product.
A credit-card tool became a test of product framing, cross-platform architecture, and the domain details that separate a demo from maintained software.


- Role
- Solo founder and product engineer
- Scope
- Strategy, UX, web, native iOS, data, analytics, launch
- Timeline
- September 2025—present
- Stack
- Next.js, SwiftUI, Hono, Supabase, PostHog, Stripe, RevenueCat
01 / Product problem
The problem was not tracking. It was decision confidence.
Premium credit cards distribute value across monthly credits, annual benefits, renewal dates, eligibility rules, and spending categories. The information exists, but it is scattered across issuer portals, statements, emails, and memory.
Instead of building another transaction dashboard, I framed the product around two questions: What should someone use next, and which cards are still worth keeping?
That became kardfolio: a web and native iOS product for reviewing benefits, recording usage, and making keep, downgrade, or cancel decisions—without requiring bank credentials.
Ask only for the context needed for the next decision.
Less automatic data, but a clearer relationship with the user’s information.
One domain model, two genuinely native surfaces.
Behavior, identity, and subscription state stay aligned across web and iOS.
Deterministic product value comes first.
Kai explains saved card context; it does not replace the core workflow.
Platform capability is a product decision.
Web and iOS stay consistent without pretending their capabilities are identical.
02 / Architecture
One domain, two product surfaces.
The architectural question was not how to share everything. It was what must remain consistent across clients—and what should stay native.
- Card and benefit domain rules
- Identity and user-data isolation
- Subscription entitlements
- Activation and core-use definitions
- Date and cycle behavior
03 / Engineering decision
A date that looked like a timestamp was not a timestamp.
A benefit usage date is a civil day. Parsing it as midnight UTC can make a local interface display the previous date. Formatter patches treated the symptom while leaving the domain error intact.
I introduced explicit concepts for CalendarDate, Instant, IssuerClock, and UserClock. User-entered dates now stay calendar dates through TypeScript, the API, Postgres, and Swift, with boundary tests protecting time-zone behavior.
2025-03-16parsed as midnight UTCMar 15CalendarDate("2025-03-16")remains a civil dayMar 1604 / Delivery and learning
A maintained product—not a launch artifact.
kardfolio is live on the web and as a native iOS app. Post-launch work has included a clearer Today experience, more accurate benefit progress and history, iOS Profiles, performance improvements, and ongoing catalog, billing, analytics, and release operations.
I separated account creation from realized value in the instrumentation: adding a first card, returning, and recording benefit usage are different signals. The evidence guides what to improve; page views do not stand in for product outcomes.
If I started again, I would formalize the date and platform-capability contracts earlier, constrain the first-value loop sooner, and schedule more customer conversations before polishing lower-priority surfaces.
