npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@finclusionaibuild/liveness-sdk

v1.0.7

Published

AWS Face Liveness SDK for React applications.

Readme

@finclusionaibuild/liveness-sdk

A comprehensive Face Liveness Detection SDK for React applications. This SDK provides biometric face verification capabilities with a mobile-responsive UI.

Features

  • Face Liveness Detection - Real-time face verification.
  • Mobile Responsive - Optimized for mobile, tablet, and desktop devices
  • Multiple Components - LivenessDetector, ExternalLiveness, PaymentLiveness
  • TypeScript Support - Full TypeScript definitions included
  • Error Handling - Comprehensive error handling and retry mechanisms
  • Customizable - Custom logos, instruction text, and styling
  • React Native Ready - Works with React Native via WebView

Installation

npm install @finclusionaibuild/liveness-sdk

Peer Dependencies

The SDK requires these peer dependencies to be installed in your project:

npm install react@^18.0.0 react-dom@^18.0.0 @tanstack/react-query@^5.39.0

Prerequisites

  1. React Query Setup: You must wrap your application (or the component using the SDK) with QueryClientProvider:
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      {/* Your app */}
    </QueryClientProvider>
  );
}
  1. CSS Import: You must import the SDK's stylesheet:
import "@finclusionaibuild/liveness-sdk/styles.css";

Quick Start (Web)

Basic Example

import React from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { LivenessDetector } from "@finclusionaibuild/liveness-sdk";
import "@finclusionaibuild/liveness-sdk/styles.css";

const queryClient = new QueryClient();

function App() {
  const config = {
    apiBaseUrl: "https://api.example.com",
    getAuthToken: () => localStorage.getItem("authToken"),
    endpoints: {
      createSession: "/api/liveliness",
      verify: "/api/liveliness/{sessionId}",
    },
  };

  const handleComplete = () => {
    console.log("Liveness check completed!");
    // Navigate to next step
  };

  return (
    <QueryClientProvider client={queryClient}>
      <LivenessDetector
        config={config}
        token={localStorage.getItem("authToken")}
        gotoNext={handleComplete}
      />
    </QueryClientProvider>
  );
}

Advanced Example with Customization

import React, { useState } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
  LivenessDetector,
  type LivenessConfig,
} from "@finclusionaibuild/liveness-sdk";
import "@finclusionaibuild/liveness-sdk/styles.css";

const queryClient = new QueryClient();

function AdvancedLivenessExample() {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const config: LivenessConfig = {
    apiBaseUrl: process.env.REACT_APP_API_BASE_URL || "https://api.example.com",
    getAuthToken: () => {
      // Get token from your auth system
      return localStorage.getItem("authToken");
    },
    endpoints: {
      createSession: "/api/v1/liveliness/create",
      verify: "/api/v1/liveliness/{sessionId}/verify",
    },
  };

  const handleComplete = async () => {
    setIsLoading(true);
    try {
      // Handle successful liveness check
      console.log("Liveness verification successful!");
      // Proceed to next step in your flow
      window.location.href = "/next-step";
    } catch (err) {
      setError("Failed to process liveness result");
      console.error(err);
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <QueryClientProvider client={queryClient}>
      <div className="container mx-auto p-4">
        {error && (
          <div className="mb-4 p-4 bg-red-100 border border-red-400 text-red-700 rounded">
            {error}
          </div>
        )}

        <LivenessDetector
          config={config}
          token={localStorage.getItem("authToken")}
          gotoNext={handleComplete}
          logoUrl="/custom-logo.svg" // Optional: Custom logo
          instructionText="Please position your face in the center of the frame and follow the instructions."
        />
      </div>
    </QueryClientProvider>
  );
}

Error Handling Example

import React, { useState } from "react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { LivenessDetector, type LivenessError } from "@finclusionaibuild/liveness-sdk";
import "@finclusionaibuild/liveness-sdk/styles.css";

const queryClient = new QueryClient();

function ErrorHandlingExample() {
  const [error, setError] = useState<LivenessError | null>(null);
  const [retryCount, setRetryCount] = useState(0);

  const config = {
    apiBaseUrl: "https://api.example.com",
    getAuthToken: () => localStorage.getItem("authToken"),
    endpoints: {
      createSession: "/api/liveliness",
      verify: "/api/liveliness/{sessionId}",
    },
  };

  const handleComplete = () => {
    console.log("Success!");
    setError(null);
    setRetryCount(0);
  };

  const handleError = (err: LivenessError) => {
    setError(err);
    console.error("Liveness error:", err);

    // Handle specific error types
    if (err.response?.status === 403) {
      // Handle unauthorized
      alert("Session expired. Please login again.");
    } else if (err.response?.status === 400) {
      // Handle bad request
      if (retryCount < 3) {
        setRetryCount((prev) => prev + 1);
        // Component will retry automatically
      } else {
        alert("Maximum retry attempts reached. Please contact support.");
      }
    }
  };

  return (
    <QueryClientProvider client={queryClient}>
      <div>
        {error && (
          <div className="mb-4 p-4 bg-yellow-100 border border-yellow-400 rounded">
            <p className="font-semibold">Error occurred:</p>
            <p>{error.message || "Unknown error"}</p>
            <p className="text-sm mt-2">Retry count: {retryCount}/3</p>
          </div>
        )}

        <LivenessDetector
          config={config}
          token={localStorage.getItem("authToken")}
          gotoNext={handleComplete}
        />
      </div>
    </QueryClientProvider>
  );
}

Component API

LivenessDetector

Main liveness detection component with full verification flow.

Props:

interface LivenessDetectorProps {
  config: LivenessConfig; // Required: Configuration object
  token?: string | null; // Optional: Authentication token
  gotoNext: () => void; // Required: Callback on success
  logoUrl?: string; // Optional: Custom logo URL (defaults to iDCERTIFY logo)
  instructionText?: string; // Optional: Custom instruction text
}

Example:

<LivenessDetector
  config={config}
  token={authToken}
  gotoNext={() => console.log("Complete!")}
  logoUrl="/my-logo.svg"
  instructionText="Custom instructions here"
/>

ExternalLiveness

Standalone liveness component for external pages or separate flows.

Props:

interface ExternalLivenessProps {
  config: LivenessConfig;
  token?: string | null;
  gotoNext: () => void;
  region?: string; // Optional:
  logoUrl?: string;
  instructionText?: string;
}

Example:

<ExternalLiveness
  config={config}
  token={authToken}
  gotoNext={handleComplete}
  region="us-west-2"
/>

PaymentLiveness

Payment verification variant that compares face with user profile.

Props:

interface PaymentLivenessProps {
  config: LivenessConfig;
  token?: string | null;
  gotoNext: () => void;
  handleClose?: () => void; // Optional: Close handler
  logoUrl?: string;
  instructionText?: string;
  onSendOtp?: () => Promise<void>; // Optional: OTP sending callback
}

Example:

<PaymentLiveness
  config={config}
  token={authToken}
  gotoNext={handleComplete}
  handleClose={() => setShowModal(false)}
  onSendOtp={async () => {
    await sendOtpToUser();
  }}
/>

Configuration

LivenessConfig

interface LivenessConfig {
  apiBaseUrl: string; // Base URL for your API
  getAuthToken: () => string | null; // Function to get auth token
  includeLivenessGuide?: boolean; // Optional: Show guide modal
  endpoints?: {
    createSession?: string; // Optional: Custom endpoint (default: '/api/liveliness')
    verify?: string; // Optional: Custom verify endpoint
    compareWithUser?: string; // Optional: Custom compare endpoint (PaymentLiveness)
  };
}

Example:

const config: LivenessConfig = {
  apiBaseUrl: "https://api.example.com",
  getAuthToken: () => {
    // Your token retrieval logic
    return localStorage.getItem("token");
  },
  includeLivenessGuide: true, // Show pre-liveness guide modal
  endpoints: {
    createSession: "/custom/liveliness/create",
    verify: "/custom/liveliness/{sessionId}/verify",
  },
};

React Native Usage (WebView)

To use this SDK in React Native applications, you'll need to embed it in a WebView component. The SDK provides a UMD build specifically for WebView compatibility. Here's a complete example:

Installation

npm install react-native-webview
# For iOS, you may also need:
cd ios && pod install

Complete React Native Example

import React, { useRef, useState } from "react";
import { View, StyleSheet, Alert, Platform } from "react-native";
import { WebView } from "react-native-webview";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

// HTML template with SDK embedded
const getHTML = (token: string, apiBaseUrl: string) => `
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <title>Liveness Check</title>
  <style>
    body {
      margin: 0;
      padding: 0;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
      overflow: hidden;
    }
    #root {
      width: 100vw;
      height: 100vh;
    }
  </style>
</head>
<body>
  <div id="root"></div>
  
  <!-- React and ReactDOM -->
  <script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
  
  <!-- React Query -->
  <script src="https://unpkg.com/@tanstack/react-query@5/build/umd/index.production.min.js"></script>
  
  <!-- SDK CSS -->
  <link rel="stylesheet" href="https://unpkg.com/@finclusionaibuild/[email protected]/dist/styles.css">
  
  <!-- SDK Bundle (UMD) -->
  <script src="https://unpkg.com/@finclusionaibuild/[email protected]/dist/index.umd.js"></script>
  
  <script>
    // Access SDK from global window object (UMD build exposes FinclusionLivenessSDK)
    const { QueryClient, QueryClientProvider } = TanStackReactQuery;
    const { LivenessDetector } = window.FinclusionLivenessSDK;
    const { createRoot } = ReactDOM;
    
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: {
          retry: 2,
          refetchOnWindowFocus: false,
        },
      },
    });
    
    const config = {
      apiBaseUrl: '${apiBaseUrl}',
      getAuthToken: () => '${token}',
      endpoints: {
        createSession: '/api/liveliness',
        verify: '/api/liveliness/{sessionId}',
      },
    };
    
    const handleComplete = () => {
      // Send message to React Native
      window.ReactNativeWebView.postMessage(JSON.stringify({
        type: 'LIVENESS_COMPLETE',
        success: true,
      }));
    };
    
    const App = () => {
      return React.createElement(QueryClientProvider, { client: queryClient },
        React.createElement(LivenessDetector, {
          config: config,
          token: '${token}',
          gotoNext: handleComplete,
        })
      );
    };
    
    const root = createRoot(document.getElementById('root'));
    root.render(React.createElement(App));
  </script>
</body>
</html>
`;

function LivenessScreen() {
  const webViewRef = useRef<WebView>(null);
  const [loading, setLoading] = useState(true);

  const authToken = "your-auth-token-here"; // Get from your auth system
  const apiBaseUrl = "https://api.example.com";

  const handleMessage = (event: any) => {
    try {
      const data = JSON.parse(event.nativeEvent.data);

      switch (data.type) {
        case "LIVENESS_COMPLETE":
          Alert.alert("Success", "Liveness check completed!", [
            {
              text: "OK",
              onPress: () => {
                // Navigate to next screen
                navigation.navigate("NextScreen");
              },
            },
          ]);
          break;
        case "LIVENESS_ERROR":
          Alert.alert("Error", data.message || "Liveness check failed");
          break;
        default:
          console.log("WebView message:", data);
      }
    } catch (error) {
      console.error("Error parsing WebView message:", error);
    }
  };

  return (
    <View style={styles.container}>
      <WebView
        ref={webViewRef}
        source={{ html: getHTML(authToken, apiBaseUrl) }}
        onMessage={handleMessage}
        onLoadEnd={() => setLoading(false)}
        style={styles.webview}
        javaScriptEnabled={true}
        domStorageEnabled={true}
        mediaPlaybackRequiresUserAction={false}
        allowsInlineMediaPlayback={true}
        // Camera permissions
        permissions={["camera", "microphone"]}
        // iOS specific
        allowsBackForwardNavigationGestures={false}
        // Android specific
        mixedContentMode="always"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  webview: {
    flex: 1,
  },
});

export default LivenessScreen;

React Native with Local Bundle (Recommended)

For better performance and offline support, bundle the SDK locally:

import React, { useRef } from "react";
import { View, StyleSheet } from "react-native";
import { WebView } from "react-native-webview";
import { Asset } from "expo-asset"; // or react-native-fs for bare React Native

function LivenessScreen() {
  const webViewRef = useRef<WebView>(null);

  // Load SDK bundle from local assets
  const [sdkHtml, setSdkHtml] = useState("");

  useEffect(() => {
    // Load your bundled HTML file
    // This should include React, React Query, and the SDK bundle
    loadSDKHTML().then(setSdkHtml);
  }, []);

  return (
    <View style={styles.container}>
      <WebView
        ref={webViewRef}
        source={{ html: sdkHtml }}
        onMessage={handleMessage}
        style={styles.webview}
        javaScriptEnabled={true}
        domStorageEnabled={true}
        mediaPlaybackRequiresUserAction={false}
        allowsInlineMediaPlayback={true}
      />
    </View>
  );
}

React Native Permissions Setup

iOS (Info.plist)

Add camera and microphone permissions:

<key>NSCameraUsageDescription</key>
<string>We need access to your camera for face verification</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone for face verification</string>

Android (AndroidManifest.xml)

Add camera and internet permissions:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.front" android:required="true" />

React Native Error Handling

const handleMessage = (event: any) => {
  try {
    const data = JSON.parse(event.nativeEvent.data);

    if (data.type === "LIVENESS_ERROR") {
      const error = data.error;

      if (error.response?.status === 403) {
        // Handle unauthorized - redirect to login
        navigation.navigate("Login");
      } else if (error.response?.status === 400) {
        // Handle bad request
        Alert.alert("Verification Failed", "Please try again");
      } else {
        // Generic error
        Alert.alert("Error", error.message || "Something went wrong");
      }
    }
  } catch (error) {
    console.error("Error handling message:", error);
  }
};

// Handle WebView errors
const handleError = (syntheticEvent: any) => {
  const { nativeEvent } = syntheticEvent;
  console.error("WebView error: ", nativeEvent);
  Alert.alert("Error", "Failed to load liveness check");
};

TypeScript Types

The SDK exports comprehensive TypeScript types:

import type {
  LivenessConfig,
  LivenessSession,
  LivenessVerificationResponse,
  FaceMatchResponse,
  LivenessError,
} from "@finclusionaibuild/liveness-sdk";

// Example usage
const config: LivenessConfig = {
  apiBaseUrl: "https://api.example.com",
  getAuthToken: () => localStorage.getItem("token"),
};

const handleResponse = (response: LivenessVerificationResponse) => {
  if (response.confidence > 60) {
    console.log("Verification successful!", response.confidence);
  }
};

API Endpoints

The SDK expects your backend to provide these endpoints:

Create Session

Endpoint: GET /api/liveliness (or custom via config.endpoints.createSession)

Response:

{
  "sessionId": "string",
  "AccessKeyId": "string",
  "SecretAccessKey": "string",
  "SessionToken": "string",
  "Region": "string"
}

Verify Session

Endpoint: GET /api/liveliness/{sessionId} (or custom via config.endpoints.verify)

Response:

{
  "confidence": 85.5,
  "image": "base64-encoded-image",
  "success": true,
  "message": "Verification successful"
}

Compare with User (PaymentLiveness)

Endpoint: GET /api/liveliness/{sessionId}/compare-with-user (or custom via config.endpoints.compareWithUser)

Response:

{
  "isMatch": true,
  "confidence": 92.3,
  "details": "Face matches user profile"
}

Styling

The SDK includes all necessary styles bundled. Simply import:

import "@finclusionaibuild/liveness-sdk/styles.css";

The stylesheet includes:

  • Tailwind CSS utilities (responsive, mobile-optimized)
  • Finclusion UI styles (processed and rebranded)
  • Component-specific styling

Note: The SDK is mobile-responsive by default. No additional CSS configuration needed.

Troubleshooting

Camera Not Working

Web:

  • Ensure HTTPS (required for camera access)
  • Check browser permissions
  • Verify getUserMedia API is available

React Native:

  • Check camera permissions in Info.plist (iOS) and AndroidManifest.xml (Android)
  • Ensure WebView has allowsInlineMediaPlayback={true} (iOS)
  • Verify mediaPlaybackRequiresUserAction={false}

Styles Not Applying

  • Ensure you've imported the CSS: import '@finclusionaibuild/liveness-sdk/styles.css';
  • Check that the CSS file is being loaded (inspect network tab)
  • Verify no CSS conflicts with your app's styles

React Query Errors

  • Ensure QueryClientProvider wraps your component
  • Verify React Query version matches peer dependency (^5.39.0)
  • Check that QueryClient is created outside component render

API Errors

  • Verify apiBaseUrl is correct
  • Check authentication token is valid
  • Ensure endpoints match your backend API
  • Check CORS settings if using cross-origin requests

Build Errors

  • Ensure all peer dependencies are installed
  • Verify Node.js version (recommended: 18+)
  • Check TypeScript version compatibility

Examples

Modal Integration

import React, { useState } from "react";
import { LivenessDetector } from "@finclusionaibuild/liveness-sdk";

function LivenessModal() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>Start Verification</button>

      {isOpen && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg max-w-2xl w-full max-h-[90vh] overflow-auto p-4">
            <div className="flex justify-between items-center mb-4">
              <h2 className="text-xl font-bold">Face Verification</h2>
              <button onClick={() => setIsOpen(false)}>✕</button>
            </div>

            <LivenessDetector
              config={config}
              token={token}
              gotoNext={() => {
                setIsOpen(false);
                // Handle success
              }}
            />
          </div>
        </div>
      )}
    </>
  );
}

With Loading States

import React, { useState } from "react";
import { LivenessDetector } from "@finclusionaibuild/liveness-sdk";

function LivenessWithLoading() {
  const [isVerifying, setIsVerifying] = useState(false);

  return (
    <div>
      {isVerifying && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white p-6 rounded-lg">
            <p>Processing verification...</p>
          </div>
        </div>
      )}

      <LivenessDetector
        config={config}
        token={token}
        gotoNext={async () => {
          setIsVerifying(true);
          try {
            // Process result
            await processVerification();
          } finally {
            setIsVerifying(false);
          }
        }}
      />
    </div>
  );
}

License

MIT

Support

For issues, questions, or contributions, please visit our GitHub repository.

Version

Current version: 1.0.3