@healthcloudai/hc-document-capture-ui
v0.4.0
Published
React Native UI for document capture — ID, insurance, and selfie scanning with Veryfi Lens / OpenCV.js
Maintainers
Readme
@healthcloudai/hc-document-capture-ui
React Native UI package for document capture — ID scanning, insurance card scanning, and selfie capture — across iOS, Android, and Web.
Provides hooks, services, and optional web components. All backend communication goes through the injected HCSettingsClient from @healthcloudai/hc-settings-connector — no credentials or URLs are hardcoded inside this package.
How it works
App creates DocumentCaptureConfig { settingsClient, registrationTypes?, veryfiCredentials?, theme?, ... }
│
▼
<DocumentCaptureProvider config={...}> ← wrap navigator or screen
│
▼
useDocumentCapture() ← reads config from context
│
├─ Native (iOS/Android): Veryfi Lens SDK → captures image → file URI
│
├─ Web: JScanifyWebCapture (OpenCV.js) or VeryfiLensWebCapture (WASM)
│ → captures image → data URL
│
└─ processCapture(fileUri, type)
│
├─ type listed in registrationTypes? → NO (auth path)
│ │
│ 1. GET canned URL
│ ├─ identification → getDrivingLicenseCannedUrl
│ ├─ healthinsurance → getInsuranceCannedUrl
│ └─ userphoto → getUserImageCannedUrl
│ 2. PUT file → fetch(ImageURL, { method: "PUT" })
│ 3. OCR submit
│ ├─ identification → captureDrivingLicense
│ ├─ healthinsurance → captureInsurance
│ └─ userphoto → captureUserPhoto
│
├─ type listed in registrationTypes? → YES (no-auth path)
│ │
│ 1. GET canned URL → getRegistrationDocumentCannedUrl(type, ext)
│ 2. PUT file → fetch(ImageURL, { method: "PUT" })
│ 3. OCR submit → captureRegistrationDocument(fileId, type)
│
└─ 4. Return OCR data → DriversLicenseData | InsuranceCardDataInstallation
npm install @healthcloudai/hc-document-capture-uiPeer dependencies
| Package | Required | Notes |
|---|---|---|
| react >=18 <20 | ✅ | |
| react-native >=0.72.0 | ✅ | |
| @healthcloudai/hc-settings-connector | ✅ | Provides HCSettingsClient |
| expo-file-system | ✅ | Native file read/write for upload |
| @expo/vector-icons | Optional | Icons used by the capture UI components |
| @veryfi/react-native-veryfi-lens | Optional | Native iOS/Android capture |
| veryfi-lens-wasm | Optional | Web WASM capture |
| expo-camera | Optional | Native fallback camera used by CardCameraCapture |
| expo-image-manipulator | Optional | Crops fallback camera captures to the scan frame |
| expo-image-picker | Optional | Gallery selection |
| heic2any | Optional | Converts HEIC/HEIF uploads to JPEG on web |
| react-native-reanimated >=3.0.0 | Optional | Animations |
Platform setup
iOS
1. Install Veryfi Lens pod
In your Podfile (or via Expo config plugin — see below):
pod 'VeryfiLens', :podspec => 'https://lens.veryfi.com/podspec/veryfi-lens-id-only-framework.podspec'2. Camera permission in Info.plist:
<key>NSCameraUsageDescription</key>
<string>Used to scan ID and insurance documents</string>3. Expo config plugin (recommended):
// app.config.js
export default {
plugins: [
["@healthcloudai/hc-document-capture-ui/plugin"]
]
};The plugin handles pod and permission setup automatically via expo prebuild.
Android
1. Add Veryfi Maven repository
The Expo config plugin does this automatically. Manual alternative in android/build.gradle:
allprojects {
repositories {
maven { url "https://dl.cloudsmith.io/public/veryfi/veryfi-lens/maven/" }
}
}2. Camera permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />3. Minimum SDK
Set minSdkVersion = 26 in android/build.gradle (Veryfi Lens requirement).
Web
No native setup needed. The package uses:
- JScanifyWebCapture — OpenCV.js loaded from CDN (
https://docs.opencv.org/4.x/opencv.js), no installation needed - VeryfiLensWebCapture — requires
veryfi-lens-wasmpeer dep
npm install veryfi-lens-wasmEnsure your Metro / bundler config allows WASM if using VeryfiLensWebCapture.
Configuration
All app-specific concerns are injected via DocumentCaptureConfig. The package never reads environment variables or hardcodes any values.
import { HCSettingsClient } from "@healthcloudai/hc-settings-connector";
import { DocumentCaptureConfig } from "@healthcloudai/hc-document-capture-ui";
// settingsClient is your existing connector instance — same one used by the rest of the app
const settingsClient = new HCSettingsClient(httpClient, loginClient);
const config: DocumentCaptureConfig = {
// Required — owns all canned URL, capture, and save APIs
settingsClient,
// Optional — document types that use the unauthenticated registration path.
// Omit this field (or leave it empty) to use the authenticated path for all types.
// See "Pre-signin vs post-signin capture" below for details.
registrationTypes: ["identification"],
// Optional — Veryfi Lens native/web credentials
veryfiCredentials: {
url: "https://api.veryfi.com/",
clientId: "YOUR_VERYFI_CLIENT_ID",
userName: "YOUR_VERYFI_USERNAME",
apiKey: "YOUR_VERYFI_API_KEY",
},
// Optional — UI color overrides (merged with defaults)
theme: {
primary: "#4caf90", // confirm button, document outline
background: "#000000", // camera backdrop
text: "#FFFFFF", // labels
error: "#F2A0A0", // error messages
overlay: "rgba(0,0,0,0.5)", // close button scrim
},
// Optional — navigation callback
onNavigate: (route, params) => navigation.navigate(route, params),
// Optional — location where the app serves this package's HTML assets
assetBasePath: "/document-capture",
// Optional — self-hosted OpenCV.js URL for JScanifyWebCapture
opencvScriptUrl: "/vendor/opencv.js",
// Optional — structured logger (default: silent)
logger: (level, message, metadata) => {
console.log(`[hc-capture][${level}] ${message}`, metadata ?? "");
},
};DocumentCaptureTheme defaults
| Property | Default | Used for |
|---|---|---|
| background | #000000 | Camera/scanner backdrop |
| text | #FFFFFF | Titles, button labels, loading text |
| primary | #4caf90 | Confirm button, document outline stroke |
| error | #F2A0A0 | Error message text |
| overlay | rgba(0,0,0,0.5) | Close button background scrim |
| surface | #1a1a1a | Dialog and popup surfaces |
| border | #333333 | Dividers, borders, and subtle backgrounds |
DocumentCaptureProvider
Wrap your navigator or screen with the provider before using any hooks from this package.
import { DocumentCaptureProvider } from "@healthcloudai/hc-document-capture-ui";
function App() {
const config: DocumentCaptureConfig = {
settingsClient, // HCSettingsClient instance from hc-settings-connector
veryfiCredentials: { // from app env variables
url: process.env.VERYFI_URL!,
clientId: process.env.VERYFI_CLIENT_ID!,
userName: process.env.VERYFI_USERNAME!,
apiKey: process.env.VERYFI_API_KEY!,
},
theme: { primary: "#4caf90" },
logger: (level, msg, meta) => console[level](msg, meta),
onNavigate: (route, params) => navigation.navigate(route, params),
};
return (
<DocumentCaptureProvider config={config}>
<YourNavigator />
</DocumentCaptureProvider>
);
}Pre-signin vs post-signin capture
Some apps need to scan documents before the user logs in (e.g. during registration), while others scan them after login (e.g. in account settings). Some apps need both — for example, ID scan during registration but insurance scan after login.
The registrationTypes config field controls which document types use the unauthenticated backend path. Everything else uses the authenticated path automatically.
Authenticated path (default)
When registrationTypes is omitted or does not include a given capture type, the hook calls endpoints that require a valid auth token:
| Capture type | Canned URL | OCR submit |
|---|---|---|
| "identification" | getDrivingLicenseCannedUrl | captureDrivingLicense |
| "healthinsurance" / "insurance" | getInsuranceCannedUrl | captureInsurance |
| "userphoto" | getUserImageCannedUrl | captureUserPhoto |
Unauthenticated registration path
When a capture type is listed in registrationTypes, the hook calls:
| Canned URL | OCR submit |
|---|---|
| getRegistrationDocumentCannedUrl(type, ext) | captureRegistrationDocument(fileId, type) |
No auth token is sent. The settingsClient must still be configured with loginClient.configure(tenantId, environment), but the user does not need to be logged in.
Note:
putIdDetailsandputInsuranceDetailsalways require authentication. They are not available in the registration flow. If you need to persist the scanned document, do it after the user logs in.
Example: all capture after login (default)
No registrationTypes needed. The user is authenticated before reaching the capture screens.
// App.tsx
function App() {
return (
<DocumentCaptureProvider config={{ settingsClient }}>
<AppNavigator />
</DocumentCaptureProvider>
);
}
// Inside AppNavigator — user is already logged in
function IDSettingsScreen() {
const { processCapture, captureDriversLicense, putIdDetails, isProcessing, result } =
useDocumentCapture();
// After the user confirms the OCR data, save it to the EHR
if (result?.ocrData) {
return (
<ConfirmScreen
data={result.ocrData as DriversLicenseData}
onConfirm={() => putIdDetails({ Image: result.fileId })}
/>
);
}
// Native: use Veryfi Lens (returns null on web)
if (Platform.OS !== "web") {
return <Button title="Scan ID" onPress={captureDriversLicense} loading={isProcessing} />;
}
// Web: use OpenCV.js scanner
return (
<JScanifyWebCapture
documentType="id"
onCaptured={(dataUrl) => processCapture(dataUrl, "identification")}
onClose={() => navigation.goBack()}
/>
);
}Example: ID scan before login, insurance after login
Use registrationTypes: ["identification"] so the ID step works without a token.
Insurance is not listed, so it uses the authenticated path automatically.
Both screens can live under the same DocumentCaptureProvider.
// App.tsx
function App() {
return (
<DocumentCaptureProvider
config={{
settingsClient,
registrationTypes: ["identification"], // ID → no-auth, insurance → auth
}}
>
<AppNavigator />
</DocumentCaptureProvider>
);
}
// Registration flow — user is NOT logged in yet
function RegistrationIDScreen() {
const { processCapture, captureDriversLicense, isProcessing, result } = useDocumentCapture();
// Hook automatically uses getRegistrationDocumentCannedUrl + captureRegistrationDocument
// No auth token is required.
// Note: putIdDetails is NOT available here — save after login if needed.
if (Platform.OS !== "web") {
return <Button title="Scan ID" onPress={captureDriversLicense} loading={isProcessing} />;
}
return (
<JScanifyWebCapture
documentType="id"
onCaptured={(dataUrl) => processCapture(dataUrl, "identification")}
onClose={() => navigation.goBack()}
/>
);
}
// Settings flow — user IS logged in
function InsuranceSettingsScreen() {
const { processCapture, captureInsuranceCard, putInsuranceDetails, isProcessing, result } =
useDocumentCapture();
// Hook uses getInsuranceCannedUrl + captureInsurance (authenticated).
// putInsuranceDetails is available here.
if (result?.ocrData) {
const ocr = result.ocrData as InsuranceCardData;
return (
<ConfirmScreen
data={ocr}
onConfirm={(details) => putInsuranceDetails(details)}
/>
);
}
if (Platform.OS !== "web") {
return <Button title="Scan Insurance" onPress={captureInsuranceCard} loading={isProcessing} />;
}
return (
<JScanifyWebCapture
documentType="insurance"
onCaptured={(dataUrl) => processCapture(dataUrl, "healthinsurance")}
onClose={() => navigation.goBack()}
/>
);
}Example: both ID and insurance before login
<DocumentCaptureProvider
config={{
settingsClient,
registrationTypes: ["identification", "healthinsurance"],
}}
>
<RegistrationNavigator />
</DocumentCaptureProvider>Both capture types now use the unauthenticated registration path. The OCR response shape is the same — result.ocrData is still DriversLicenseData or InsuranceCardData.
useDocumentCapture hook
Main hook — handles the full capture → upload → OCR flow. Must be used inside <DocumentCaptureProvider>.
const capture = useDocumentCapture();Return values
| Property | Type | Description |
|---|---|---|
| isProcessing | boolean | Upload + OCR in progress |
| isVeryfiProcessingUi | boolean | Veryfi SDK is processing after shutter (show loading overlay) |
| isVeryfiAvailable | boolean | Veryfi native SDK is linked and ready |
| result | DocumentCaptureResult \| null | Last successful capture result |
| error | Error \| null | Last error |
| captureDriversLicense() | () => Promise<DocumentCaptureResult> | Native Veryfi ID capture (iOS/Android) |
| captureInsuranceCard() | () => Promise<DocumentCaptureResult> | Native Veryfi insurance capture (iOS/Android) |
| captureSelfie(fileUri) | (uri: string) => Promise<DocumentCaptureResult> | Upload + submit a selfie URI |
| processCapture(uri, type) | (uri, type) => Promise<DocumentCaptureResult> | Upload + OCR for any capture type (used after web capture) |
| uploadCapture(uri, type) | (uri, type) => Promise<UploadResult> | Request a presigned URL and upload the image without starting OCR |
| processUploadedCapture(upload, type) | (upload, type) => Promise<DocumentCaptureResult> | Start OCR for a result returned by uploadCapture |
| putInsuranceDetails(details) | (details: InsuranceDetails) => Promise<void> | Save confirmed insurance OCR data to EHR (authenticated only — not available in registration flow) |
| putIdDetails(details) | (details: IdDetails) => Promise<void> | Save confirmed ID OCR data to EHR (authenticated only — not available in registration flow) |
| reset() | () => void | Clear result, error, and processing state |
DocumentCaptureResult
interface DocumentCaptureResult {
fileId: string; // S3 file key / FileName from canned URL response
url: string; // S3 ImageURL where file was uploaded
key: string; // Same as fileId
captureType: DocumentCaptureType;
ocrData?: DriversLicenseData | InsuranceCardData; // Populated after OCR submit
}Usage example
import { useDocumentCapture, JScanifyWebCapture } from "@healthcloudai/hc-document-capture-ui";
import { Platform } from "react-native";
// IdScanScreen must be rendered inside <DocumentCaptureProvider>
function IdScanScreen() {
const { captureDriversLicense, processCapture, putIdDetails, isProcessing, result, error } =
useDocumentCapture();
// --- Native (iOS / Android) ---
const handleNativeCapture = async () => {
try {
const result = await captureDriversLicense();
console.log("OCR data:", result.ocrData);
// result.ocrData is DriversLicenseData
} catch (e) {
console.error(e);
}
};
// --- Web ---
if (Platform.OS === "web") {
return (
<JScanifyWebCapture
documentType="id"
onCaptured={async (dataUrl) => {
const result = await processCapture(dataUrl, "identification");
console.log("OCR data:", result.ocrData);
}}
onClose={() => navigation.goBack()}
/>
);
}
// ... native UI
}useVeryfiLens hook
Lower-level hook for screens that need direct Veryfi Lens control (e.g. when you want to handle the image yourself before OCR).
const veryfi = useVeryfiLens({
credentials: config.veryfiCredentials,
onCaptureSuccess: (result) => console.log(result.imageUri),
onCaptureCancel: () => navigation.goBack(),
onCaptureError: (err) => console.error(err),
});Return values
| Property | Type | Description |
|---|---|---|
| isAvailable | boolean | Veryfi native SDK linked |
| isInitializing | boolean | SDK initializing |
| isCapturing | boolean | Camera open |
| isVeryfiLensProcessingUi | boolean | Post-shutter processing |
| shouldUseFallback | boolean | true on web or when SDK unavailable — show web fallback |
| result | VeryfiLensResult \| null | Raw SDK result |
| error | Error \| null | |
| captureDriversLicense() | () => Promise<VeryfiLensResult> | |
| captureInsuranceCard() | () => Promise<VeryfiLensResult> | |
| captureDocument(type) | (type: VeryfiDocumentType) => Promise<VeryfiLensResult> | |
| reset() | () => void | |
VeryfiLensResult
interface VeryfiLensResult {
success: boolean;
imageUri?: string; // file:// URI (native) or data URL (web)
imagePath?: string; // absolute file path (native)
documentType?: VeryfiDocumentType;
data?: DriversLicenseData | InsuranceCardData; // SDK-extracted OCR (if available)
error?: string;
rawResponse?: unknown;
}Web capture components
Both components are web-only — they return null on iOS/Android.
JScanifyWebCapture
OpenCV.js document scanner. Auto-captures when document is stable and in frame. No external SDK, no licensing.
import { JScanifyWebCapture } from "@healthcloudai/hc-document-capture-ui";
<JScanifyWebCapture
documentType="id" // "id" | "insurance"
theme={config.theme} // optional
logger={config.logger} // optional
opencvScriptUrl="/vendor/opencv.js" // optional; also read from provider config
onCaptured={(dataUrl) => processCapture(dataUrl, "identification")}
onClose={() => navigation.goBack()}
onError={(err) => console.error(err)}
/>How it works: loads opencv.js from CDN → accesses device camera → draws video frames to canvas → runs Canny edge detection and contour analysis → when a stable 4-corner document quad is detected, performs perspective warp and CLAHE enhancement → calls onCaptured with a JPEG data URL.
VeryfiLensWebCapture
Veryfi Lens WASM web capture. Requires veryfi-lens-wasm installed.
import { VeryfiLensWebCapture } from "@healthcloudai/hc-document-capture-ui";
<VeryfiLensWebCapture
documentType="insurance" // "id" | "insurance"
clientId={config.veryfiCredentials.clientId}
theme={config.theme} // optional
onCaptured={(dataUrl) => processCapture(dataUrl, "healthinsurance")}
onClose={() => navigation.goBack()}
onError={(err) => console.error(err)}
/>Native fallback camera
CardCameraCapture provides an expo-camera fallback when the Veryfi native
SDK is unavailable or when the consuming app wants to own the capture screen.
It renders an ID/insurance card guide, supports timed auto-capture and a manual
shutter, and crops the returned photo to the visible guide frame when
expo-image-manipulator is installed.
import { CardCameraCapture } from "@healthcloudai/hc-document-capture-ui";
<CardCameraCapture
documentType="id"
topInset={safeAreaInsets.top}
bottomInset={safeAreaInsets.bottom}
onCaptured={(fileUri) => processCapture(fileUri, "identification")}
onClose={() => navigation.goBack()}
onError={(error) => console.error(error)}
/>expo-camera and expo-image-manipulator are optional peers. If
expo-camera is not installed, the component renders an unavailable state and
calls onError. If expo-image-manipulator is missing, the original uncropped
photo URI is returned.
Capture UI building blocks
CardScanGuiderenders a reusable ID/insurance card guide.CaptureOcrNoticeModalrenders a themed web notice for capture/OCR failures.WebFileUploadDialogprovides web selfie capture and single/multiple image selection. It readsassetBasePathfrom its prop or the provider config.VeryfiHelpViewprovides a themed help screen for the native Veryfi camera.getCaptureErrorMessagenormalizes empty and generic capture errors.cropToScanFrameexposes the fallback camera crop helper for custom capture screens.
Full flow with all platforms
// DocumentCaptureScreen must be rendered inside <DocumentCaptureProvider>
function DocumentCaptureScreen({ documentType }: { documentType: "id" | "insurance" }) {
const {
captureDriversLicense,
captureInsuranceCard,
processCapture,
putIdDetails,
putInsuranceDetails,
isVeryfiAvailable,
isProcessing,
result,
} = useDocumentCapture();
const captureType = documentType === "id" ? "identification" : "healthinsurance";
// Web — show OpenCV scanner
if (Platform.OS === "web") {
return (
<JScanifyWebCapture
documentType={documentType}
onCaptured={(dataUrl) => processCapture(dataUrl, captureType)}
onClose={() => navigation.goBack()}
/>
);
}
// Native — use Veryfi Lens
const handleCapture = () => {
if (documentType === "id") return captureDriversLicense();
return captureInsuranceCard();
};
// After OCR result, let user confirm then save
if (result?.ocrData) {
return (
<ConfirmScreen
ocrData={result.ocrData}
onConfirm={async (details) => {
if (documentType === "id") await putIdDetails({ Image: result.fileId });
else await putInsuranceDetails(details as InsuranceDetails);
}}
/>
);
}
return <CaptureButton onPress={handleCapture} loading={isProcessing} />;
}API response examples
Canned URL response (from settingsClient.getDrivingLicenseCannedUrl)
{
"Data": {
"ImageURL": "https://hc-dev-storage-cv-sources.s3.us-east-1.amazonaws.com/1234567890123.jpg?X-Amz-Signature=...",
"FileName": "1234567890123.jpg",
"Extension": null
},
"IsOK": true,
"ErrorMessage": null
}ID capture OCR response (from settingsClient.captureDrivingLicense)
{
"Data": {
"IsCaptured": true,
"InsurancePackages": null,
"CapturedData": {
"FirstName": "John",
"LastName": "Doe",
"StreetAddress": "123 Main St",
"City": "Austin",
"ZipCode": "78701",
"State": "TX",
"IssuedDate": "2019-03-15",
"ExpiresDate": "2027-03-15",
"Dob": "1990-06-01",
"IDNumber": "12345678"
}
},
"IsOK": true,
"ErrorMessage": null
}Mapped to DriversLicenseData:
{
firstName: "John",
lastName: "Doe",
address: "123 Main St",
city: "Austin",
zipCode: "78701",
state: "TX",
issueDate: "2019-03-15",
expirationDate: "2027-03-15",
dateOfBirth: "1990-06-01",
licenseNumber: "12345678",
rawData: { /* original backend fields */ }
}Insurance capture OCR response (from settingsClient.captureInsurance)
{
"Data": {
"IsCaptured": true,
"InsurancePackages": [
{ "Id": 42, "Name": "BlueCross PPO Gold" }
],
"CapturedData": {
"FirstName": "Jane",
"LastName": "Doe",
"MemberId": "XYZ987654",
"GroupNumber": "GRP001",
"EffectiveDate": "2024-01-01",
"RxBIN": "004336",
"RxPCN": "ADV",
"RxGRP": "RXGRP01",
"Carrier": "BlueCross BlueShield"
}
},
"IsOK": true,
"ErrorMessage": null
}Mapped to InsuranceCardData:
{
memberName: "Jane Doe",
memberId: "XYZ987654",
groupNumber: "GRP001",
effectiveDate: "2024-01-01",
rxBin: "004336",
rxPcn: "ADV",
rxGrp: "RXGRP01",
insurerName: "BlueCross BlueShield",
rawData: { /* original backend fields */ }
}Save insurance details payload (putInsuranceDetails)
await putInsuranceDetails({
InsurancePackageId: "42", // from InsurancePackages[0].Id
MemberId: "XYZ987654",
FirstName: "Jane",
LastName: "Doe",
Sex: "F",
Image: result.fileId, // fileName from upload (e.g. "1234567890123.jpg")
});Save ID details payload (putIdDetails)
await putIdDetails({
Image: result.fileId, // fileName from upload
});HEIC utilities
Helper functions for detecting and normalizing HEIC/HEIF images (common on iOS).
import {
isHeicMimeType,
isHeicFileName,
isHeicUri,
isHeicAsset,
getExtensionForMimeType,
getMimeTypeForExtension,
toJpegFileName,
convertHeicBlobToJpeg,
normalizeWebUploadBlob,
normalizeWebImageFile,
normalizeWebImageAsset,
} from "@healthcloudai/hc-document-capture-ui";
isHeicMimeType("image/heic") // true
isHeicFileName("photo.HEIF") // true
isHeicUri("file:///tmp/scan.heic") // true
getExtensionForMimeType("image/png") // "png"
getMimeTypeForExtension("jpg") // "image/jpeg"
toJpegFileName("scan.heic") // "scan.jpg"The normalizeWeb* helpers are web-only. They load the optional heic2any
peer lazily when a HEIC/HEIF file needs conversion, so native bundles do not
load that dependency.
Advanced: direct upload service
For custom upload flows outside of useDocumentCapture:
import { uploadFile, writeDataUrlToFile } from "@healthcloudai/hc-document-capture-ui";
// Write a web data URL to a native file (no-op on web — returns data URL as-is)
const { fileUri, contentType } = await writeDataUrlToFile(dataUrl, "capture.jpg");
// Upload to canned URL — works on both web and native
const result = await uploadFile(
fileUri,
(extension) =>
settingsClient.getDrivingLicenseCannedUrl(extension).then((r) => ({
ImageURL: r.Data?.ImageURL ?? null,
FileName: r.Data?.FileName ?? null,
})),
);
// result: { fileId: "1234567890123.jpg", url: "https://...", key: "1234567890123.jpg" }Expo config plugin
The plugin configures native projects for Veryfi Lens. Add it to app.config.js:
export default {
plugins: [
["@healthcloudai/hc-document-capture-ui/plugin"]
]
};Then run:
npx expo prebuildAndroid: Adds the Veryfi Maven repository to android/build.gradle.
iOS: Removes any legacy manual VeryfiLens pod entries (autolinking handles it from RN 0.72+).
Platform behavior summary
| Feature | iOS | Android | Web |
|---|---|---|---|
| Document capture | Veryfi Lens SDK or CardCameraCapture fallback | Veryfi Lens SDK or CardCameraCapture fallback | JScanifyWebCapture (OpenCV.js) or VeryfiLensWebCapture (WASM) |
| Upload | expo-file-system uploadAsync → PUT canned URL | Same | Canvas compress → fetch PUT canned URL |
| Image compression | None (Veryfi handles it) | None | Auto-compressed to ≤1MB JPEG via Canvas API |
| HEIC normalization | Detected by MIME/extension | Same | Converted to JPEG with optional heic2any |
| isVeryfiAvailable | true if pod linked | true if VeryfiLensAndroid native module present | Always false |
Types reference
type DocumentCaptureType = "userphoto" | "healthinsurance" | "identification" | "insurance";
interface DocumentCaptureConfig {
settingsClient: HCSettingsClient;
/**
* Document types that use the unauthenticated registration path.
* Types not listed here use the authenticated path.
* Omit entirely to use the authenticated path for all types.
*/
registrationTypes?: DocumentCaptureType[];
veryfiCredentials?: VeryfiLensCredentials;
theme?: Partial<DocumentCaptureTheme>;
onNavigate?: (route: string, params?: Record<string, unknown>) => void;
assetBasePath?: string;
opencvScriptUrl?: string;
logger?: (level: "debug" | "info" | "warn" | "error", message: string, metadata?: Record<string, unknown>) => void;
}interface InsuranceDetails { InsurancePackageId: string; MemberId: string; FirstName: string; LastName: string; Sex: string; Image: string; // fileName from upload result }
interface IdDetails { Image: string; // fileName from upload result }
interface DriversLicenseData { firstName?: string; lastName?: string; dateOfBirth?: string; expirationDate?: string; issueDate?: string; licenseNumber?: string; state?: string; address?: string; city?: string; zipCode?: string; gender?: string; rawData?: Record<string, unknown>; // ... full list in types.ts }
interface InsuranceCardData { memberName?: string; memberId?: string; groupNumber?: string; effectiveDate?: string; rxBin?: string; rxPcn?: string; rxGrp?: string; insurerName?: string; rawData?: Record<string, unknown>; // ... full list in types.ts }
