VerifymeDocs
Widget

Frameworks

React, Next.js, Vue, Nuxt, Svelte, Angular, plain HTML — one widget.

Every binding wraps the same loader, so options and events are identical. All of them take baseUrl when you run your own Verifyme instance.

React

"use client"
import { VerifyWidget } from "@cubis/verifyme/react"

export function PhoneStep({ token }: { token: string | null }) {
  return (
    <VerifyWidget
      token={token} // null is fine: the loader starts early, the widget opens when set
      onSuccess={({ proof }) => complete(proof)}
      onError={({ code }) => code === "session_expired" && restart()}
    />
  )
}

Need your own chrome around it? Use the hook:

import { useVerifyWidget } from "@cubis/verifyme/react"

const { ref, status, error } = useVerifyWidget({ token, onSuccess })
return (
  <>
    {status === "loading" && <Spinner />}
    <div ref={ref} />
  </>
)

Callbacks are kept in a ref, so re-renders never restart the verification. Next.js: use it in a Client Component ("use client"); create the session in a Route Handler or Server Action.

Vue and Nuxt

<script setup lang="ts">
import { VerifyWidget } from "@cubis/verifyme/vue"

const token = ref<string | null>(null)
onMounted(async () => {
  token.value = (await $fetch("/api/verify/start", { method: "POST" })).token
})
</script>

<template>
  <ClientOnly> <!-- Nuxt only -->
    <VerifyWidget :token="token" @success="({ proof }) => complete(proof)" />
  </ClientOnly>
</template>

Composable form: const { el, status } = useVerifyWidget({ token, onSuccess }) with <div ref="el" />. token, theme and labels may be refs.

Svelte, Angular, Solid, anything else

The loader defines a <verifyme-widget> custom element:

<script>
  import { onMount } from "svelte"
  import { loadWidgetScript } from "@cubis/verifyme/browser"
  export let token
  onMount(() => loadWidgetScript())
</script>

<verifyme-widget {token} on:verifyme-success={(e) => complete(e.detail.proof)} />

Events: verifyme-ready, verifyme-success ({ proof, expiresIn }), verifyme-error ({ code, message }), verifyme-close. Set theme and labels as properties. Changing token starts over; removing the element closes it.

Omit the container and the widget opens as an accessible modal (Esc and backdrop close it, focus returns afterwards):

import { openWidget } from "@cubis/verifyme/browser"

const widget = await openWidget({
  token,
  width: 400, // 280–640
  onSuccess: ({ proof }) => complete(proof),
  onClose: () => {},
})
widget.close()

Options

OptionDefault
tokenvw_… from your server
containermodalselector or element
baseUrlhttps://verifyme.cubis.techyour instance
theme · labelssaved brandingsee Customize
height320initial px, avoids layout shift
autoClosetruemodal closes after success
version · integrity · noncepin the loader, SRI, CSP nonce

Performance

  • The React and Vue bindings fetch the loader on mount, in parallel with your session request. Elsewhere call loadWidgetScript() early.
  • The loader is a few KB and cached; the frame's assets are content-hashed and immutable, so a return visit downloads nothing but the page.
  • Set height to your widget's usual height to avoid a jump.

Pin and lock the loader

For a strict CSP or change control, pin the exact file with Subresource Integrity. GET /widget/v1/integrity returns each file's version and integrity:

<VerifyWidget token={token} version="8ef6e2b8c38d" integrity="sha384-…" nonce={cspNonce} />

Unpinned is the right default: fixes reach you within five minutes.

On this page