Selected Work - Engineering

MintCollect - the trading-card commerce platform

A trading-card data and commerce platform: real-time card identification, a multi-mode marketplace, a portfolio/price-tracking engine, and a subscription layer - built mobile-first and scaled for influencer-driven traffic spikes.

Role

Founding Software Engineer

Stack

React Native · Flask · PostgreSQL · AWS

Links

App Store · GitHub

01Overview

MintCollect lets collectors scan, value, organize, and trade cards from their phone. As founding engineer I own the React Native client and a large share of the Python and Flask backend, from the scanning pipeline and the portfolio ledger to the marketplace and payments, working alongside a small backend team. Today it backs 50k+ accounts against a 185k-card catalog, served by 230+ API endpoints and a PostgreSQL schema of 100+ tables.

02What I built

  • Card identification pipeline - phone-camera capture wired to the Ximilar vision API for server-side recognition, mapping a photo to a specific card, variant, and printing across 185k+ catalog entries.

  • Portfolio & ledger engine - an append-only collection ledger with FIFO cost-basis accounting, idempotent writes, and pre-aggregated rollup tables so net-profit and collection-value math stays correct and fast.

  • Multi-mode marketplace - a unified Product → Listing → Inventory model with pool-based inventory, SKIP LOCKED reservation at checkout, Stripe-hosted payment, and a full order → shipment → refund → dispute lifecycle.

  • Subscription layer - tiered access (free + paid tiers) with server-side receipt verification via RevenueCat / StoreKit webhooks, so entitlements are provable, not claimed.

  • Data layer - a React Query fetching/caching strategy on the client and a fail-open Redis cache with per-account epoch invalidation on the server.

  • Internationalization - the full UI localized into 7 languages (en/es/fr/de/ja/ko/zh).

  • Admin dashboard - a Vite + React control plane for catalog, marketplace, orders/disputes, news, and app-control (maintenance mode, forced updates, version gating).

  • Load readiness - a pre-launch stress-testing plan for influencer-driven concurrency spikes.

03Architecture

Mobile App

React Native · Expo

Admin Dashboard

Vite · React

API Layer

Flask · Gunicorn behind Nginx on AWS EC2

Scanner

Ximilar Vision API

Data

PostgreSQL 16.8 · AWS RDS

Cache

Redis · rate limiting

Payments

Stripe · RevenueCat

Media

S3 + CloudFront

Two clients, a React Native app and a React admin dashboard, talk to a Flask API behind Nginx on AWS EC2. The API uses PostgreSQL on RDS for data, Redis for caching and rate limiting, and S3 with CloudFront for images, plus external services for recognition, payments, and subscriptions through Ximilar, Stripe, and RevenueCat.

04Technical challenges

Card recognition from a photo

Problem
Cards have to be recognized from a phone photo in poor lighting, across thousands of near-identical printings and variants.
Approach
I sent the camera capture to the Ximilar vision API for server-side recognition, then resolved the match against the 185k-card catalog from card to variant to printing, with pg_trgm fuzzy search as a fallback.
Result
Capture-to-match is fast and separates close variants instead of guessing between them.

Concurrency-safe ledger math

Problem
Collection value and profit had to stay correct as people bought and sold, with no double counting when writes overlapped across a 3.5M-row history.
Approach
I kept an append-only ledger with FIFO cost basis and idempotency keys, locked rows on write with SELECT FOR UPDATE, and precomputed rollup tables that I keep current with ON CONFLICT upserts.
Result
The numbers stay accurate, reads skip the full ledger, and a nightly drift check has held at zero.

No oversells at checkout

Problem
Two buyers can race for the last copy of an item, and a client that believes it paid cannot be trusted to create the order.
Approach
I reserved stock from a shared pool with SELECT FOR UPDATE SKIP LOCKED at checkout and made the Stripe webhook the only thing that creates an order.
Result
Orders only exist after confirmed payment, and the last copy never sells twice.

Sub-30ms search over 185k cards

Problem
The original search scanned three text fields sequentially and could not keep up with as-you-type queries from power users and vendors.
Approach
I built one /catalog/search endpoint on pg_trgm GIN indexes with a small query language (multi-term AND, quoted exact match, exclusions, card-number facets) and a fuzzy fallback that runs only when the exact pass is thin.
Result
Fuzzy matches return in about 29 ms over 185k live cards, measured with EXPLAIN ANALYZE.
Pokédex catalog
Portfolio analytics
Marketplace
Card scanner

05Stack & why

React Native for one mobile codebase, Flask and PostgreSQL for the data and pricing work.

React NativeTypeScriptReact QueryNativeWindZustandFlaskPythonPostgreSQLRedisAWSNginxGunicornStripeRevenueCatXimilarSentry

06Outcomes

iOS / Android

Shipped to both stores

50k+

Registered accounts

185k+

Cards cataloged · 1,642 sets · 4,044 sealed

230+

API endpoints

9 / 100+

Postgres schemas / tables

7

Localized languages