Project 2 of 5
CardScope
Computer vision that identifies an object from a photo, and a third-party integration that never acts without a human's explicit sign-off.
Why this matters to a client
Why this matters to a client
Two capabilities most multi-site operators eventually need: turning a photo into structured data (document intake, chart abstraction, anything currently keyed in by hand), and connecting to an outside platform that can take an action you can't undo — publish a listing, submit a claim, send a payment. The interesting engineering isn't the AI call, it's what happens around it: what a system does when a user doesn't confirm, when a request fails halfway, or when someone clicks the button twice.
What it does
What it does
CardScope identifies a trading card from a photo, extracts structured data about it (player, year, set, grade, condition), and lets the owner list it for sale on eBay. It does not price the card automatically — it links out to real sold listings so the owner can judge value themselves, and the owner sets the price.
Product screenshots
Placeholder — not a real screenshot. CardScope product imagery to be added before launch.
How it's built
How it's built
Technical detailFor readers who want the engineering — skip ahead if you just want the outcome.
Next.js on Vercel, PostgreSQL via Prisma. Photo identification calls OpenAI's vision API with a strict JSON schema so the model returns fixed, structured fields instead of free text — it's instructed to leave a field blank rather than guess. The eBay integration is a standard OAuth flow with tokens encrypted at rest (AES-256-GCM, random IV per token, verified auth tag). Before anything reaches eBay, a review screen shows the exact title, price, and condition fields pulled live from eBay's own category schema, and nothing is sent until the owner clicks publish. The publish call is idempotent: if it's clicked twice, or fails partway through, the code checks what already exists on eBay before creating anything new, so a retry can't create a duplicate listing or publish a stale price.
The interesting decision
The interesting decision
The easy version of "publish to eBay" is one API call behind one button. The harder, safer version treats publish as a resumable multi-step operation: create or update the inventory item, create or reuse the offer, then publish it — recording each step's result so a network failure partway through leaves the listing in a state that can be safely retried, not one that's silently duplicated or half-published. That's more code for a feature that, from the outside, looks identical either way. It's also the difference between a demo and something you'd trust with a real account.
Status
Status
Deployed and running in production. The scan-and-identify flow is live. The eBay publish flow is fully built — OAuth, encrypted tokens, the confirmation gate, the retry-safe publish sequence — but is currently switched off: the eBay credentials required to reach eBay's servers are not set in the live environment, so nothing can publish yet. It needs one supervised end-to-end test against eBay's own sandbox before it's turned on.