---
name: iphone-camera-barcode-scanner
description: Use when adding or improving iPhone camera barcode scanning, UPC scanning, or mobile scanner flows in Expo React Native apps. Applies to iOS/iPhone and Android camera scanners built with expo-camera CameraView, including Valet Ballet apps such as DVD Valet, Pull Tab Valet, and CDC Valet. Covers permissions, scanner overlays, duplicate suppression, scan locks, manual fallback, local-first persistence, and real-device validation.
metadata:
  short-description: Add iPhone camera barcode scanning
---

# iPhone Camera Barcode Scanner

Use this skill when adding or improving scanner flows in Expo React Native apps, especially collection, inventory, media library, ticketing, venue, and retail apps that use a phone camera as a barcode or UPC scanner.

## Core Pattern

Prefer `expo-camera` with `CameraView`.

Do not use the deprecated standalone `expo-barcode-scanner` package unless the repo already depends on it and the user explicitly wants to preserve it.

Expected flow:

1. Ensure local schema/storage is ready before scanning.
2. Request camera permission only when the user starts scanning.
3. Show a native camera view on mobile; provide manual entry on desktop/web or when scanning is unavailable.
4. Normalize scanned values before saving.
5. Ignore empty/invalid values.
6. Suppress immediate duplicate reads with a ref such as `lastUpcRef`.
7. Prevent concurrent save/navigation with a ref such as `scanLockRef`.
8. Save locally first so scanning works offline.
9. Give fast feedback after a successful scan.
10. Route to the next useful screen only after persistence succeeds.

## Implementation Notes

For simple UPC apps, use a narrow barcode list:

```ts
barcodeScannerSettings={{ barcodeTypes: ['upc_a', 'ean13'] }}
```

For broader box, ticket, or inventory code apps, expand the supported barcode types and keep validation domain-specific.

Use stable UI geometry:

- full-screen camera or modal camera surface
- high-contrast overlay
- visible scan frame
- `Done` / `Close` action
- `Reset` or manual fallback when useful
- short saved/error feedback

Keep the scanner resilient:

- clear duplicate refs when starting a new scan session
- release `scanLockRef` on failure
- avoid saving while a previous scan is in flight
- keep manual entry using the same normalization and save path as camera scans

## Validation

After changes:

1. Run TypeScript:

```bash
npx tsc --noEmit
```

2. Start Expo with LAN mode for iPhone testing:

```bash
npx expo start --clear --lan --port 8082
```

3. Test on a real iPhone when possible:

- permission prompt appears only when scanner starts
- camera view is not blank
- valid barcode saves once
- immediate repeated reads are ignored
- manual entry still works
- offline/local save path works
- navigation after scan is correct

## Porting Checklist

- Match the target app's naming, colors, and navigation routes.
- Reuse the target app's existing DB helpers instead of copying another app's data APIs wholesale.
- Keep domain-specific validation separate from generic scanner mechanics.
- Do not introduce authentication for scanner use unless the app already requires it.
- Prefer small, local edits over refactoring unrelated screens.
