Services Case Studies Insights AI Readiness About Start a project →
Android React Native · TypeScript Google Play

Costco Receipt Finder — every item, found.

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.

▷
Get it on Google Play
🔒
Zero-server Local-First Data
Costco Receipt Finder — search by item name or number, export for budgeting, never lose a receipt again
2yr
Purchase history synced
100%
Data stays on-device
0
Servers holding user data
0
Passwords touched
3
Free searches / day
Costco Receipt Finder app icon
Costco Receipt Finder
Search by item name or number
Receipt Sync Fuzzy Search Encrypted SQLite WebView Auth Freemium Local-First

A question Costco’s own app can’t answer.

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.

  • → 01
    Credential-free by design The app never shows its own login form. Costco’s real sign-in page loads in a WebView; injected JavaScript intercepts the bearer token Costco’s own frontend issues after login. Your email and password are never seen by this app.
  • → 02
    Built around a hostile API Costco’s receipt data lives behind a GraphQL endpoint meant for its own web app, with a bearer token that expires in ~15 minutes. The sync engine works within those constraints — rolling 6-month windows, a persisted cursor, graceful failure on token expiry.
  • → 03
    Local-first, genuinely private Receipts, items, and the fuzzy search index all live in an on-device encrypted SQLite database. There is no backend holding member data — uninstalling the app removes everything, which is also the entire privacy policy in one sentence.
  • → 04
    A real monetization path Free tier: 3 searches a day, 3 months of history, non-personalized AdMob ads. A single Google Play Billing purchase unlocks unlimited search and the full 2-year lookback — payment handled entirely by the platform, never by this app.

Small app. Several hard problems.

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.

Feature 01

WebView Authentication

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.

Feature 02

Windowed Sync Engine

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.

Feature 03

Incremental Sync

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.

Feature 04

Fuzzy Search

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.

Feature 05

Encrypted On-Device Storage

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.

Feature 06

Receipt Detail

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.

Feature 07

Freemium Monetization

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.

Feature 08

Clean, Testable Architecture

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.

Feature 09

Resilient Token Handling

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.

Feature 10

Simple, Focused Navigation

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.

The app, in hand.

Real captures from the shipped Android build — the splash screen, a live fuzzy search result, the free-tier paywall, and the synced receipts list.

Costco Receipt Finder splash screen
Splash Screen
Fuzzy search results for "eggs" grouped by item, showing receipt counts
Fuzzy Search Results
Upgrade to Premium paywall shown after the daily free search limit is reached
Freemium Paywall
Synced receipts list showing warehouse, date, and total for each visit
My Receipts

← Scroll to see all screens

Cross-platform, zero bridge overhead.

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
TypeScript 5.8
Framework
React Native 0.84React 19.2
Navigation
React Navigation 7Bottom TabsNative Stack
State
Zustand 5.0
Database
@op-engineering/op-sqlite 15.2JSI, no bridge
Search
Fuse.js 7.1
Networking
Axios 1.14
Auth Capture
react-native-webview 13.16
Secure Storage
react-native-encrypted-storage 4.0
Monetization
Google Mobile Ads 16.3react-native-iap 15.3
Gestures
react-native-gesture-handler 2.30
Dates
Day.js 1.11
Testing
JestESLintPrettier
Min / Target SDK
API 24 (Android 7.0)API 36

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.

— KT Solutions Ltd, on building Costco Receipt Finder

Need a mobile app that syncs against an API you don’t control?

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.

Start a conversation → Our mobile practice ↗
KT Solutions Assistant

Before we start, please share a few details so we can follow up with you.

Please enter your name and a valid email address.

End this conversation? Your chat will be emailed to us.