Skip to content
jaimebgPublic

About

Privacy-first receipt scanner for Spanish supermarkets: on-device ML Kit OCR, offline SQLite storage and spending analytics. React Native + Expo, iOS & Android.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

312 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CestApp Logo

CestApp

Supermarket receipt scanner that respects your privacy.

Scan receipts from Mercadona, Carrefour, Lidl, and more. Track spending. Keep your data local. Started in Spain, opening to more countries one chain at a time.

Latest release License: MIT PRs Welcome Platform: iOS | Android Expo SDK 57 React Native 0.86.2 TypeScript Privacy: 100% Local


The dashboard, receipt review, history, analytics, how a receipt was read, and settings


Status

1.1.0 is in review at the App Store and Google Play.

Why CestApp?

  • 100% on-device: ML Kit OCR runs locally. No cloud uploads.
  • Any format: Document scanner, gallery, or PDF.
  • Smart categories: Auto-sorts items. Learns from your corrections.
  • Supermarket templates: Pre-trained templates for Spanish chains, with a contribution path for every other country.
  • Multi-language: English & Spanish UI.

Features

Capture: Document scanner (auto-crop & enhance), gallery import, PDFs. CestApp reads a capture on the spot and opens it in review.

Review: Edit the store, date, total and every line before saving. "How it was read" shows the zones over the receipt and the recognized text. If the reading is off, redraw the zones or crop the image to the receipt, and CestApp reads it again. It warns you before you save a duplicate.

Smart Parsing: Chain-specific templates detect Mercadona, Carrefour, Lidl, Eroski, Dia, Consum, Alcampo, Aldi, HiperDino by NIF/name patterns.

Smart reading (iOS): On iPhones with Apple Intelligence, an on-device model repairs receipts the OCR read badly. CestApp keeps only the items it can match to the OCR text, and checks that their prices add up to the total.

Organize: 11 built-in categories, auto-categorization, user learning, store detection.

Analyze: Monthly trends, category breakdowns, store comparisons, top items.

Privacy: Offline-first, local SQLite, no tracking, no ads. Export everything to a JSON backup. Full policy: jbgsoft.com/cestapp/privacy.

Details: Phone and tablet layouts, dark mode, each receipt kept in its own currency and amounts written the way your language writes them, animations that respect Reduce Motion.

Installation

git clone https://github.com/jaimebg/CestApp.git
cd CestApp
npm install

# Dev build required (ML Kit needs native code)
npx expo run:ios     # or
npx expo run:android

Expo Go won't work. You need a development build.

Tech Stack

Category Technology
Framework React Native 0.86.2 + Expo SDK 57
Navigation Expo Router
Styling NativeWind v4
Database Drizzle ORM + expo-sqlite
State Zustand v5
OCR ML Kit (@infinitered)
Fiscal QR ZXing (Android), Vision (iOS)
LLM Apple Foundation Models (iOS)
PDF Custom parser + pako
i18n i18next
Animations Reanimated v4
Charts react-native-gifted-charts

Project Structure

app/           # Screens (Expo Router)
src/
  components/  # UI components
  config/      # Countries and their chain templates, currencies
  db/          # Schema, migrations & queries
  services/    # OCR, fiscal QR, PDF, capture, storage, LLM
  store/       # Zustand state
  theme/       # Palette & type
  i18n/        # Translations
scripts/
  store-screenshots/  # Captures, frames and lays out the store screenshots
  fixtures/           # Scrubs a recorded capture into a chain fixture
modules/
  qr-decoder/         # Native QR decoding for fiscal codes

Development

npx tsc --noEmit   # Type check
npm test           # Jest, including fixture-based parser tests
npm run check      # ESLint + Prettier

CI runs all three on every push. If you change the parser, extend the fixtures in src/services/ocr/__tests__/. Chain fixtures under src/config/countries/*/__tests__/fixtures/ test themselves; npm run fixture makes one from a recorded capture (see CONTRIBUTING.md).

Store screenshots regenerate end to end with npm run shots:all, with no manual step. It renders the sample ticket and boots two dedicated Android emulators (a phone and a tablet, created upright on first use so your development AVDs are never touched). It builds a release APK in screenshot mode (EXPO_PUBLIC_SCREENSHOTS=1, wiped from android/ when the run ends so no store build can pick it up), seeds demo data, opens each screen through cestapp:///screenshots deep links and captures it once the screen stops moving. Finally it frames the captures for the App Store and Google Play in English and Spanish, and lays out the panorama at the top of this README.

Releases build locally and ship through fastlane. The fastlane/ folder holds credentials and store assets, so it stays out of the repo.

How It Works

  1. Detect Chain and Country: Identifies the supermarket and its country by tax ID, store name patterns, or fingerprints (brand names like "Hacendado" for Mercadona). Where the receipt carries a fiscal QR code readable offline (Portugal, Austria), its total, date and tax ID take precedence
  2. Apply Template: Uses chain-specific parsing rules (layout, item patterns, OCR corrections)
  3. Extract: ML Kit OCR for images, custom parser for PDFs. The parser uses the capture's zones when it has them, then the geometry of its text blocks, then its lines alone
  4. Categorize: User corrections → keyword matching → default

Learning is store-aware: same item can have different categories at different stores.

Supported Countries and Chains

Country Chains
Spain Mercadona, Carrefour, Lidl, Eroski, Dia, Consum, Alcampo, Aldi, HiperDino (with IGIC tax for Canarias)
Portugal None yet: fiscal QR codes are read, chains are waiting for contributions
Austria None yet: fiscal QR codes are read, chains are waiting for contributions

Your country or chain is missing? Donate a ticket: a photo is enough.

Contributing

The most useful contributions are receipts and chain templates from countries CestApp can't read yet: donate a ticket (no code needed), or write the template for a donated one. CONTRIBUTING.md covers both, plus adding a country or a UI language.

License

MIT. See LICENSE.


Made with care by JBGSoft - Jaime Barreto 🧡

About

Privacy-first receipt scanner for Spanish supermarkets: on-device ML Kit OCR, offline SQLite storage and spending analytics. React Native + Expo, iOS & Android.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages