This guide walks you through integrating the Accura Face Plugin into a Next.js project using the App Router.
Prerequisites
Before proceeding, ensure the following requirement is met:
accura.xml — Place your accura.xml file in the public/ folder of your project as public/accura.xml. This file is required by the plugin to initialize the face detection engine. You can download it from here.
If you do not have an existing Next.js project, create one using the official CLI:
npxcreate-next-app@latestmy-face-appcdmy-face-app
Step 2: Install Plugin
Install the Accura Face Plugin package from the npm registry:
Step 3: TypeScript Support
Since the accurafaceplugin package does not ship with TypeScript declarations, create a type definition file at the project root to resolve module errors and enable type checking:
Ensure this file is referenced in your tsconfig.json's include array:
Step 4: Implementation
Create components/FaceScanner.tsx. The snippet below demonstrates only the plugin import and instantiation — the minimal code required to activate the face detection engine in a Next.js client component:
Step 5: Response Handling
Upon a successful face capture, the plugin invokes the base64Handler callback asynchronously. The callback receives a single argument — an object with a base64 property containing the captured image encoded as a Base64 Data URL string (e.g., data:image/jpeg;base64,/9j/...).
What is Base64? Base64 is a binary-to-text encoding scheme that converts raw binary image data into a sequence of printable ASCII characters. The prefix segment (e.g., data:image/jpeg;base64,) conveys the MIME type, while the remainder is the encoded image payload. This format enables safe and seamless transmission of binary content over text-based protocols such as HTTP multipart form submissions.
The following handler demonstrates forwarding the captured image to a remote verification endpoint:
Step 6: Demo Implementation
The following is the complete, production-ready component. Copy and paste it directly into components/FaceScanner.tsx. The original logic is preserved exactly as-is.
Step 7: Usage
Import and render the component in your app/page.tsx:
"use client"; // Required: marks this as a Client Component for browser-only execution
import { useEffect, useRef } from "react";
import type FacePlugin from "accurafaceplugin";
export default function FaceScanner() {
const pluginRef = useRef<FacePlugin | null>(null); // Persists the plugin instance across renders
const initialized = useRef<boolean>(false); // Prevents double-init from React Strict Mode
useEffect(() => {
// Exit early if the plugin has already been initialized
if (initialized.current) return;
initialized.current = true;
// Dynamically import the plugin at runtime to avoid SSR-related errors.
// Next.js renders components on the server by default; browser APIs
// (camera, DOM) are unavailable there. Dynamic import defers execution
// to the client side only.
import("accurafaceplugin").then((Module) => {
const FacePlugin = Module.default;
// Instantiate the plugin with the license path, capture callback, and UI configuration.
pluginRef.current = new FacePlugin(
"/accura.xml", // Resolves to public/accura.xml at runtime
base64Handler, // Invoked automatically when a valid face is captured
{
threshold: 3, // Detection strictness level (1–100)
textSize: "", // Overlay text size (uses default when empty)
textColor: "", // Overlay text color (uses default when empty)
textWeight: "", // Overlay text font weight (uses default when empty)
textBgColor: "", // Overlay text background (uses default when empty)
BodyBgColor: "", // Viewport background color (uses default when empty)
}
);
// Launch the camera interface and begin the face detection session.
pluginRef.current.start().then(() => {
console.log("Accura Plugin Ready");
});
}).catch(err => {
console.error("Failed to load FacePlugin:", err);
});
// Cleanup: invoked when the component unmounts (e.g., page navigation).
// Ensures the camera stream is released and all plugin resources are freed.
return () => {
if (pluginRef.current) {
pluginRef.current.destroy();
}
};
}, []);
return <></>;
}
// Invoked by the plugin upon each successful face capture event.
// Receives: { base64 } — a complete Data URL of the captured face image.
const base64Handler = async ({ base64 }: { base64: string }) => {
console.log("Base64 received:", base64);
try {
// Compose a multipart form body to carry the base64-encoded image.
const formData = new FormData();
// Attach the image string under the field name expected by your backend.
formData.append("imagebase64", base64);
// Send the payload to your server-side face verification endpoint.
// Replace with your actual backend host and path.
const response = await fetch("https://ip:port/upload.php", {
method: "POST",
body: formData,
});
// Parse the JSON body of the server response.
const data = await response.json();
console.log("API Response:", data);
// Inspect the liveness/match score returned by the verification service.
if (data?.score !== undefined) {
console.log(`Score: ${data.score}`);
}
} catch (error) {
console.error("Error sending to API:", error);
}
};