A privacy-first mobile app that pulls your own Costco warehouse purchase history onto your phone and makes every item you’ve ever bought instantly searchable — which trip, which warehouse, what you paid. No servers holding your data, no passwords typed into a third-party form, and a working freemium model shipped to Google Play.
Costco gives every member a paper receipt and a purchase history buried in its website, but no way to ask “have I bought this before, and what did I pay?” Costco Receipt Finder was built to answer exactly that — and every architectural decision was made in service of doing it without ever holding a member’s data ourselves.
Every capability exists to solve a specific constraint — a short-lived token, an undocumented API, a member’s expectation of privacy. Nothing was bolted on.
Costco’s real login page loads inside a WebView. Injected JavaScript
patches fetch and XMLHttpRequest to watch the first authenticated
call Costco’s own frontend makes after sign-in, capturing the costco-x-authorization
bearer token and a per-session client-identifier via postMessage.
The app never renders its own login form and never touches a member’s credentials.
Costco’s GraphQL API paginates receipts in date ranges. The sync engine breaks the full two-year lookback into rolling 6-month windows and fetches each in sequence, then pulls itemized detail only for receipts not already stored. Covers in-warehouse, gas station, and car wash receipts.
A last_sync_cursor persisted in the local app_config table means
every sync after the first is incremental — only receipts newer than the last run are
requested. Upgrading to premium clears the cursor once, so the next sync backfills the
full history without ever re-fetching what’s already stored.
A Fuse.js index is built in-memory from every item name in the database on load and after each sync, debounced at 250ms. Results are grouped by item and sorted by most recent purchase — so “eggs” finds every carton you’ve ever bought, misspellings included.
Receipts and line items are written to SQLite via @op-engineering/op-sqlite,
a JSI binding with no bridge overhead, behind versioned migrations applied automatically
on startup. The captured Costco session token lives separately in the OS keystore via
react-native-encrypted-storage.
Tap through from any search result or sync list entry to the full itemized receipt — tender type, taxes, and instant-savings, exactly as it appeared on the warehouse printout, reconstructed entirely from locally stored data.
Free users get 3 searches a day and 3 months of history, with non-personalized AdMob banner and app-open ads. A single non-consumable Google Play Billing purchase removes both limits permanently — entitlement is verified against Play on every app open, so it survives reinstalls.
Distinct layers for the API client, auth service, sync engine, database repositories,
search service, and Zustand stores — each independently testable. Screens consume
hooks (useSync, useSearch, useReceipts) that own
all the async state, keeping components thin.
The Costco bearer token expires roughly every 15 minutes. Rather than pretending to hold a long-lived session, the app degrades gracefully on auth failure and routes the member back to the WebView login to capture a fresh token — no silent data loss, no crash.
Two bottom tabs — Search and My Receipts — behind an auth gate that shows the login stack until a valid session exists. No unnecessary screens, no onboarding funnel; the app opens straight into the thing members came for.
Real captures from the shipped Android build — the splash screen, a live fuzzy search result, the free-tier paywall, and the synced receipts list.
← Scroll to see all screens
A React Native stack chosen for one goal: fast, fully on-device data and search, with no backend to operate or secure.
| Layer | Technology |
|---|---|
| Language | |
| Framework | |
| Navigation | |
| State | |
| Database | |
| Search | |
| Networking | |
| Auth Capture | |
| Secure Storage | |
| Monetization | |
| Gestures | |
| Dates | |
| Testing | |
| Min / Target SDK |
Every layer is separated deliberately: src/api talks to Costco and knows nothing
about storage; src/sync orchestrates windowed fetches and de-duplication;
src/db owns schema migrations and repositories; src/search owns the
Fuse.js index lifecycle; and screens are thin consumers of hooks
(useSync, useSearch, useReceipts) that hold all the
async state. No layer reaches past its neighbor, which kept the sync engine and the paywall
logic independently testable while the UI was still being iterated on.
We don’t sell, trade, or transmit member data because there is no server to send it to — the architecture makes the privacy policy true by construction, not by promise.
Costco Receipt Finder represents the pragmatic side of our mobile practice — credential-free auth, resilient sync against a short-lived token, and a genuinely local-first data layer. If your app needs the same discipline, we’d like to hear about it.
Before we start, please share a few details so we can follow up with you.
End this conversation? Your chat will be emailed to us.