Next JS (Recommended default template)
Follow these steps to get started with NextJS template.
-
Set up the workspace by running the following command:
pnpx create-next-app@latest livenesstestA folder/directory named
livenesstestshould appear and the folder/ directory structure should look like this:livenesstest/ | +-- node_modules/ | +-- public/ | | | +-- file.svg | | | +-- globe.svg | | | +-- next.svg | | | +-- vercel.svg | | | \-- window.svg | +-- app/ | | | +-- favicon.ico | | | +-- global.css | | | +-- layout.tsx | | | \-- page.tsx | +-- .gitignore | +-- AGENTS.md | +-- CLAUDE.md | +-- eslint.config.mjs | +-- next-env.d.ts | +-- next.config.ts | +-- package.json | +-- package-lock.json | +-- postcss.config.mjs | +-- README.md | \-- tsconfig.json -
Extract file
Verihubs WebSDK Liveness [version] [organization].zipfile. Renamebuildfolder/directory asliveness. -
Put extracted
livenessfolder/directory that contains the liveness engine and builders likebuilder.js, into thepublicfolder/directory of project folder/directory (livenesstest). -
Add the liveness package to
package.jsonby running this command insidelivenesstestReact.js project.livenesstest$ pnpm i file:public/livenessThis will add
@verihubs/livenessdependency inpackage.json. -
Create
liveness.tsxfile insidesrcfolder -
Add the following code to the
liveness.tsxfile insidesrcfolder."use client"; import { useCallback, useEffect, useState } from "react"; import Builder from "@verihubs/liveness"; import Image from "next/image"; export default function Liveness() { const [image, setImage] = useState<string | null>(null); const [data, setData] = useState(""); const LivenessSDK = new Builder() .setInstruction(["look_left", "look_right"], { commands: ["open_mouth"], seedLimit: 1, }) .setProxyMiddleware({ PassiveLiveness: { url: "http://localhost:8888/liveness/face", headers: { "App-ID": "<replace-me-with-app-id>", "api-key": "<replace-me-with-api-key>", }, }, License: { url: "http://localhost:8888/license/{license_id}/check", headers: { "App-ID": "<replace-me-with-app-id>", "api-key": "<replace-me-with-api-key>", }, }, }) .setTimeout(60000) .setURL("./liveness") .setVirtualCameraLabel(["OBS", "Virtual"]) .build(); useEffect(() => { const livenessMessageListener = ({ data: { data, subject }, }: { // eslint-disable-next-line @typescript-eslint/no-explicit-any data: { data: any; subject: string }; }) => { switch (subject) { case "Verification.Verbose": console.log("[Verbose]", data); break; case "Camera.NotAllowed": case "Camera.NotFound": case "Camera.PermissionDenied": case "ScreenOrientation.NotAllowed": case "Verification.Disrupted": case "Verification.Timeout": console.log({ data, subject }); alert(subject); LivenessSDK.onDestroy(); break; case "Verification.Success": setImage(`data:image/png;base64,${data.image.url}`); setData(JSON.stringify(data, undefined, 2)); LivenessSDK.onDestroy(); break; default: console.log({ data, subject }); alert(subject); break; } }; window.addEventListener("message", livenessMessageListener); return () => { window.removeEventListener("message", livenessMessageListener); }; }, [LivenessSDK]); const doLivenessVerification = useCallback(() => { LivenessSDK.onStart(); }, [LivenessSDK]); return ( <div> <button onClick={doLivenessVerification}> Run Liveness Verification </button> <br /> {image && <Image src={image} alt="" />} <div className="data-result">{data}</div> </div> ); }Replace proxy middleware URLs with a URL that points to the correct endoints, and replace
<replace-me-with-app-id>and<replace-me-with-api-key>with the appropriate App-ID and API-Key for the passive liveness (remove the headers if the api doesn't need credentials or the url is pointing towards an intermediate endpoint).Look Out!To not accidentally leak of
AppIDandAPIKeyfor passive liveness, always pass them to an intermediate endpoint (like a proxy middleware) and append theApp-IDandAPI-Keyheader before reaching Verihubs' passive liveness service in production. Additional data can also be passed to this intermediate endpoint for end user identification.For more information about creating a Proxy Middleware, refer to Proxy Middleware.
For API documentation of the Builder, refer to
Builder.InfoCheck System Messages for full system message references.
-
Populate the
page.tsxcomponent logic by the code below:"use client"; import dynamic from "next/dynamic"; const Liveness = dynamic(() => import("./liveness"), { ssr: false }); export default function Home() { return ( <div className="flex flex-col flex-1 items-center justify-center bg-zinc-50 font-sans dark:bg-black"> <main className="flex flex-1 w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start"> <Liveness /> </main> </div> ); }
To try the above implementation you can run the following command from the livenesstest project:
livenesstest$ pnpm devUpdated about 10 hours ago
Protect credential using Proxy Middleware
