Framework Integration

📘

This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation here. We strongly recommend upgrading - contact your Incode Representative for upgrade information.

Every Incode UI module ships as a standard Web Component — registered via a side-effect import (import '@incodetech/web/<module>') and consumed like any HTML element. Because the elements are framework-agnostic, the same SDK code runs from vanilla HTML, React, Angular, Vue, or any other web framework. The only difference is how each framework lets you mount custom elements and bind non-string properties.

This page documents the four mainstream paths. All of them share one rule:

Set config, onFinish, and onError as JavaScript properties on the element, not as HTML attributes. They are object/function values, not strings, so they can't go through setAttribute. Each framework section below shows how to do that idiomatically.

Vanilla HTML / TypeScript

<incode-flow id="flow"></incode-flow>

<script type="module">
  import { setup } from '@incodetech/core';
  import '@incodetech/web/flow';
  import '@incodetech/web/flow/styles.css';

  await setup({ apiURL: 'https://demo-api.incodesmile.com', token: session.token });

  const flow = document.getElementById('flow');
  flow.config = { token: session.token };
  flow.onFinish = (result) => {
    /* ... */
  };
</script>

The same shape applies to every other module — replace flow with phone, selfie, id, etc., and set the corresponding config / handlers on the element.

React

Universal pattern (works on React 16.8+)

Use the custom element directly with a ref. React renders custom elements as-is, and you assign non-string properties imperatively in useEffect. This works on every React version since hooks landed:

import { useEffect, useRef } from 'react';
import { setup } from '@incodetech/core';
import type { FlowConfig } from '@incodetech/web/flow';
import type { FinishStatus } from '@incodetech/core/flow';
import '@incodetech/web/flow';
import '@incodetech/web/flow/styles.css';

type FlowElement = HTMLElement & {
  config: FlowConfig;
  onFinish: (result?: FinishStatus) => void;
};

export function MyFlow({ token }: { token: string }) {
  const ref = useRef<FlowElement>(null);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    el.config = { token };
    el.onFinish = (result) => console.log('Done:', result);
  }, [token]);

  return <incode-flow ref={ref} style={{ display: 'block', height: '100vh' }} />;
}

React 19+ shortcut

React 19 ships native custom-element support: it sets non-string JSX props as DOM properties and bridges on* props through addEventListener. If you're on React 19 you can drop the ref + useEffect ceremony entirely:

import { setup } from '@incodetech/core';
import '@incodetech/web/flow';
import '@incodetech/web/flow/styles.css';

export function MyFlow({ token }: { token: string }) {
  return (
    <incode-flow
      config={{ token }}
      onFinish={(result) => console.log('Done:', result)}
      onError={(error, code) => console.error(error, code)}
      style={{ display: 'block', height: '100vh' }}
    />
  );
}

This shortcut does not work on React 18 or earlier — those versions serialize JSX props through setAttribute, which coerces config={{token}} to the string "[object Object]". Use the universal pattern above unless you're certain every consumer of your code is on React 19+.

TypeScript: JSX support for incode-* tags

React 19+ treats unknown lowercase tags as HTML elements automatically — no extra TypeScript setup is needed.

React 18 and earlier strict-checks JSX.IntrinsicElements, so referencing <incode-flow> (or any other Incode tag) directly in JSX errors out. Add a one-time augmentation somewhere in your project (e.g. src/types/incode.d.ts) that covers every incode-* tag your app uses:

// src/types/incode.d.ts
import 'react';

type IncodeElementAttrs = React.DetailedHTMLProps<
  React.HTMLAttributes<HTMLElement>,
  HTMLElement
>;

declare global {
  namespace JSX {
    interface IntrinsicElements {
      'incode-flow': IncodeElementAttrs;
      'incode-flow-completed': IncodeElementAttrs;
      'incode-selfie': IncodeElementAttrs;
      'incode-id': IncodeElementAttrs;
      'incode-phone': IncodeElementAttrs;
      'incode-email': IncodeElementAttrs;
      'incode-document-capture': IncodeElementAttrs;
      'incode-face-match': IncodeElementAttrs;
      'incode-consent': IncodeElementAttrs;
      'incode-geolocation': IncodeElementAttrs;
      'incode-antifraud': IncodeElementAttrs;
      'incode-curp-validation': IncodeElementAttrs;
      'incode-identity-reuse': IncodeElementAttrs;
      'incode-redirect-to-mobile': IncodeElementAttrs;
      'incode-signature': IncodeElementAttrs;
      'incode-electronic-signature': IncodeElementAttrs;
      'incode-ae-signature': IncodeElementAttrs;
      'incode-qe-signature': IncodeElementAttrs;
      'incode-ekyc': IncodeElementAttrs;
      'incode-ekyb': IncodeElementAttrs;
      'incode-workflow': IncodeElementAttrs;
      'incode-cross-document-data-match': IncodeElementAttrs;
      // Add any other incode-* tags you mount; the shape is identical.
    }
  }
}

The element-specific properties (config, onFinish, onError) are set imperatively through the ref — that's why IncodeElementAttrs is just the standard HTML element shape. The full per-tag catalog lives in Web Components.

Angular

Add CUSTOM_ELEMENTS_SCHEMA to the module that uses Incode tags:

import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@NgModule({
  declarations: [MyFlowComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class AppModule {}

Then bind to the element's properties from a template using property binding:

<incode-flow [config]="flowConfig" (onFinish)="handleFinish($event)"></incode-flow>

Vue 3

Tell the template compiler to treat incode-* tags as custom elements:

// vite.config.ts
import vue from '@vitejs/plugin-vue';

vue({
  template: {
    compilerOptions: {
      isCustomElement: (tag) => tag.startsWith('incode-'),
    },
  },
});

Then bind properties with .prop modifiers:

<incode-flow :config.prop="flowConfig" :onFinish.prop="handleFinish" />

See also