Note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation here. Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade.
Full rollout to all clients still TBD.
WebAssembly (WASM) powers the SDK's on-device ML pipelines: face detection and liveness for the Selfie module, document detection and quality scoring for the ID Capture module.
When WASM is Required
The SDK ships the following ML pipelines, all delivered as WebAssembly:
| Pipeline | Used by | Default warmup? | What it does |
|---|---|---|---|
selfie |
<incode-selfie>, <incode-authentication> (via createAuthenticationManager), createSelfieManager |
Yes, when pipelines is omitted |
Face detection, positioning feedback, liveness analysis. |
idCapture |
<incode-id>, createIdCaptureManager |
Yes, when pipelines is omitted |
Document detection plus blur / glare / barcode quality checks during capture. |
onDeviceSelfie |
Selfie / Authentication when onDeviceFaceResultsSubmissionEnabled: true |
No, opt-in only | On-device face-results pipeline. Computes the face analysis client-side; the SDK submits the results to the server only. |
videoSelfie |
<incode-video-selfie>, createVideoSelfieRecordingManager |
No, opt-in only | Face detection tuned for the video-selfie flow. |
videoSelfieId |
<incode-video-selfie>, createVideoSelfieRecordingManager |
No, opt-in only | Document detection tuned for the video-selfie flow. |
onDeviceSelfie is opt-in — it is not in the default pipelines set. Enabling it has prerequisites beyond just the WASM pipeline (E2EE-provisioned apiURL, the onDeviceFaceResultsSubmissionEnabled config flag, and an API-key transmission choice); see On-Device Face Capture for the full walkthrough.
videoSelfie and videoSelfieId are also opt-in. The Core Video Selfie recording manager automatically warms the pipelines its config needs; warmupVideoSelfieWasm (@incodetech/core/video-selfie) remains available for explicit earlier preloading.
WASM is not needed for phone verification, email verification, consent, redirect-to-mobile, or any flow that doesn't include the selfie or ID-capture modules — unless you enable End-to-end encryption, which routes all SDK traffic through the WASM transport.
Configuration
The simplest integration is the wasm option on setup(). It accepts a WasmConfig object, the literal false, or can be omitted entirely:
import { setup } from '@incodetech/core';
import { initializeSession } from '@incodetech/core/session';
// 1. Default: omit the option — the SDK does NOT preload WASM.
// It loads lazily on first selfie or ID capture.
await setup({ apiURL: 'https://demo-api.incodesmile.com' });
await initializeSession({ token: 'your-session-token' });
// 2. Preload using Incode's CDN defaults (recommended for most apps).
// Paths and model files come from the CDN; you only choose pipelines.
await setup({
apiURL: 'https://demo-api.incodesmile.com',
wasm: { pipelines: ['selfie'] }, // or ['selfie', 'idCapture']
});
await initializeSession({ token: 'your-session-token' });
// 3. Hybrid configuration: override selected paths. Anything omitted
// continues to use the Incode CDN.
await setup({
apiURL: 'https://demo-api.incodesmile.com',
wasm: {
wasmPath: '/wasm/webLib.wasm',
glueCodePath: '/wasm/webLib.js',
modelsBasePath: '/wasm/models',
},
});
await initializeSession({ token: 'your-session-token' });
// 4. Explicitly disable WASM warmup (e.g. when this page only runs
// phone or email verification, and you want to skip the bundle cost).
await setup({ apiURL: 'https://demo-api.incodesmile.com', wasm: false });
await initializeSession({ token: 'your-session-token' });
Each snippet pairs setup({ apiURL, wasm? }) (which provisions the HTTP client and optionally warms up WASM) with initializeSession({ token }) (which activates the session). The one-shot form setup({ apiURL, token }) is still supported and delegates to initializeSession internally — splitting them out lets you start setup before the session token exists, e.g. to begin WASM warmup while createSession is still in flight.
Advanced: warmupWasm() directly
For headless integrations or callers that want to pre-warm WASM before setup() runs (or with stricter typing), import the underlying helper from @incodetech/core/wasm:
import { warmupWasm } from '@incodetech/core/wasm';
await warmupWasm({
wasmPath: '/wasm/webLib.wasm',
wasmSimdPath: '/wasm/webLibSimd.wasm', // optional SIMD variant
glueCodePath: '/wasm/webLib.js',
modelsBasePath: '/wasm/models', // default: inferred from wasmPath
pipelines: ['selfie', 'idCapture'], // default: both pipelines
});
WarmupConfig (the type that warmupWasm accepts) requires wasmPath and glueCodePath. WasmConfig (the type setup({ wasm }) accepts) makes those optional and fills missing fields from the Incode CDN.
WasmConfig properties
WasmConfig accepts every WarmupConfig property below as optional. It also accepts these setup properties:
| Property | Type | Required | Description |
|---|---|---|---|
basePath |
string |
No | Root URL that contains the binaries, glue modules, and models/ directory. It derives wasmPath, glueCodePath, and modelsBasePath. |
selfHosted |
boolean |
No | Enables strict asset resolution: a required model that is not supplied throws before any request is made. defineWasm sets it automatically; with basePath, set it yourself. |
showLogs |
boolean |
No | Enables verbose native logs. Default false. Use it only for local diagnosis. |
WarmupConfig properties
| Property | Type | Required | Description |
|---|---|---|---|
wasmPath |
WasmSource |
Yes | URL, data URI, ArrayBuffer, or Uint8Array for the standard binary |
glueCodePath |
string |
Yes | Path to the standard JavaScript glue |
wasmSimdPath |
WasmSource |
No | SIMD binary source. Falls back to wasmPath |
glueCodeSimdPath |
string |
No | Path to the SIMD glue. Defaults to a sibling .js derived from wasmSimdPath |
useSimd |
boolean |
No | Use SIMD when available. Default true |
pipelines |
WasmPipeline[] |
No | Pipelines to preload. Default ['selfie', 'idCapture'] |
modelsBasePath |
string |
No | Root URL for model files. Defaults to a directory beside wasmPath |
pipelineModels |
object |
No | Override model filenames per pipeline |
modelUrls |
object |
No | Fully resolved source for each model filename. Used verbatim; the SDK never rewrites these URLs |
legacyModelUrls |
object |
No | Non-SIMD counterparts of modelUrls, keyed by the same filenames. Used only when SIMD initialization falls back to the standard binary. Also used verbatim |
loadGlue |
function |
No | Lazy ES-module loader for standard glue |
loadGlueSimd |
function |
No | Lazy ES-module loader for SIMD glue |
WasmPipeline is 'selfie' | 'idCapture' | 'onDeviceSelfie' | 'videoSelfie' | 'videoSelfieId'. Add 'onDeviceSelfie' only when you've also enabled onDeviceFaceResultsSubmissionEnabled on the relevant Selfie or Authentication config; add 'videoSelfie' / 'videoSelfieId' only when your flow includes the video-selfie module.
End-to-end encryption
setup({ encryption: true }) opts the SDK into end-to-end-encrypted transport for every request. The encrypted transport runs over the WASM binary channel — the legacy plain fetch / XHR transport does not support E2EE.
E2EE is a one-flag enable but has provisioning prerequisites (dedicated apiURL, MGF1 scheme, and an API-key transmission choice) that can't be guessed. See End-to-End Encryption for the full walkthrough, including the /0 vs customHeaders: { 'x-api-key': ... } choice and failure-mode troubleshooting.
Hosting WASM Files
The SDK uses cdn.incodesmile.com by default. Existing integrations do not need to change.
Use one of these self-hosting routes when the Incode CDN is not permitted:
| Route | Use it when |
|---|---|
basePath |
You use a customer CDN, an air-gapped mirror, a script tag, or a server-driven Flow or Workflow. |
| Explicit imports | Your bundler must hash and deploy a known module set with the application. |
Self-hosting is available in 2.3.0. Obtain the release-matched asset distribution and deployment instructions from your Incode representative. Deploy the complete distribution without renaming files or changing its directory layout; keep it separate from assets for other SDK releases.
Customer CDN or mirror
Point basePath at the root of that distribution. Core setup can run before you receive a session token:
import { setup } from '@incodetech/core';
import { initializeSession } from '@incodetech/core/session';
await setup({
apiURL: 'https://demo-api.incodesmile.com',
wasm: {
basePath: 'https://mycdn.example.com/assets/incode/release-assets',
selfHosted: true,
pipelines: ['idCapture'],
},
});
// Activate the token obtained from your backend before starting verification.
await initializeSession({ token: 'SESSION_TOKEN_FROM_YOUR_BACKEND' });
Use a versioned directory or replace the whole distribution atomically and invalidate stale caches. Keep all compatibility assets supplied with the distribution. A missing asset must fail visibly; do not rely on a fallback to the Incode CDN.
Flow and Workflow reuse the WASM configuration from setup(). A component-level wasmConfig overrides that stored configuration.
Bundler-managed assets
defineWasm from @incodetech/core/wasm accepts explicit asset sources and lazy JavaScript loaders and produces a WasmConfig. It sets selfHosted: true and checks that the declared pipelines have their required assets. Use the release-matched import configuration provided with your asset distribution; the asset inventory is not maintained in this guide.
Configure your bundler to emit the supplied binary assets as URLs and preserve lazy JavaScript imports. WasmSource also accepts data URIs, ArrayBuffer, and Uint8Array; emitted URLs generally avoid retaining the binary in your application's JavaScript memory.
Missing assets
Treat initialization or download failures as deployment errors. Check that every required asset is available at its configured URL, that CORS permits your application, and that your deployment has not mixed SDK releases. Contact your Incode representative if the supplied distribution does not satisfy the selected pipelines.
Server Configuration
Serve WASM files with the correct header:
Content-Type: application/wasm
Nginx:
types {
application/wasm wasm;
}
Apache:
AddType application/wasm .wasm
For a cross-origin CDN, allow the application origin through CORS. Serve model files as application/octet-stream.
If the server normally returns index.html for unknown paths, exclude the WASM directory. A missing binary must return an error status, not HTML with status 200.
Versioned asset directories can use:
Cache-Control: public, max-age=31536000, immutable
SIMD Support
The SDK automatically uses SIMD-optimized WASM when the browser supports it, falling back to standard WASM otherwise. Provide both files for best compatibility.
Lazy Loading
If you don't pass a wasm option to setup(), WASM stays unloaded until the first <incode-selfie> or <incode-id> (or their headless createSelfieManager / createIdCaptureManager counterparts) actually needs it. The Workflow also waits to load the Selfie or ID pipeline until that capture step starts instead of loading both at startup. This keeps the initial bundle small for flows that only run phone, email, consent, or other non-capture steps. For latency-sensitive selfie/ID flows, prefer wasm: { pipelines: [...] } so warmup runs while the user is on earlier steps.
Troubleshooting
| Issue | Solution |
|---|---|
| WASM not loading | Check file paths and server MIME types |
| 404 errors | Verify files are in your public directory |
| Face detection not working | Ensure models are in the correct path |
See Also
- Module: Selfie: Selfie capture documentation
- Troubleshooting: Common issues