FaceGateBack to home

React SDK

@facegate/react is the drop-in face authentication component. It owns the camera, the liveness challenge, and the QR fallback for devices without a camera. You give it an API key and an onAuthenticated callback. Everything else ships inside the component.

It targets React 18 and 19. The core is the <FaceGate /> component plus a small set of theme and consent helpers.

Install

npm install @facegate/react

If you are minting a Supabase session from the scan, also install the adapter:

npm install @facegate/react @facegate/supabase

Usage

import { FaceGate } from '@facegate/react';
 
export function SignIn() {
  return (
    <FaceGate
      apiKey="fg_test_your_key_here"
      mode="verify"
      onAuthenticated={(session) => {
        // session.token         — signed JWT
        // session.user          — { id, name, role, metadata }
        // session.provider_session — provider tokens (Tier 2), or null
        console.log('Signed in as', session.user.name);
      }}
      onError={(err) => console.error(err)}
    />
  );
}

That is the entire client integration. No camera permission UI to build, no liveness logic to write.

Props

These are the props on the FaceGateProps type (sdk/react/src/FaceGate.tsx, lines 17–28). Document only what is in the type — there are no other props.

PropTypeDefaultDescription
apiKeystringYour FaceGate API key (fg_test_… in development). Required unless supplied by <FaceGateProvider />. If missing, the component renders an error.
serverUrlstringhttps://api.facegate.aiFaceGate API base URL. Override for self-hosted servers.
mode'verify' | 'enroll''verify'verify authenticates an existing user. enroll captures a new face. See Modes.
livenessbooleantrueRequire a liveness challenge (head movements) after the face match. Leave on for anti-spoofing.
onAuthenticated(session: FaceGateSession) => voidFired on a successful verification. Receives the session.
onError(error: Error) => voidFired on camera, network, or verification failure.
enrollment{ name: boolean; email?: boolean; phone?: boolean }{ name: true }Which fields to collect during enroll mode. Ignored in verify mode.
theme'dark' | 'light' | Record<string, string>'dark'Preset name or a map of theme overrides. See Theming.
fallback'qr' | 'none''qr'Behavior when the device has no usable camera. qr shows a scan-to-continue code; none shows an error. See QR fallback.

Modes

mode selects what the component does with the captured face.

ModeWhat it doesWhat you get back
verifyMatches the face against an enrolled user and runs liveness.A FaceGateSession via onAuthenticated.
enrollCaptures a new face and collects the fields named in enrollment.A FaceGateSession for the newly enrolled user via onAuthenticated.
<FaceGate
  apiKey="fg_test_your_key_here"
  mode="enroll"
  enrollment={{ name: true, email: true }}
  onAuthenticated={(session) => {
    console.log('Enrolled', session.user.id);
  }}
/>

The session shape

onAuthenticated receives a FaceGateSession. The type is re-exported from @facegate/react and defined in @facegate/client (sdk/client/src/types.ts, lines 61–74).

import type { FaceGateSession } from '@facegate/react';
 
interface FaceGateSession {
  token: string;            // signed JWT access token
  refresh_token: string;    // refresh token
  expires_in: number;       // token expiry in seconds
  user: {
    id: string;
    name: string;
    role: string | null;
    metadata: Record<string, unknown>;
  };
  provider_session: Record<string, unknown> | null; // provider tokens (Tier 2), or null
  confidence?: number;      // face-match confidence (0–100)
}

For Tier 1 (Verify), use token directly — you manage sessions yourself. For Tier 2 (Adapt), hand the whole session to your provider adapter; provider_session carries the tokens it needs.

Provider

To avoid passing apiKey to every <FaceGate />, wrap your app in <FaceGateProvider />. Props passed directly to <FaceGate /> still win.

PropTypeDefaultDescription
apiKeystringAPI key inherited by descendant <FaceGate /> components.
serverUrlstringhttps://api.facegate.aiServer URL inherited by descendants.
childrenReactNodeYour app tree.
import { FaceGateProvider, FaceGate } from '@facegate/react';
 
export function App() {
  return (
    <FaceGateProvider apiKey="fg_test_your_key_here">
      <FaceGate mode="verify" onAuthenticated={handleAuth} />
    </FaceGateProvider>
  );
}

Theming

Pass theme="dark" (the default) or theme="light" for a preset, or a Record<string, string> to override individual tokens.

For programmatic control, @facegate/react exports LIGHT_THEME, DARK_THEME, and resolveTheme, plus the FaceGateTheme type. resolveTheme merges your overrides onto a preset and resolves colorScheme: 'auto' against the system preference.

import { resolveTheme } from '@facegate/react';
 
const brand = resolveTheme({
  colorScheme: 'auto',     // 'dark' | 'light' | 'auto'
  accentColor: '#6366f1',
  borderRadius: '20px',
});
 
<FaceGate apiKey="fg_test_your_key_here" theme={brand} />;

The FaceGateTheme tokens (sdk/react/src/theme.ts, lines 1–12):

TokenTypeDescription
colorScheme'dark' | 'light' | 'auto'Base scheme. auto follows the system preference.
accentColorstringPrimary accent (oval, progress, success).
backgroundColorstringComponent background.
textColorstringPrimary text.
mutedColorstringSecondary text and hints.
borderColorstringBorders and dividers.
errorColorstringError state.
successColorstringSuccess state.
borderRadiusstringCorner radius.
fontFamilystringFont stack.

QR and camera fallback

When the device has no usable camera, fallback decides what happens:

  • fallback="qr" (default) renders a QR code. The user scans it with a phone, authenticates there, and the original session activates over a WebSocket. No code on your side.
  • fallback="none" renders an error instead.

The component detects the camera and switches automatically — you do not branch on device type.

Consent

@facegate/react also exports the BiometricConsent component plus the CONSENT_TEXT string and getConsentHash helper, for jurisdictions that require explicit biometric consent before enrollment. Gate mode="enroll" behind <BiometricConsent /> where you need a recorded opt-in.

Next steps

  • Next.js — App Router setup, 'use client', and SSR notes.
  • Supabase adapter — turn a scan into a real Supabase session.
  • REST API — call the endpoints directly without the SDK.