Repository navigation
NextJS
Integrating the iProov Web SDK with Next.js requires a dynamic import because the SDK accesses browser APIs (window, document) that are not available during server-side rendering.
ℹ️ Supported versions. We support any Next.js release still receiving security patches — that is Active or Maintenance LTS under the Next.js support policy, which at the time of writing is v15 and above. This guide uses the Pages Router.
The same dynamic import pattern works in the App Router, but the component must be a Client Component — add
"use client"at the top of the file, becauseuseEffectanduseStateare not available in a Server Component. Reaching fornext/dynamicwithssr: falseinstead will not help: Next.js rejects that option in Server Components.
The key difference from a standard React integration is that @iproov/web-sdk must be imported dynamically inside a useEffect hook (or equivalent client-side lifecycle), not at the top of the file.
pages/index.tsx
import Head from "next/head"
import { useEffect, useState } from "react"
function IProovMe() {
const [token, setToken] = useState(null)
const [isLoading, setLoading] = useState(true)
useEffect(() => {
const fetchIproovMe = async () => {
// Dynamic import is required because Next.js renders on the server first,
// and the iProov SDK requires browser APIs (window, document) to initialise.
return await import("@iproov/web-sdk")
}
const fetchToken = async () => {
await fetchIproovMe()
// Replace with your backend token endpoint
const response = await fetch("***YOUR_BACKEND_TOKEN_ENDPOINT***", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
resource: "https://iproov.app",
user_id: "example@example.com",
client: "Web SDK NextJS",
}),
})
const data = await response.json()
setToken(data.token)
setLoading(false)
}
fetchToken().catch((err) => {
setLoading(false)
console.error(err)
})
}, [])
if (isLoading) return <p>Loading...</p>
if (!token) return <p>Error loading token</p>
return (
<iproov-me
token={token}
base_url="***YOUR_BASE_URL***"
assets_url="***YOUR_ASSETS_URL***"
aria_live="assertive"
>
<div slot="ready">
<div>Ready to verify</div>
</div>
</iproov-me>
)
}
export default function Home() {
return (
<>
<Head>
<title>iProov Web SDK - Next.js</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</Head>
<main>
<IProovMe />
</main>
</>
)
}Next.js pre-renders pages on the server by default. The iProov Web SDK registers a custom element (<iproov-me>) and accesses browser-only APIs during initialisation. A static import "@iproov/web-sdk" at the top of the file would execute during SSR and fail.
By using await import("@iproov/web-sdk") inside useEffect, the SDK is only loaded client-side after the component has mounted.
The Support Checker has its own subpath, so it can be loaded without pulling in the component at all — which is the point of it. Import it dynamically for the same SSR reason:
useEffect(() => {
const init = async () => {
const { iProovSupport } = await import("@iproov/web-sdk/iProovSupport.js")
const supportChecker = new iProovSupport()
const { supported, granted } = await supportChecker.check()
console.log("Supported:", supported, "Granted:", granted)
}
init()
}, [])
⚠️ From 7.0.0 thewindow.IProovglobal has been removed, sonew window.IProov.IProovSupport()no longer works. The.jsextension on the subpath is required, becauseexportssubpaths are matched exactly.
See the full Support Checker documentation.
Pass custom slots as children of the <iproov-me> component:
<iproov-me token={token} base_url="***YOUR_BASE_URL***" assets_url="***YOUR_ASSETS_URL***">
<div slot="ready">Ready to scan</div>
<div slot="button">Start scanning</div>
<div slot="passed">Verification passed!</div>
<div slot="failed">Verification failed</div>
</iproov-me>next.config.js
const nextConfig = {
reactStrictMode: true,
}
module.exports = nextConfigNo special Next.js configuration is required beyond the standard setup. The dynamic import handles the SSR/client boundary.
Set the assets_url attribute to the URL where your application serves the iProov SDK assets. For Next.js, copy the required assets from node_modules/@iproov/web-sdk into your public/ directory and set assets_url to your application's origin. See the Serving Assets and CORS guide for details.
The iProov SDK requires HTTPS for camera access. Next.js generates a locally trusted certificate for you:
next dev --experimental-httpsThe dev server then serves https://localhost:3000. To use your own certificate instead, pass --experimental-https-key and --experimental-https-cert.