Widget Configuration
The widget is a single script (widget.js) with zero runtime dependencies. It exposes the global NexloLabsVerification object.
Loading the script
<script src="https://verify.nexlolabs.net/widget.js"></script>
A minified version is available at https://verify.nexlolabs.net/widget.min.js.
Data attributes
Every <div class="nexlolabs-verification"> is configured through attributes:
| Attribute | Default | Values | Description |
|---|---|---|---|
data-sitekey | — | nlx_site_... | Required. Public key of your site. |
data-type | checkbox | checkbox, image_select, puzzle, math, code, shapes, vowels, invisible | Challenge type to render. |
data-difficulty | normal | easy, normal, hard | Challenge strength (tile count, grid size, code length). |
data-theme | auto | auto, light, dark | Color scheme. auto follows prefers-color-scheme. |
data-locale | auto | en, de, fr, es | UI language. auto follows the browser language. |
data-size | normal | normal, compact | Widget size. |
data-styles | {} | JSON string | Per-widget styling overrides (see below). |
Example:
<div
class="nexlolabs-verification"
data-sitekey="nlx_site_YOUR_SITE_KEY"
data-type="puzzle"
data-difficulty="hard"
data-theme="dark"
data-locale="de"
></div>
Styling
Apply a brand look via data-styles (JSON) with CSS custom-property overrides:
<div
class="nexlolabs-verification"
data-sitekey="nlx_site_YOUR_SITE_KEY"
data-styles='{"primaryColor":"#7c3aed","radius":"10px","checkboxSize":"28px"}'
></div>
| Key | Type | Default | Description |
|---|---|---|---|
primaryColor | string | brand color | Accent color for buttons & active elements. |
radius | string | inherited | Border radius of the container (any CSS length). |
checkboxSize | string | platform default | Side length of the checkbox (any CSS length). |
Global configuration
Set window.NexloLabsConfig before the widget script loads:
<script>
window.NexloLabsConfig = {
apiBaseUrl: "https://verify.nexlolabs.net/api", // override for self-hosting
locale: "en",
theme: "auto",
};
</script>
<script src="https://verify.nexlolabs.net/widget.js"></script>
| Option | Type | Default | Description |
|---|---|---|---|
apiBaseUrl | string | https://verify.nexlolabs.net/api | Base URL of the API. |
locale | "en" | "de" | "fr" | "es" | en | Default locale for all widgets. |
theme | "auto" | "light" | "dark" | auto | Default theme for all widgets. |
JavaScript API
render(selector) → NexloLabsVerification
Renders a widget into every matching element.
NexloLabsVerification.render(".nexlolabs-verification");
onSuccess(callback)
Called with the verification token once the challenge is solved.
NexloLabsVerification.onSuccess((token) => {
console.log("Token:", token);
});
onError(callback)
Called when the widget fails (network error, invalid site key, expired challenge, ...).
NexloLabsVerification.onError((error) => {
console.error(error.message);
});
onExpired(callback)
Called when a token expires before being redeemed.
NexloLabsVerification.onExpired(() => {
console.log("Token expired - re-verifying");
});
reset()
Clears all widgets and resets their state. Useful on form errors.
NexloLabsVerification.reset();
execute()
Runs the challenge flow programmatically (e.g. for invisible verification).
NexloLabsVerification.execute();
getToken() → string | null
Returns the current token (same value as delivered to onSuccess).
destroy()
Removes all widget UI and event listeners.
Token lifecycle
- Widget creates a challenge (
POST /api/challenge/create). - User solves it (
POST /api/challenge/solve) → signed token returned. - Token is valid for 120 seconds and can be redeemed once.
onSuccessfires with the token. After verification server-side, it cannot be re-used.
The widget itself never verifies the token — verification always happens in your backend with your site secret. A token shown in the browser cannot be forged or reused because it is HMAC-signed.
Multiple widgets per page
Every nexlolabs-verification div becomes its own widget. Tokens are emitted per widget and each token can only be redeemed once — submit the token that belongs to the form being sent.
Self-hosting
Point apiBaseUrl at your own deployment:
window.NexloLabsConfig = { apiBaseUrl: "https://verify.your-domain.com/api" };