# Asset Overrides

:::note
This guide is specific to Web SDK 2.0. If you are still using 1.x, you can find documentation [here](/sdk-reference/web-sdk-reference).  Contact your Incode Representative for upgrade information and check if you are a candidate for this upgrade. <br /><br />Full rollout to all clients still TBD.
:::

Replace the SDK's built-in branded illustrations (SVG) and animations (Lottie) with your own artwork - no fork, no rebuild. Overrides are supplied at runtime through the same `setup()` / web-component `config` channels you already use for the rest of the SDK.

This is a different mechanism from [Theming & Styling](/sdk-reference/web-sdk-2-theming/): CSS tokens recolor functional UI chrome (buttons, inputs, the spinner track) via `currentColor`, while asset overrides replace whole decorative illustrations and animations — tutorial graphics, success/fail screens, and similar branding moments.

## Quick start

Pass `assets` and/or `animations` maps to the `uiConfig` option of `setup()`. Keys are type-checked — only allowlisted keys autocomplete, and an unknown key is a compile error:

```ts
import { setup } from '@incodetech/web';

await setup({
  apiURL: API_URL,
  token: session.token,
  uiConfig: {
    assets: {
      // A plain string is treated as a URL (or raw `<svg …>` markup if it starts with '<')
      'faceMatch.success': 'https://cdn.example.com/id/match-ok.svg',
    },
    animations: {
      'id.tutorial.front': { url: 'https://cdn.example.com/id/tutorial.json' },
    },
  },
});
```

Every SDK instance on the page picks up these overrides. To change overrides after `setup()` has already run, call `setUiConfig` directly:

```ts
import { setUiConfig } from '@incodetech/web';

setUiConfig({
  assets: { 'faceMatch.success': 'https://cdn.example.com/id/match-ok.svg' },
});
```

`setUiConfig` replaces the entire `UiConfig` object rather than merging into it — pass every field you want to keep (`logoSrc`, `assets`, `animations`, and so on) each time you call it.

## How overrides resolve

An override wins in this order, most specific first:

1. **Per-instance** — the `assets` / `animations` maps on a single web component's `config` prop (see [Per-instance overrides](#per-instance-overrides) below).
2. **Global** — the `assets` / `animations` maps passed to `setup({ uiConfig })` or `setUiConfig`.
3. **Built-in default** — the SDK's own illustration or animation, unchanged.

If a key has no override at any tier, the SDK renders exactly what it renders today. A malformed override, a `{ url }` that fails to load, or an unknown key all fall back to the built-in default silently — an override never throws and never blocks rendering.

## What can be overridden

Overrides are **allowlist-only**. Only the keys listed below can be overridden; there is no override-by-path or wildcard. Every other SDK graphic — functional icons, form-control glyphs, and capture-critical overlays like camera frames or alignment guides — stays fixed. Recolor those through [CSS tokens](/sdk-reference/web-sdk-2-theming/) instead.

### SVG illustrations (`AssetKey`)

| Key                                | Screen                                    |
| ----------------------------------- | ------------------------------------------ |
| `faceMatch.success`                 | Face match success result                  |
| `faceMatch.fail`                    | Face match failure result                  |
| `documentCapture.tutorial`          | Document capture tutorial illustration     |
| `id.uploadScreen`                   | ID document upload screen                  |
| `id.ageVerification.dob`            | Age verification: date-of-birth step       |
| `id.ageVerification.scan`           | Age verification: scan step                |
| `id.ageVerification.privacy`        | Age verification: privacy step             |
| `videoSelfie.success`               | Video selfie success result                |
| `videoSelfie.fail`                  | Video selfie failure result                |
| `videoSelfie.tutorial.permission`   | Video selfie tutorial: camera permission   |
| `videoSelfie.tutorial.selfie`       | Video selfie tutorial: selfie step         |
| `videoSelfie.tutorial.frontId`      | Video selfie tutorial: front-of-ID step    |
| `videoSelfie.tutorial.backId`       | Video selfie tutorial: back-of-ID step     |
| `videoSelfie.tutorial.poa`          | Video selfie tutorial: proof-of-address    |
| `videoSelfie.tutorial.questions`    | Video selfie tutorial: questions step      |
| `videoSelfie.tutorial.speech`       | Video selfie tutorial: speech step         |
| `loader.spinner`                    | Replaces the default loading spinner (see [The loading spinner](#the-loading-spinner)) |

### Lottie animations (`AnimationKey`)

| Key                   | Screen                                                    |
| ---------------------- | ---------------------------------------------------------- |
| `id.tutorial.front`    | ID capture tutorial: front side                             |
| `id.tutorial.back`     | ID capture tutorial: back side                              |
| `id.tutorial.passport` | ID capture tutorial: passport                                |
| `id.flip`              | ID capture "flip the card" animation                        |
| `id.processing`        | ID analyzing / laser-scan loader                            |
| `selfie.tutorial`      | Selfie capture tutorial                                     |
| `loader.spinner`       | Replaces the default loading spinner (see below)            |

Only assets that are purely decorative or branding graphics are on this list. If a key you need isn't here, it's most likely functional chrome or a capture-critical overlay, and isn't a candidate for override.

## Override forms

### SVG overrides

`AssetOverride` accepts several shapes, so you can pick whichever is least work:

```ts
type AssetOverride =
  | string // a URL, or raw `<svg …>` markup (detected by a leading '<')
  | { url: string } // fetched and rendered via <img>; no script execution
  | { raw: string } // inline markup, sanitized before injection
  | { svg: SvgComponent }; // a precompiled Preact component (build-time integrations)
```

`{ raw }` markup is sanitized before it's injected into the page — scripts, event-handler attributes, `<foreignObject>`, and external `href` / `xlink:href` references are stripped (in-document `#fragment` references used for gradients and filters are preserved). If sanitizing strips everything, the SDK treats the override as failed and falls back to the built-in default.

### Animation overrides

```ts
type AnimationOverride =
  | LottieAnimationData // a parsed Lottie JSON object
  | { url: string } // fetched and cached at runtime
  | { animationData: LottieAnimationData };
```

An animation `{ url }` is fetched once and cached; a failed fetch falls back to the built-in default.

## Per-instance overrides

Every module web component's `config` prop also accepts `assets` and `animations`. This overrides the global `setup({ uiConfig })` values for that one element only — useful when a single flow instance on the page needs different branding than the rest of the app:

```ts
const el = document.createElement('incode-selfie');
el.manager = selfieManager;
el.config = {
  token,
  assets: {
    'videoSelfie.success': 'https://cdn.example.com/id/selfie-done.svg',
  },
};
container.appendChild(el);
```

`<incode-flow>` takes the same two maps on its `FlowConfig`:

```ts
flow.config = {
  token: session.token,
  animations: {
    'loader.spinner': { url: 'https://cdn.example.com/id/spinner.json' },
  },
};
```

If the same key is set both globally and per-instance, the per-instance value wins for that element.

## The loading spinner

The default loading spinner (shown during flow initialization, module loading, and transitions) is CSS + inline SVG, not an asset — it stays fully customizable through the `--spinner-*` CSS tokens described in [Theming & Styling](/sdk-reference/web-sdk-2-theming/#spinner-customization), unaffected by this feature.

`loader.spinner` is a separate, optional override that *replaces* the built-in spinner entirely with your own SVG or Lottie asset. Set it (as an `AssetOverride` for an SVG, or an `AnimationOverride` for a Lottie animation) and the SDK renders your asset instead of the CSS spinner everywhere the spinner appears. Leave it unset and the CSS spinner renders exactly as it does today.

## Accessibility & security

- **Accessible names and `aria-hidden` always come from the SDK's built-in catalog, never from your override.** Replacing an asset's pixels can't remove its accessible name.
- **The WCAG 2.2.2 five-second auto-stop on animations can't be bypassed by an override.** A customer-supplied Lottie animation is still subject to the same auto-stop as the built-in default.
- **Raw SVG markup is sanitized before injection** (see [Override forms](#override-forms) above). Prefer `{ url }` when you control the hosting and don't need inline theming.
- **The SDK never recolors a customer-supplied asset.** Color the asset yourself before handing it to the SDK.

## TypeScript

```ts
import type {
  AssetKey,
  AssetOverride,
  AssetOverrides,
  AnimationKey,
  AnimationOverride,
  AnimationOverrides,
  SvgComponent,
} from '@incodetech/web';
```

The same types are also available from `@incodetech/web/extensibility` if you're already importing shared components/hooks from that subpath.

## See Also

- [Theming & Styling](/sdk-reference/web-sdk-2-theming/): CSS-token recoloring of UI chrome
- [IncodeFlow Component](/sdk-reference/web-sdk-2-incodeflow-component/): full `FlowConfig` reference, including `assets` / `animations`
- [Web Components](/sdk-reference/web-sdk-2-web-components/): setting per-instance `config` on any module element
- [TypeScript Types](/sdk-reference/web-sdk-2-typescript-types/): the full type catalog
