@onefootprint/footprint-expo-camera-module
v0.1.0
Published
Native document capture for Expo apps using the Footprint platform
Readme
@onefootprint/footprint-expo-camera-module
Expo SDK bridge that exposes the native document capture screen from @onefootprint/footprint-native-camera-module to React Native code. Pairs with @onefootprint/footprint-expo (the SDK that handles the rest of the onboarding flow + the upload).
What this package does
- Provides a single async function:
captureDocument({ documentSide, appearance, l10n, ... }). - Presents the native capture screen modally on iOS (SwiftUI via
UIHostingController) and as an Activity on Android (Compose viaActivityResultContract). - Returns the captured image as a base64 JPEG. The SDK calls
footprintQueries.uploadDoc(...)afterwards.
What this package does NOT do
- It does not own the UI — that lives in
footprint-native-camera-module. This package is a ~150-line bridge that translates JS calls to native calls. - It does not handle uploads. The SDK takes the returned image and uploads via the existing
footprintQueriesclient. - It does not duplicate detection or camera primitives. Both come from the native camera module.
Usage
import { captureDocument } from '@onefootprint/footprint-expo-camera-module';
const result = await captureDocument({
documentSide: 'front',
appearance: {
theme: 'light',
variables: {
colorAccent: '#0052FF',
buttonPrimaryBg: '#0052FF',
buttonBorderRadius: '12px',
},
},
l10n: { language: 'en' },
});
// result: { imageBase64, documentSide, capturedManually, fromGallery }
// then: await footprintQueries.uploadDoc({ ... })Appearance and L10n mirror the shapes used by the rest of the Footprint SDKs (footprint-js, footprint-swift, footprint_flutter) — integrators can pass the same object they pass elsewhere.
Config plugin
Adds the iOS camera + photo-library usage descriptions to Info.plist, and the camera + photo permissions to AndroidManifest.xml. Wire it in app.json:
{
"expo": {
"plugins": [
[
"@onefootprint/footprint-expo-camera-module",
{
"cameraPermission": "Take a photo of your ID",
"photoLibraryPermission": "Pick an ID photo from your library"
}
]
]
}
}Dev workflow
Both this bridge and the native camera module are linked via yalc during local dev. To make a code change:
# 1. If you changed Kotlin / Swift in the native camera module:
cd ../footprint-native-camera-module
pnpm build:native # rebuilds xcframework + AAR
yalc publish
# 2. Build this bridge:
cd ../footprint-expo-camera-module
yalc update # pulls the camera module update (if step 1 ran)
pnpm build # compiles TS + the config plugin
yalc publish
# 3. In the consuming app (e.g. demo-expo):
yalc update # pulls both bridges
pnpm install
npx expo prebuild --clean # regenerates native projects + autolinks
npx expo run:ios # (or run:android)Or run pnpm dev:local from this directory to watch + auto-yalc-publish on every change.
Package layout
src/ # TypeScript: captureDocument + types
ios/
├── FootprintExpoCameraModule.podspec # depends on FootprintNativeCameraSwift (from the native module)
├── FootprintExpoCameraModule.swift # Expo Module — presents the SwiftUI screen
└── CaptureDocumentOptionsRecord.swift # Records for JS interop
android/
├── build.gradle # depends on the native camera module's android/ subproject
└── src/main/java/.../
├── FootprintExpoCameraModule.kt # Expo Module — launches the Activity via the contract
└── CaptureDocumentOptionsRecord.kt
plugin/src/ # Expo config plugin (permissions injection)Nothing UI-shaped lives here. The screen, overlays, capture pipeline, and translations all live in footprint-native-camera-module.
Publishing to npm
Published as @onefootprint/footprint-expo-camera-module via the mobile_npm_publish GitHub
workflow (npm OIDC trusted publishing). prepack runs pnpm build, so build/ + plugin/build/
are freshly compiled into the tarball. Publish this bridge after the native camera module, and
keep its @onefootprint/footprint-native-camera-module peer range in sync with that module's version.
