React Native ยท Expo ยท On-device OCR

No cloud. No account.
Just your receipts.

Receipt Scanner turns paper receipts into structured, searchable records โ€” merchant, date, items, tax, total โ€” using on-device OCR. The camera, the parsing, and the storage never leave your phone.

Expo SDK 57 ยท RN 0.86 On-device ML Kit OCR SQLite, no backend English + Italian parsing
One scan, structured

From paper to data, with a confidence score on every field.

GROCERY MART 03/09/2026 1 Bread 3.50 2 Milk 2.20 1 Coffee 6.99 3 Apples 4.80 SUBTOTAL 17.49 TAX 1.40 TOTAL 18.89
โ†’
MerchantGrocery MartDetected
Date03/09/2026Detected
Items4 itemsDetected
Subtotal17.49Detected
Tax1.40Needs review
Total18.89Detected

Illustrative sample โ€” every field a real scan produces gets this same Detected / Needs review treatment before you save it.

Where things actually stand

Confirmed, and not yet confirmed.

Confirmed on a real Android device

  • Settings screen
  • History empty state
  • Camera-permission screen

All render correctly, matching the built design exactly.

Not yet end-to-end confirmed

  • A full capture โ†’ OCR โ†’ parse โ†’ save round trip on an actual receipt

Each piece is checked independently โ€” the parser against realistic sample OCR text, the storage layer's SQL against a real SQLite engine, a clean Metro bundle for both platforms โ€” but that's not the same as scanning a real receipt end to end.

No live receipt edge detection yet โ€” capture is manual: position, then tap.

Parsing is heuristic and keyword-based. Unusual layouts โ€” handwritten, extremely faded, non-tabular โ€” will likely need the parser extended.

The scanner frame's size is computed once at mount, not reactive to window changes like Android split-screen.

Why it's built this way

Five calls made without a device attached.

01

On-device OCR, not a cloud API

Privacy is the whole premise here, not a feature bullet point. A cloud OCR call was never on the table, regardless of any accuracy tradeoff.

02

Manual capture, not live edge detection

Real-time document detection needs frame-by-frame computer vision โ€” a large native surface that's hard to get right without a device to test against. Position-and-tap is simpler, and how most receipt apps actually work.

03

React Native's Animated, not Reanimated

Reanimated needs its own native build step and worklet config. Animated ships with core React Native โ€” the safer choice to build without a device attached to verify the config against.

04

The parser returns null, never a guess

An invented total or date is worse than an empty field โ€” a wrong-but-confident-looking number is the error a user won't think to double-check. The review screen is where a human confirms it.

05

One dark theme, not an unfinished light one

The dark navy and violet look isn't a color scheme bolted on โ€” it's the whole visual identity, down to the scanner glow. A half-built light mode would dilute that, not extend it.

Get started

Best tried on an actual phone.

01

Clone and install

git clone https://github.com/mirconegri/receipt-scanner.git

npm install

02

Build a dev client (needs a real device)

npx expo prebuild, then npx expo run:android โ€” or run:ios with a Mac and Xcode.

03

Verify without a device

npm run verify-parser, npm run verify-sql, npm run typecheck, npm run lint

04

Or build for testing on Expo's servers

npx eas-cli@latest build --profile preview --platform android โ€” no local Xcode or Android Studio needed.

Built in the open, verified where it could be.

Look at the code, run the verifiers, or open an issue.

Real end-to-end scanLive edge detectionCSV/PDF exportCategory taggingMore localesOpt-in cloud backup