Scan to data

Camera or photo becomes structured data (receipt, business card, event, or your own schema) via on-device OCR and the local model.

Mock· scripted answersNo model runs in a browser, so every answer here is scripted. On a phone it comes from the model.
  • Apple Foundation Models: supported
  • Gemini Nano: supported
  • Llama (not yet supported): not supported
  • A cloud model: supported
  • The text in the photo comes from an OCR you pass in as ocr (Apple Vision or ML Kit Text Recognition). The model only turns that text into fields.

Install

npx ondai add scan-to-data

Usage

import { ScanToData } from '@/components/ondai/scan-to-data'
import TextRecognition from '@react-native-ml-kit/text-recognition'

<ScanToData
  preset="receipt"
  ocr={async (img) => (await TextRecognition.recognize(img.uri)).text}
  onData={(receipt) => expenses.add(receipt)}
/>
  • OCR runs on device through the ocr function you pass (ML Kit, Apple Vision). The model only sees text, which also keeps the request inside the 4K budget.
  • Presets: receipt, businessCard, event; or preset="custom" with your own zod schema.

Customize

Every AI component takes the same look and customization props, so it fits your app rather than ours.

<ScanToData
  variant="pop"
  tint="#FF5A5F"
  size="lg"
  radius={12}
  icons={{ scan: Search, camera: null }}
  labels={{ subject: '…', scan: '…' }}
/>
PropWhat it does
variantThe look of the whole component: clean, minimal, glass, pop, candy, metal, shine
sizesm, md, lg; type, rows, icons and keys scale together
tintAny colour; the variant paints its keys, tiles and glow in it
radiusCorner radius of the container
iconsReplace any icon (a lucide component, an element, or null to hide it): scan, camera, library, reading, finding, done, error, retake
labelsEvery visible and spoken string; defaults are exported as scanToDataLabels: subject, scan, scanHint, takePhoto, choosePhoto, noOcr, reading, read, gotText, lines, finding, findingMany, andMore, found, foundOne, fromYour, check, scanAgain, use, retake, error, scanning, scanAnother
SlotsDraw a part yourself: renderEmpty, renderRow, renderResult, renderUse
stylesStyle any named part

Variants

PropOptions
variantclean, minimal, glass, pop, candy, metal, shine
presentationcamera, picker, card
sizesm, md, lg
presetreceipt, businessCard, event, custom

Token budget

Input budget: 1500 tokens. OCR text (not the image) goes to the model; fields refined deterministically.

Fallback

When no provider is ready the component renders the unavailable state (AvailabilityGate copy) and, where a deterministic path exists, keeps working without the model.

Eval score

Fixtures: evals/scan-to-data/fixtures.json.

Files

Registry dependencies: button, on-device-badge, shimmer-text, surface

npm dependencies: @ondai/core, @ondai/tokens, expo-haptics, expo-image-picker, lucide-react-native, react-native-reanimated, react-native-svg, zod

On this page