@giouwur/biometric-sdk
v1.1.9
Published
SDK for Intelli Biometric components and logic
Readme
@giouwur/biometric-sdk
React SDK for capturing, previewing, and packaging biometric data (fingerprint, palm, face, and iris) for enrollment and verification against an ABIS-style backend. It is the client-side integration layer used by Intelli Biometrics applications (e.g. hospital/clinic administration systems) to talk to a local biometric device bridge and to assemble ABIS-compliant enrollment payloads.
Private package. This repository and the package it produces are proprietary and intended for internal/client use only — do not redistribute.
Contents
- Overview
- Features
- Requirements
- Installation
- Getting Started
- Enrollment Modules
- CLI: Test/Docs Page Generator
- Building Custom Capture Flows
- State Management
- Backend API Client (optional)
- Image Utilities
- Device Bridge WebSocket Protocol
- Full Export Reference
- Styling
- Project Structure
Overview
The SDK does not talk to fingerprint/palm/face/iris hardware directly from the browser. Instead it connects, over WebSocket, to a local "device bridge" process (typically running alongside the workstation's scanner drivers) that streams capture frames, quality feedback, and finished biometric templates back to the page. The SDK turns those messages into ready-to-submit ABIS enrollment/update requests (enrollAction: "Masterize", fingerprintModality, faceModality, irisModality, etc.), which the host application then forwards to its own backend (e.g. intell-biometric-system).
Everything is exported — components, hooks, Zustand stores, types, and low-level protocol primitives — so a consuming app can either drop in the pre-built enrollment modules or build a fully custom capture UI on top of the same state.
Features
- Multi-modal capture UI: pre-built modules for flat fingerprints, rolled fingerprints, palms, face, and iris.
- Standard fingerprint capture groupings: single finger (1-1), two-finger pairs (2-2), and four-finger slaps + thumbs (4-4-2), matching common livescan capture workflows.
- In-browser face liveness/quality checks using
@vladmandic/face-api(centering, distance, head-pose) before a frame is sent to the backend for validation. - WebSocket device bridge client with auto-reconnect, per-session id, and a pub/sub handler registry (
registerHandler/sendMessage) for the device protocol. - "Missing biometric" tracking (e.g. amputations or uncapturable modalities) with reasons, synced to the device bridge and reflected in the ABIS payload.
- ABIS-oriented request builders:
buildEnrollmentRequest()andbuildUpdateRequest()(the latter only includes modalities that actually changed, via dirty-tracking against the last loaded applicant snapshot). - Zustand-based state: zero-config stores for device/protocol state (
useBiometricStore), enrollment data (useEnrollmentStore), UI/event log (useUiStore), and optional auth (useAuthStore). - Optional REST client: a preconfigured Axios instance plus thin service wrappers for login, enrollment, update, lookup, verification, and identification calls.
- Fully typed: all component props, store shapes, and ABIS request/response types are exported.
- Customizable UI: every module and primitive accepts
className; colors are themed via CSS variables. initCLI: scaffolds a self-contained test/reference page into a Next.js App Router project.
Requirements
- React
>= 18andreact-dom >= 18(peer dependencies) - Tailwind CSS
>= 3(peer dependency) — the components are styled with Tailwind utility classes and CSS variables - A running device bridge service reachable over WebSocket (default
ws://127.0.0.1:5000/biometric) that implements the message protocol described below - If you use
FaceEnrollModule/FaceCameraModal: the@vladmandic/face-apitiny face detector + landmark model weights served from/modelsin your app's public directory - If you use the built-in API client (
api,BiometricService,AuthService,useAuthStore):axiosandjs-cookieinstalled in the host app (declared asoptionalDependencies, not bundled)
Installation
This is a private package — install it from your organization's private registry (or as a local/git dependency), then add the peer dependencies:
npm install @giouwur/biometric-sdk
npm install react react-dom tailwindcssIf you plan to use the optional REST client:
npm install axios js-cookieGetting Started
1. Wrap your app with BiometricProvider
BiometricProvider opens the WebSocket connection to the device bridge on mount and makes the config available to any descendant via useBiometricConfig().
import { BiometricProvider } from "@giouwur/biometric-sdk";
export default function Layout({ children }) {
return (
<BiometricProvider
config={{
wsUrl: "ws://127.0.0.1:5000/biometric", // device bridge WebSocket URL
apiBaseUrl: "https://your-api.example.com/v1", // optional, read back via useBiometricConfig()
deviceId: "scanner_front_01", // optional identifier, persisted to localStorage
}}
>
{children}
</BiometricProvider>
);
}Note: apiBaseUrl is not wired into the SDK's internal API client automatically — it's just exposed through useBiometricConfig() so your own fetch/axios calls can read it. If you use the SDK's own client instead, call setApiBaseUrl() explicitly (see Backend API Client).
2. Drop in an enrollment module
import { FingerEnrollModule, FaceEnrollModule } from "@giouwur/biometric-sdk";
function EnrollmentPage() {
return (
<div className="space-y-8">
<FingerEnrollModule className="custom-card-style" />
<FaceEnrollModule />
</div>
);
}Enrollment Modules
Pre-built, drop-in components exported from the package root. Each accepts a className and manages its own capture modal, quality feedback, and "mark as missing" flow, writing captured data into useEnrollmentStore:
| Module | Modality | Notes |
|---|---|---|
| FingerEnrollModule | Flat fingerprints | Supports 1-1, 2-2, and 4-4-2 (slap + thumbs) capture groupings |
| FingerRollEnrollModule | Rolled fingerprints | Separate storage from flat captures (rolledFingerprints) |
| PalmEnrollModule | Palms (upper/lower/writer's, left & right) | |
| FaceEnrollModule | Face (5 angles) | Uses FaceCameraModal for in-browser liveness/quality gating before submission |
| IrisEnrollModule | Iris (left/right) | |
Each module's paired capture modal (FingerCaptureModal, FingerRollCaptureModal, PalmCaptureModal, FaceCameraModal, IrisCameraModal) is also exported individually so you can reuse the capture UI inside a custom flow.
CLI: Test/Docs Page Generator
npx biometric-sdk initDetects a Next.js App Router project (app/ or src/app/) and writes a self-contained reference page to app/sdk-test/page.tsx (or src/app/sdk-test/page.tsx) exercising the SDK's modules, useful as living documentation and a smoke test against your device bridge. Serve it at /sdk-test.
Building Custom Capture Flows
Instead of the pre-built modules, you can talk to the device bridge directly through useBiometricStore and store results yourself:
import { useBiometricStore } from "@giouwur/biometric-sdk";
function MyCapture() {
const { sendMessage, registerHandler, isConnected } = useBiometricStore();
const handleCapture = () => {
registerHandler("FINGER_CAPTURE_COMPLETE", (msg) => {
console.log("Captured image (base64):", msg.image);
});
sendMessage({
messageType: "START_FINGER_CAPTURE",
biometricData: { mode: "MODE_1_1", targetFinger: "RIGHT_INDEX" },
});
};
return (
<button onClick={handleCapture} disabled={!isConnected}>
Start Scan
</button>
);
}State Management
The SDK uses Zustand; every store is a plain hook you can read from or act on anywhere in the tree (or outside of React via useXStore.getState()).
| Store | Purpose |
|---|---|
| useBiometricStore | WebSocket connection lifecycle (connect, disconnect, init, auto-reconnect), sendMessage/registerHandler/unregisterHandler protocol primitives, device status, and "missing finger" tracking synced to the bridge |
| useEnrollmentStore | Accumulated capture data per modality (fingerprints, rolled fingerprints, palms, faces, irises) plus missing-modality reasons; fetchApplicantData() to hydrate from an existing applicant record; buildEnrollmentRequest() / buildUpdateRequest() to produce ABIS-shaped payloads; getDirtyModalities() for change tracking |
| useUiStore | A capped, timestamped event log (messages) and console open/close toggle, used for on-screen diagnostics |
| useAuthStore | Optional token/user session store backed by a js-cookie cookie + localStorage |
import { useEnrollmentStore } from "@giouwur/biometric-sdk";
function Status() {
const { fingerprints, faces } = useEnrollmentStore();
return (
<div>
{Object.keys(fingerprints).length} fingerprints, {faces.length} faces captured.
</div>
);
}Assembling the ABIS payload
const store = useEnrollmentStore.getState();
// New applicant
const payload = store.buildEnrollmentRequest();
await fetch("/api/enroll", { method: "POST", body: JSON.stringify(payload) });
// Existing applicant — only changed modalities are included
const patch = store.buildUpdateRequest();
await fetch(`/api/enroll/${store.externalId}`, { method: "PUT", body: JSON.stringify(patch) });Backend API Client (optional)
An Axios-based client and two thin service wrappers are exported for apps that want to use them directly instead of rolling their own fetch calls. They require axios and js-cookie to be installed in the host app.
import { api, setApiBaseUrl, BiometricService, AuthService } from "@giouwur/biometric-sdk";
setApiBaseUrl("https://your-api.example.com/v1"); // defaults to http://localhost:8080/api/v1
await AuthService.login({ username, password });
await BiometricService.enrollApplicant(payload);
await BiometricService.updateApplicant(externalId, patch);
await BiometricService.getApplicant(externalId);
await BiometricService.verifyIdentity(externalId, biometricData);
await BiometricService.identifyProbe(biometricData);api automatically attaches the token from useAuthStore as an x-access-token header on every request. These map to the backend routes /auth/login, /biometric/enrollment, /biometric/update/:externalId, /biometric/:externalId, /biometric/:externalId/verify, and /biometric/identify.
Image Utilities
Helpers for the base64/data-URL juggling that biometric capture payloads require:
import {
normalizeImageForStorage, // strips the data:image/...;base64, prefix for storage/API payloads
getImageSrcForDisplay, // adds the data:image/...;base64, prefix back for <img src>
isRemoteImage, // true if the string is an http(s) URL rather than base64
downloadImageAsBase64, // fetches a remote image URL and returns raw base64
canvasToBase64, // extracts base64 from a <canvas>
base64toBlob, // for building FormData uploads
detectImageFormat, // sniffs png/jpeg/gif/bmp/webp/jp2 from base64 magic bytes
isValidBase64,
} from "@giouwur/biometric-sdk";Device Bridge WebSocket Protocol
BiometricProvider opens a connection to wsUrl (appending a persisted sid session id) and useBiometricStore dispatches inbound messages by messageType to handlers registered with registerHandler. Messages ending in _FRAME are treated as live preview frames and don't update lastMessage. DEVICE_STATUS_UPDATE is handled centrally and exposed as deviceStatus.
Representative outbound message types used by the built-in modules:
| Modality | Start | Abort | Finalize |
|---|---|---|---|
| Fingerprint (flat) | START_FINGER_CAPTURE | ABORT_FINGER_CAPTURE | FINALIZE_ENROLLMENT |
| Fingerprint (rolled) | START_FINGER_ROLL_CAPTURE | ABORT_FINGER_ROLL_CAPTURE | FINALIZE_ENROLLMENT |
| Palm | START_PALM_CAPTURE | ABORT_PALM_CAPTURE | FINALIZE_PALM_ENROLLMENT |
| Iris | START_IRIS_CAPTURE (+ START_IRIS_PREVIEW) | ABORT_IRIS_CAPTURE | — |
| Face | — (validated in-browser, then VALIDATE_FACE_IMAGE) | — | FINALIZE_FACE_ENROLLMENT |
And representative inbound message types the modules listen for:
| Modality | Preview/status | Completion | Errors |
|---|---|---|---|
| Fingerprint (flat) | FINGER_PREVIEW_FRAME | FINGER_CAPTURE_COMPLETE, ENROLLMENT_COMPLETE | FINGER_QUALITY_LOW, DUPLICATE_FINGER, FINGER_ERROR |
| Fingerprint (rolled) | FINGER_PREVIEW_FRAME, FINGER_ROLL_START_SIGNAL | FINGER_ROLL_COMPLETE_SIGNAL, FINGER_CAPTURE_COMPLETE, ENROLLMENT_COMPLETE | same as flat |
| Palm | PALM_PREVIEW_FRAME, PALM_CAPTURE_STATUS | PALM_CAPTURE_COMPLETE, PALM_TEMPLATE_GENERATED | PALM_ERROR |
| Iris | IRIS_PREVIEW_FRAME, IRIS_STATUS_UPDATE | IRIS_ENROLLMENT_COMPLETE | IRIS_ERROR |
| Face | FACE_VALIDATION_RESULT (response to VALIDATE_FACE_IMAGE, carries isValid/message/qualityScore) | FACE_ENROLLMENT_COMPLETE | ERROR |
Shared across modalities: ERROR, ERROR_DEVICE_BUSY, ERROR_DEVICE_NOT_FOUND, ERROR_CAPTURE_FAILED, UPDATE_MISSING_BIOMETRICS (syncs the missing-finger/palm exception list to the bridge), and DEVICE_STATUS_UPDATE (handled centrally by the store and exposed as deviceStatus).
Full Export Reference
Everything below is exported from the package root (src/index.ts):
- Provider:
BiometricProvider,useBiometricConfig,BiometricConfig(type) - Enrollment modules:
FingerEnrollModule,FaceEnrollModule,PalmEnrollModule,IrisEnrollModule,FingerRollEnrollModule - Capture modals:
FingerCaptureModal,FingerRollCaptureModal,FaceCameraModal,PalmCaptureModal,IrisCameraModal,ModuleHeader - UI primitives:
Button,Card,Input,Select,StatusChip,QualityBadge,ProgressBar,Modal,Loader,Tabs/TabsList/TabsTrigger/TabsContent,BiometricSlot,MissingBiometricModal/MissingFingerModal,TableWrapper/TableHeader/TableRow - Component prop types:
ButtonProps,CardProps,InputProps,ModalProps,BiometricSlotProps - Stores:
useBiometricStore,useEnrollmentStore,useUiStore,useAuthStore - Store types:
BiometricItem,EnrollmentState,OriginalSnapshot,BiometricState,DeviceStatus,SocketMessage,MessageHandler,UiState - Image utilities:
normalizeImageForStorage,getImageSrcForDisplay,isRemoteImage,downloadImageAsBase64,canvasToBase64,base64toBlob,detectImageFormat,isValidBase64 - Constants:
FINGER_NAMES,RIGHT_FINGERS,LEFT_FINGERS - ABIS types:
FingerprintPosition,FingerprintImpressionType,IrisPosition,BiometricImage,FingerprintItem,MissingFingerprintItem,FaceItem,MissingFaceItem,IrisItem,MissingIrisItem,EnrollAction,CustomDetails,EnrollApplicantRequest - Optional API/services:
api(default),setApiBaseUrl,BiometricService,AuthService
Styling
All modules and UI primitives accept className:
<FingerEnrollModule className="!bg-slate-900 border-2 border-primary/20 rounded-2xl p-8" />Brand colors are read from CSS variables (HSL channel values, consumed by Tailwind):
:root {
--primary: 219 255 0;
--primary-foreground: 0 0 0;
--success: 34 197 94;
}Project Structure
src/
components/
BiometricProvider.tsx # WebSocket bootstrap + config context
enrollment/ # Pre-built modules + their capture modals
ui/ # Shared UI primitives
lib/
api.ts # Axios instance + auth header injection
services/biometricService.ts # AuthService, BiometricService (REST wrappers)
stores/ # biometricStore, enrollmentStore, uiStore, authStore
utils/imageHelpers.ts
constants/fingerPositions.ts
types/abis-types.ts # ABIS request/response types
bin/init.js # `biometric-sdk init` CLI
templates/test-page.tsx # Template copied by the CLI