Skip to content

ISBN Barcode Scanning

Quickly add books to your library by scanning their barcode.

Overview

Users can scan the ISBN barcode on physical books using their phone's camera to instantly look up and add books to their library - no typing required.

Requirements

  • Camera permission handling (request, denied state, settings redirect)
  • Real-time barcode detection from camera feed
  • ISBN-10 and ISBN-13 barcode support (EAN-13 format)
  • Haptic/audio feedback on successful scan
  • Quick add flow after scan

User Flow

┌─────────────────┐
│  Tap Scan Icon  │
└────────┬────────┘


┌─────────────────┐     ┌─────────────────┐
│ Camera Active   │────▶│ Permission      │
│ (has permission)│     │ Denied Screen   │
└────────┬────────┘     └─────────────────┘
         │ Barcode detected

┌─────────────────┐
│ Lookup ISBN     │
└────────┬────────┘

    ┌────┴────┐
    ▼         ▼
┌───────┐  ┌─────────────────┐
│ Found │  │ Not Found       │
└───┬───┘  │ (manual entry?) │
    │      └─────────────────┘

┌─────────────────┐
│ Book Preview    │
│ + Status Select │
└────────┬────────┘


┌─────────────────┐
│ Added to Library│
│ (with feedback) │
└─────────────────┘

Technical Approach

Expo Camera + Barcode Scanner

Use expo-camera with barcode scanning capabilities:

typescript
import { CameraView, useCameraPermissions } from 'expo-camera';

function BarcodeScanner() {
  const [permission, requestPermission] = useCameraPermissions();

  const handleBarcodeScanned = ({ type, data }) => {
    if (type === 'ean13' || type === 'ean8') {
      // data contains the ISBN
      lookupBook(data);
    }
  };

  return (
    <CameraView
      facing="back"
      barcodeScannerSettings={{
        barcodeTypes: ['ean13', 'ean8'],
      }}
      onBarcodeScanned={handleBarcodeScanned}
    />
  );
}

ISBN Validation

Validate scanned barcodes before API lookup:

typescript
function isValidISBN13(isbn: string): boolean {
  if (isbn.length !== 13) return false;
  if (!isbn.startsWith('978') && !isbn.startsWith('979')) return false;

  // Check digit validation
  let sum = 0;
  for (let i = 0; i < 12; i++) {
    sum += parseInt(isbn[i]) * (i % 2 === 0 ? 1 : 3);
  }
  const checkDigit = (10 - (sum % 10)) % 10;
  return checkDigit === parseInt(isbn[12]);
}

Debouncing & State

Prevent duplicate scans and handle rapid-fire detection:

typescript
const [scanned, setScanned] = useState(false);
const [lastScannedISBN, setLastScannedISBN] = useState<string | null>(null);

const handleBarcodeScanned = ({ data }) => {
  if (scanned || data === lastScannedISBN) return;

  setScanned(true);
  setLastScannedISBN(data);

  // Haptic feedback
  Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);

  // Lookup and show result
  lookupAndShowBook(data);
};

UI Components

Scanner Screen

  • Full-screen camera view
  • Viewfinder overlay (rectangular guide)
  • Cancel/close button
  • Flash toggle (for low light)
  • Manual ISBN entry fallback link

Book Found Modal

  • Book cover thumbnail
  • Title and author
  • Quick status selector (Want to Read, Currently Reading, Finished)
  • "Add to Library" CTA
  • "Scan Another" option

Not Found State

  • "Book not found" message
  • ISBN that was scanned
  • Option to try again
  • Link to manual search/entry

Edge Cases

ScenarioHandling
Camera permission deniedShow explanation + "Open Settings" button
Book not in databaseOffer manual entry or search
Poor lightingSuggest enabling flash
Non-book barcode scannedIgnore (only process ISBN prefixes)
Network error during lookupShow retry option with scanned ISBN
Multiple barcodes in frameProcess first valid ISBN detected

Accessibility

  • VoiceOver announcements for scan results
  • Alternative manual entry always available
  • High contrast viewfinder overlay
  • Audio feedback option (not just haptic)

Dependencies

json
{
  "expo-camera": "~16.0.0",
  "expo-haptics": "~14.0.0"
}

API Integration

Scanner triggers existing book lookup endpoint:

GET /books/isbn/{isbn}

Returns book data if found, 404 if not. See Book Data Sources for lookup strategy.

Metrics

Track to measure feature success:

  • Scans attempted per user
  • Scan success rate (found vs not found)
  • Time from scan to add
  • Scanner abandonment rate
  • Manual entry fallback usage

Open Questions

  • [ ] Support scanning from photos (gallery import)?
  • [ ] Batch scanning mode (scan multiple books quickly)?
  • [ ] Offline scanning with sync later?
  • [ ] What if user scans a book they already have?

Built with VitePress