<script>
	import WidgetExamples from '$components/blocks/WidgetExamples.svelte';
	import WidgetsMobile from '$components/blocks/WidgetsMobile.svelte';
</script>

# Widget Integration

Integrating ALTCHA into your website or web app is straightforward and can be done within minutes.

The widget performs the user verification by computing the proof-of-work challenge and when used with the [ALTCHA Sentinel](/docs/sentinel/), it also provides necessary UI for the optional code challenge.

## Installation via NPM

Install the package:

```bash
npm install altcha
```

Import it into your project:

```js
// form.js
import "altcha";
```

## Alternatively, download the script

Download the ALTCHA script from [GitHub](https://github.com/altcha-org/altcha) or use the CDN:

```
https://cdn.jsdelivr.net/gh/altcha-org/altcha/dist/main/altcha.min.js
```

To integrate the widget, add the script to your website:

```html
// form.html
<script async defer src="/altcha.js" type="module"></script>
```

For optimal integration, place the script tag within the `<head>` section.

## Examples

<WidgetExamples />

## Mobile

<WidgetsMobile />

## Using `<altcha-widget>`

The ALTCHA widget functions as a [Web Component](https://developer.mozilla.org/en-US/docs/Web/API/Web_components) and utilizes the browser's internal capabilities to register a new tag `<altcha-widget>`. Integrate this tag within your forms:

```html
// form.html
<altcha-widget challenge="{YOUR_SERVER_HERE}"></altcha-widget>
```

Configure the `challenge` with your server's address.

## Usage with ALTCHA Sentinel

When using [ALTCHA Sentinel](/docs/sentinel/) for challenge generation, configure the widget with your Sentinel endpoint URL:

```html
<altcha-widget
challenge="https://sentinel.example.com/v1/challenge?apiKey=key_..."
></altcha-widget>
```

Where to find these values:

1. **Endpoint URL**: This is your Sentinel instance's base URL with `/v1/challenge` path
2. **API Key**: A unique key authenticating your application with Sentinel

Both values are available in your Sentinel app.

## Internationalization (i18n)

ALTCHA supports **50+ languages**, allowing you to deliver a localized experience to your users. Set the `language` attribute (or the `language` option via `.configure()`) to the ISO alpha-2 code you need — see [Core Settings](#core-settings) above.

## Themes and Customization

Customize the widget’s appearance to match your UI and branding using the `theme` attribute — see [UI & Display](#ui--display) above.

## Content Security Policy (CSP)

The default Web Component bundle includes styles and a Web Worker in a single file. If you are using a strict CSP, additional configuration may be required to allow the bundled worker and styles to load.

## Configuration

### Programmatic Configuration

The widget provides a global `$altcha` object to manage defaults, register new algorithms, or add custom translations.

To update an existing widget instance, use the `.configure()` [method](). This is the preferred way to handle complex objects or functions that cannot be passed via HTML attributes.

```ts
// Set defaults for all future widget instances:
$altcha.defaults.set({
	challenge: 'https://api.example.com/challenge',
	debug: true
});

// Update a specific instance dynamically:
const widget = document.querySelector('altcha-widget');
widget.configure({
	workers: 2,
	language: 'fr'
});
```

### Attribute Configuration

For simple implementations, the widget supports a subset of configuration options directly as HTML attributes. For more advanced properties, use the programmatic approach above.

**Supported Attributes:**

```html
<altcha-widget
	auto="off"
	challenge="https://api.example.com/challenge"
	configuration='{"delay": 500}'
	display="standard"
	language="en"
	name="altcha"
	theme="default"
	type="checkbox"
	workers="4"
></altcha-widget>
```

The `configuration` attribute accepts a JSON-encoded string, allowing you to pass complex settings directly in your HTML markup.

### Core Settings

- **`name`**: The `name` attribute of the hidden input field containing the payload. (Default: `"altcha"`)
- **`challenge`**: The challenge data or the URL to fetch a new challenge from.
- **`type`**: Visual style of the interaction element (`'native'`, `'checkbox'`, or `'switch'`).
- **`language`**: The ISO alpha-2 language code for localization (requires corresponding i18n file).
- **`workers`**: The number of Web Workers to spawn for proof-of-work calculations.

### Automation & Timing

- **`auto`**: Determines when verification triggers automatically (`'off'`, `'onfocus'`, `'onload'`, or `'onsubmit'`).
- **`minDuration`**: The minimum verification time in milliseconds; adds an artificial delay if the PoW is faster. (Default: `500`)
- **`retryOnOutOfMemoryError`**: Automatically attempts to restart verification with fewer workers if the browser runs out of memory (Argon2 and Scrypt only).

### UI & Display

- **`display`**: The visual layout mode (`'standard'`, `'bar'`, `'floating'`, `'overlay'`, or `'invisible'`).
- **`barPlacement`**: Vertical position of the widget when `display` is set to `bar` (`'bottom'` or `'top'`).
- **`hideLogo`**: Hides the ALTCHA logo icon.
- **`hideFooter`**: Hides the "ALTCHA" attribution link.
- **`validationMessage`**: Custom validation message for the HTML5 `setCustomValidity` API.

### Floating Widget Settings

- **`floatingAnchor`**: The element or CSS selector the floating UI attaches to. Defaults to the first submit button.
- **`floatingPlacement`**: Preferred position relative to the anchor (`'auto'`, `'bottom'`, or `'top'`).
- **`floatingOffset`**: Vertical offset in pixels between the UI and its anchor. (Default: `12`)
- **`floatingPersist`**: Whether the floating widget remains visible after successful verification.
- **`popoverPlacement`**: Preferred position of popovers relative to the widget (`'auto'`, `'bottom'`, or `'top'`).

### Modal & Challenge Settings

- **`codeChallengeDisplay`**: UI layout for the code-challenge modal (`'standard'`, `'overlay'`, or `'bottomsheet'`).
- **`overlayContent`**: CSS selector for an element to be mirrored inside the overlay modal.
- **`audioChallengeLanguage`**: Forces a specific language for audio-based challenges.
- **`disableAutoFocus`**: Prevents the code-challenge modal from stealing focus when opened.

### Advanced & Debugging

- **`debug`**: Enables verbose logging in the browser console.
- **`test`**: Mocks a successful verification for testing environments.
- **`mockError`**: Forces the widget into a failed state for UI testing.
- **`fetch`**: A custom `fetch` implementation for network requests.
- **`humanInteractionSignature`**: Whether the collector for HIS is enabled (Default: `true`).
- **`setCookie`**: When configured, sends the payload as a cookie.
- **`timeout`**: Verification timeout in milliseconds (Default: `90_000`).
- **`verifyFunction`**: A custom verification handler that overrides default network verification.

## Algorithms

ALTCHA supports multiple proof-of-work algorithms. `PBKDF2/*` and `SHA-*` are bundled with the main widget by default. `Argon2` and `Scrypt` are memory-bound algorithms that resist hardware acceleration (ASICs/GPUs) but require importing their workers separately.

**Supported algorithms:**

- `PBKDF2/SHA-256` (default, bundled)
- `PBKDF2/SHA-384` (bundled)
- `PBKDF2/SHA-512` (bundled)
- `SHA-256` (bundled)
- `SHA-384` (bundled)
- `SHA-512` (bundled)
- `ARGON2ID` (requires separate worker import)
- `SCRYPT` (requires separate worker import)

If you use `Argon2` or `Scrypt`, import their workers and register them via the `$altcha.algorithms` global before the widget initializes.

### Adding Argon2 / Scrypt Workers (Vite)

Works with both `altcha` and `altcha/external`:

```ts
import 'altcha'; // or 'altcha/external'
import Argon2idWorker from 'altcha/workers/argon2id?worker';
import ScryptWorker from 'altcha/workers/scrypt?worker';

$altcha.algorithms.set('ARGON2ID', () => new Argon2idWorker());
$altcha.algorithms.set('SCRYPT', () => new ScryptWorker());
```

### Without Bundler Worker Import Support

If your environment does not support `?worker` imports, load the prebuilt worker files directly:

```ts
import 'altcha';

$altcha.algorithms.set('ARGON2ID', () => new Worker('/path/to/node_modules/altcha/dist/workers/argon2id.js'));
$altcha.algorithms.set('SCRYPT', () => new Worker('/path/to/node_modules/altcha/dist/workers/scrypt.js'));
```

### Using `altcha/external`

`altcha/external` excludes all bundled workers, requiring you to register every algorithm explicitly. Use this for full control over which workers are loaded:

```ts
import 'altcha/external';
import Argon2idWorker from 'altcha/workers/argon2id?worker';
import Pbkdf2Worker from 'altcha/workers/pbkdf2?worker';
import ScryptWorker from 'altcha/workers/scrypt?worker';
import ShaWorker from 'altcha/workers/sha?worker';

$altcha.algorithms.set('PBKDF2/SHA-256', () => new Pbkdf2Worker());
$altcha.algorithms.set('PBKDF2/SHA-384', () => new Pbkdf2Worker());
$altcha.algorithms.set('PBKDF2/SHA-512', () => new Pbkdf2Worker());
$altcha.algorithms.set('SHA-256', () => new ShaWorker());
$altcha.algorithms.set('SHA-384', () => new ShaWorker());
$altcha.algorithms.set('SHA-512', () => new ShaWorker());
$altcha.algorithms.set('ARGON2ID', () => new Argon2idWorker());
$altcha.algorithms.set('SCRYPT', () => new ScryptWorker());
```

## Cookies

By default, the widget sends the ALTCHA payload as a form field by creating a hidden input. It can also be configured to send the payload via a cookie.

To enable this behavior, use the `setCookie` configuration option:

```ts
widget.configure({
	setCookie: {
		name: 'altcha',
		path: '/'
	}
});
```

`setCookie` accepts the following cookie options:

```ts
interface SetCookieOptions {
	domain?: string;
	name?: string;
	maxAge?: number;
	path?: string;
	sameSite?: string;
	secure?: boolean;
}
```

## Methods

- `configure(options)` - Configures the widget with the given options. See Configuration options above.
- `getConfiguration()` - Returns the current configuration.
- `getState()` - Returns the current `state` of the widget.
- `show()` - Displays the widget (used in some display modes).
- `hide()` - Hides the widget (used in some display modes).
- `reset(state?, err?)` - Resets the internal `state`, optionally with an error.
- `setState(state, err?)` - Manually sets the specified `state`, optionally with an error.
- `updateUI()` - Force UI update or reposition, for example for the floating display mode.
- `verify()` - Initiates the verification process.

## Events

- **codechallenge** - Triggers when code-challenge verification is requested.
- **expired** - Triggers when the challenge expires.
- **load** - Triggers when the widget loads. The exported methods become available after this event.
- **outofmemory** - Triggers when an Out-Of-Memory error is received (Argon2 and Scrypt only).
- **serververification** -Triggers upon a server verification.
- **statechange** - Triggers whenever an internal `state` changes.
- **verified** - Triggers when the challenge is verified.

```ts
enum State {
	CODE = 'code',
	ERROR = 'error',
	VERIFIED = 'verified',
	VERIFYING = 'verifying',
	UNVERIFIED = 'unverified',
	EXPIRED = 'expired'
}
```

Using events:

```js
const widget = document.querySelector('altcha-widget');
widget.addEventListener('statechange', (ev) => {
	// See enum State above
	console.log('state:', ev.detail.state);
});
```

Both programmatic configuration and event listeners have to called/attached after the ALTCHA script loads, such as within `window.addEventListener('load', ...)`.

## Caveats

- **Secure context requirement**

The widget utilizes the browser's built-in [subtle.crypto](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto) interface to compute solutions securely. It's essential to note that this cryptographic interface is exclusively available in a [secure context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts), commonly implemented through HTTPS.

The widget necessitates a secure HTTPS connection to operate. Websites served over insecure HTTP connections will not support the widget's functionality due to the absence of the required cryptographic interface. To ensure seamless widget operation, always serve your website securely via HTTPS.

- **JavaScript dependency**

The widget operates with JavaScript and relies on its execution environment to perform computation and submission functions. Consequently, JavaScript-enabled browsers are a prerequisite for users to interact successfully with the widget.

When integrating the widget into website forms, consider that users without JavaScript enabled in their browsers will be unable to utilize or submit forms protected by the widget. Ensure your audience is aware of this requirement for seamless form submission.

## Having Troubles?

- See the [troubleshooting guide](/docs/integration/troubleshooting/).
