> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerswap.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Swap Widget Quickstart

> Add the Swap Widget to your React app with @layerswap/widget-react — one package, no CSS imports, no bundler config.

The Swap Widget is delivered through **`@layerswap/widget-react`** — a thin React loader that fetches the widget at runtime from Layerswap's signed CDN. The widget code and its heavy dependencies (wallet SDKs, animation and form libraries) **never enter your bundle**: your app installs only the loader, and widget updates roll out automatically without you redeploying.

<Note>
  Need to control the complete bundle? See [Self-bundled Widget](/widget/advanced/self-bundled). Existing self-bundled integrations can follow the [migration guide](/widget/advanced/migrate-to-widget-react).
</Note>

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @layerswap/widget-react
  ```

  ```bash pnpm theme={null}
  pnpm add @layerswap/widget-react
  ```

  ```bash yarn theme={null}
  yarn add @layerswap/widget-react
  ```
</CodeGroup>

`react` and `react-dom` (18 or 19) are the only required peer dependencies. `wagmi` is an **optional, types-only** peer — install it only if you pass a [`wagmiConfig`](/widget/wagmi-config) prop. Everything else the widget needs ships inside the CDN remote.

## Render the widget

```tsx theme={null}
import { LayerswapWidget } from '@layerswap/widget-react';

export function App() {
  return (
    <LayerswapWidget
      config={{ apiKey: 'YOUR_API_KEY', version: 'mainnet' }}
      fallback={<div>Loading widget…</div>}
      onReady={() => console.log('widget mounted')}
      onError={(e) => console.error(e)}
    />
  );
}
```

`YOUR_API_KEY` identifies your app to the Layerswap API. Generate one in the [Partner Dashboard](/get-started/api-keys).

That's the complete minimum integration. Compared with the self-bundled Widget, note what's **not** here:

* **No CSS import** — the widget injects its styles at runtime.
* **No provider wrapper and no wallet provider setup** — the widget builds its wallet providers internally. You can [filter chains or supply credentials](/widget/wallets) via props.
* **No bundler configuration** — no polyfills, no `transpilePackages`, no `next/dynamic`. It works in the Next.js App Router as-is: the component declares `"use client"`, the server renders only `fallback`, and the loader starts after hydration.

## Things to know

<Warning>
  **One widget per page.** The widget keeps process-global state, so only one instance (of either `LayerswapWidget` or `LayerswapDepositWidget`) may be live per page at a time. If you need both, swap between them (e.g. with tabs) instead of rendering both.
</Warning>

<Note>
  **Keep object props referentially stable.** `config`, `callbacks`, `walletDefaults`, and `walletProvidersConfig` are compared by identity. Recreating them causes avoidable provider-list rebuilds and re-renders. Hoist them to module scope or wrap them in `useMemo`.
</Note>

```tsx theme={null}
// Hoisted to module scope — stable across renders
const widgetConfig = { apiKey: 'YOUR_API_KEY', version: 'mainnet' } as const;

const callbacks = {
  onSwapCreate: (swap) => console.log('swap created', swap),
  onSwapComplete: (swap) => console.log('swap complete', swap),
};

export function App() {
  return <LayerswapWidget config={widgetConfig} callbacks={callbacks} />;
}
```

**Layout is controlled by your container.** The widget has no `className`, `style`, or size props — wrap it in a container that constrains its width:

```tsx theme={null}
<div style={{ width: '100%', maxWidth: 512 }}>
  <LayerswapWidget config={widgetConfig} />
</div>
```

## Versioning

Pinning an exact CDN build is not a public API. See [Widget delivery and security](/widget/delivery-and-security) for the delivery and verification pipeline.

## Next steps

<CardGroup cols={2}>
  <Card title="Configuration" icon="gear" href="/widget/configuration">
    The `config` prop — API key, network set, theme, initial values
  </Card>

  <Card title="Widget delivery and security" icon="shield-check" href="/widget/delivery-and-security">
    CDN delivery, manifest signing, CSP, and failure modes
  </Card>

  <Card title="Wallets" icon="wallet" href="/widget/wallets">
    Filter chains, supply WalletConnect/TON credentials, share your wagmi config
  </Card>

  <Card title="Deposit Widget" icon="arrow-down-to-line" href="/widget/deposit-widget">
    Fixed-destination deposit flow with `LayerswapDepositWidget`
  </Card>

  <Card title="Event Callbacks" icon="bell" href="/widget/events/overview">
    React to swap lifecycle events via the `callbacks` prop
  </Card>

  <Card title="Other frameworks" icon="js" href="/widget/vanilla-js">
    Vue, Angular, Svelte, or plain DOM with `@layerswap/widget-js`
  </Card>

  <Card title="Production checklist" icon="list-check" href="/resources/production-checklist">
    Environment, CSP, error handling, release, and monitoring checks
  </Card>
</CardGroup>
