---
title: "Requirements"
description: "The browser support matrix, cross-origin isolation prerequisites, and backend services needed to integrate the Wavelength SDK."
canonical: https://wavelength.lightning.engineering/web/get-started/requirements/
---

> Docs index: https://wavelength.lightning.engineering/llms.txt

# Requirements

## Browser support

Wavelength runs the full wallet daemon in the browser as WebAssembly. Target browsers with mature WASM, Web Worker, and storage APIs:

| Browser                              | Minimum version |
| ------------------------------------ | --------------- |
| Chrome (and Chromium-based browsers) | 100+            |
| Firefox                              | 110+            |
| Safari (macOS and iOS)               | 16+             |

Node.js 20 or later is recommended for local development (Vite, Next.js, and similar bundlers). No special build plugins are required beyond serving the WASM runtime assets and, for worker mode, setting cross-origin isolation headers.

Passkey support (WebAuthn with PRF) is optional and depends on the browser and OS. Password-based wallets work everywhere in the matrix above.

## Cross-origin isolation

The default transport runs the daemon in a dedicated Web Worker and persists wallet state with OPFS-backed SQLite. Both paths rely on `SharedArrayBuffer`, which browsers only expose on **cross-origin isolated** pages.

Your app must send `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` response headers on every route that loads the wallet. See [Cross-origin isolation](/web/get-started/cross-origin-isolation/) for the exact values and a quick verification command.

If you cannot isolate the page (for example, because third-party embeds block `require-corp`), you can run the runtime on the main thread with `createWebClient({ runtimeThread: 'main' })`, but OPFS persistence will not be available and the UI thread will block while the daemon is busy. See [Data & persistence](/web/runtime/data-and-persistence/) for how storage behavior differs between main-thread and worker mode.

## Backends

Wavelength is self-custodial: the seed never leaves the browser. The embedded daemon still needs reachable **Ark**, **Esplora**, and (for Lightning swaps) **swap server** endpoints at runtime.

**Signet (recommended for development)** works out of the box with the public preset. Pass `defaultConfig('signet')` to `start()` and the client connects to Lightning Labs hosted gateways:

```ts
import { createWebClient, defaultConfig } from '@lightninglabs/wavelength-web';

const client = createWebClient();
await client.start(defaultConfig('signet'));
```

Presets also exist for `testnet`. No local backend is required for any hosted network.

**Regtest (local development)** targets services you run yourself, so there is no `defaultConfig` preset for it; local ports vary per machine, and the URLs are the whole point of a preset. Start [arktest](https://github.com/lightninglabs/wavelength), note the ports it prints, and build the config by hand, including the insecure-transport flags for plain-HTTP local gateways:

```ts
import type { RuntimeConfig } from '@lightninglabs/wavelength-web';

const config: RuntimeConfig = {
  network: 'regtest',
  arkServerAddress: 'http://127.0.0.1:7071',
  walletEsploraUrl: 'http://127.0.0.1:8501',
  swapServerAddress: 'http://127.0.0.1:10032',
  arkServerInsecure: true,
  swapServerInsecure: true,
};

await client.start(config);
```

**Mainnet** has no public preset yet, so like regtest there is no `defaultConfig` for it. Build the config by hand with your own gateway URLs and set `allowMainnet: true` before going live:

```ts
await client.start({
  network: 'mainnet',
  arkServerAddress: 'https://your-ark-server.example.com',
  walletEsploraUrl: 'https://your-esplora.example.com/api',
  swapServerAddress: 'https://your-swap-server.example.com',
  allowMainnet: true,
});
```

On web, `arkServerAddress` and `swapServerAddress` must be REST URLs. `walletEsploraUrl` is an HTTP Esplora endpoint. The web transport always rejects `arkServerTlsCertPath`. It accepts `swapServerTlsCertPath` only when `disableSwaps: true`, which suppresses every swap field.

Mainnet access is gated to an approved allowlist. See [Mainnet access](/concepts/networks-and-config/#mainnet-access) for how to request it with your client’s `identity_pubkey`.
