Inspiration

Every card tracker on the market assumes you are an English-speaking collector buying on one marketplace. We are not. A Charizard is not one card: it is an English card, an Italian card, a Japanese card and a Simplified Chinese card, each with its own print run, its own scarcity and its own price, and the gap between them can be 10x. Ask five apps what a collection is worth and you get five confident numbers, none of which tells you which market, which language, which condition or which printing it refers to.

So we started from an uncomfortable question: what is a collection honestly worth, right now? The honest answer is never a single number. It is a number plus how sure you can be about it. That became the whole product.

What it does

RareBit takes a collector from "what do I own" to "what should I do about it".

  • Scan. Point the camera at a card. Identification runs fully on-device (perceptual hashing, OCR and a small embedding model), so recognition works offline and photos never leave the phone.
  • Track. What actually determines value: language, condition, printing (normal / holo / reverse), grading, sealed vs singles, and multiple copies of the same card bought at different prices.
  • Price. Against the real markets, not one of them: Cardmarket (EU), TCGplayer (US), PriceCharting, CardTrader, graded sales on eBay, plus Japanese and Chinese sources for the Eastern print lines.
  • Decide. Price history, market movers, alerts, and the raw-vs-graded spread that tells you whether a card is worth sending in for grading before you sell it.

Four games (Pokémon, One Piece, Lorcana, Riftbound). The catalog tracks cards in eight languages, including the Japanese, Simplified Chinese and Korean print lines, and the interface itself is fully localized in six (EN, IT, ES, FR, DE, JA), on web, iOS and Android.

Every price carries a confidence indicator. If all we have is a stale quote, or a quote from a different market than the language you own, the app says so instead of inventing precision.

The business model mirrors the product's honesty. The free tier is the map: a complete mirror of your collection with full value, unlimited CSV export, no lock-in. Premium is the compass: history, movers, alerts. Subscriptions run on RevenueCat on mobile and Stripe on the web. We charge for the decision, never for the exit: if RareBit stops being useful, you leave with all your data in one click.

How we built it

A TypeScript monorepo, three surfaces, one data spine.

  • API: NestJS on Fastify, Prisma, PostgreSQL, JWT, nestjs-i18n.
  • Web: Next.js 15 App Router, TailwindCSS, Radix, TanStack Query, next-intl with six fully localized route trees.
  • Mobile: React Native / Expo; on-device inference for the scanner (ExecuTorch, Tesseract, pHash); RevenueCat powering subscriptions and entitlements across the App Store and Play Store.
  • Content: Payload CMS for the multilingual blog.
  • Infra: Docker Compose behind Caddy on a single Hetzner VPS running three environments; GitHub Actions ships develop to dev and a v* tag to prod; nightly price jobs run as systemd timers with their own watchdogs; Sentry for errors, Stripe and RevenueCat for billing.

The interesting half is the data pipeline. Each price source is an idempotent importer plus a fetcher writing into one append-only PriceSnapshot table, today about 39.7 million rows across 66,063 cards and 751 sets. Nothing in the UI reads a source directly: a read model resolves market × language × condition × printing into the single number you see, and records how it got there.

Challenges we ran into

  • No price source publishes a condition ladder. Marketplaces quote near-mint and nothing else. We derive the rest in the read model with an explicit, documented multiplier matrix, and we label it as derived rather than passing it off as observed data.
  • The same card is many cards. Matching the Western and Japanese printings of the same artwork has no shared identifier: set codes differ, numbering differs, names differ. We ended up bridging them with a perceptual-hash signature built from the scanner, which took coverage from 66% to ~90%.
  • At 39 million rows, a wrong price is worse than no price. A single bad decimal from an upstream source poisons a chart and destroys trust instantly. We built anomaly guards (a quote that jumps 10x is quarantined, not published) plus a nightly sanitizer, then went back and cleaned tens of thousands of historical rows.
  • On-device scanning on cheap Android phones. Our first scanner crashed with a native SIGSEGV inside the JS engine's garbage collector, and only on low-end devices. The fix was moving image decoding off the JS thread entirely. "It works on my phone" is not a test strategy.
  • Upstream catalogs are not stable. Publishers rename expansions and renumber sets, and every rename silently breaks a join key somewhere. We made identifiers immutable on our side and treat every importer as add-only.

Accomplishments that we're proud of

It is live, in production, and in both stores, not a prototype. Roughly 40 million price points across 66,000 cards and 751 sets, served through one read model that can always say where a number came from. Six interface languages from day one rather than English plus an afterthought, on a catalog that speaks eight. And a free tier that exports everything, forever: if RareBit stops being useful, you can leave with your data in one click. Building that on purpose, into a paid product, is the decision we would defend hardest.

What we learned

Honesty is a feature you can ship. Users do not punish "we are not sure about this number"; they punish the confident number that turns out to be wrong. The same held for monetization: a free tier with a real exit builds more paying subscribers than a locked door. And in a data product, the UI is the easy part: everything hard lives in provenance, in reconciliation, and in the discipline to say where a number came from.

What's next for RareBit

More games and deeper Eastern coverage (the Chinese and Korean print lines are already in the catalog; next is closing their price coverage), richer grading signals (raw-vs-slab spreads per grade), and a public API so collectors, shops and communities can build on the same data spine we use ourselves.

Built With

Share this project:

Updates