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

# Embed the yield widget

> Install @stakekit/widget 0.0.290, render it with an API key, and configure wallet signing, tracking, theming and the other props.

export const CompactDemo = ({src, title, width = 480, height = 720, caption}) => {
  return <figure style={{
    margin: "24px 0",
    textAlign: "center"
  }}>
      <iframe src={src} title={title} width={width} height={height} allow="clipboard-read; clipboard-write" loading="lazy" style={{
    border: "1px solid rgba(127, 127, 127, 0.25)",
    borderRadius: "16px",
    width: "100%",
    maxWidth: `${width}px`,
    height: `${height}px`,
    display: "block",
    margin: "0 auto"
  }} />
      <figcaption style={{
    marginTop: "8px",
    fontSize: "14px",
    opacity: 0.75
  }}>
        {caption ? `${caption} ` : ""}
        <a href={src} target="_blank" rel="noopener noreferrer">
          Open the demo in a new tab
        </a>
      </figcaption>
    </figure>;
};

The yield widget is a full Earn interface in one package, `@stakekit/widget`. It covers yield discovery, wallet connection, and the enter, exit and manage flows. It calls the Earn API with your project's API key and shows only the yields enabled for that project. See [Discover yields](/guides/earn/discover-yields).

This guide covers the classic layout. For the dashboard layout with Borrow, Manage and Activity tabs, see [Widget Pro](/guides/widgets-dashboard/yield-dashboard). For Perps, see the [Perps widget](/guides/widgets-dashboard/perps-widget).

<CompactDemo src="https://widget.stakek.it/?variant=classic" title="Yield.xyz widget demo" width={480} height={720} caption="The yield widget, classic layout." />

## Prerequisites

* A Yield.xyz API key for the project whose yields you want to show. See [API keys](/documentation/get-started/onboarding#api-keys).
* React 19 or later if you use the React entry point (`SKApp`). The browser renderer (`renderSKWidget`) does not require React on the host page.

<Note>
  The API key ships to the browser in every widget deployment. Read the [security notice](/legal/security-notice) for the risks and how to limit them.
</Note>

## Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @stakekit/widget@0.0.290
  ```

  ```bash pnpm theme={null}
  pnpm add @stakekit/widget@0.0.290
  ```

  ```bash yarn theme={null}
  yarn add @stakekit/widget@0.0.290
  ```
</CodeGroup>

`@stakekit/widget` exposes three entry points: the package root (`SKApp`, for React apps), `./bundle` (`renderSKWidget`, framework-agnostic) and `./style.css` (the stylesheet, required by both). If your app already uses React, the React entry point keeps your bundle smaller.

## React

Import the stylesheet once, then render `SKApp` with your API key:

```tsx theme={null}
import "@stakekit/widget/style.css";
import { darkTheme, SKApp } from "@stakekit/widget";

export const Widget = () => {
  return <SKApp apiKey={YIELD_API_KEY} theme={darkTheme} />;
};
```

### Next.js

Render the widget in a client component and load it without server-side rendering:

<CodeGroup>
  ```tsx app/widget/widget.tsx theme={null}
  "use client";

  import "@stakekit/widget/style.css";
  import { darkTheme, SKApp } from "@stakekit/widget";

  export const Widget = () => {
    return <SKApp apiKey={YIELD_API_KEY} theme={darkTheme} />;
  };
  ```

  ```tsx app/widget/index.tsx theme={null}
  "use client";

  import dynamic from "next/dynamic";

  export default dynamic(() => import("./widget").then((mod) => mod.Widget), {
    ssr: false,
  });
  ```
</CodeGroup>

## Browser renderer

`renderSKWidget` mounts the widget into a container element without React in your app:

```ts theme={null}
import "@stakekit/widget/style.css";
import { darkTheme, renderSKWidget } from "@stakekit/widget/bundle";

const widget = renderSKWidget({
  container: document.querySelector("#widget")!,
  apiKey: YIELD_API_KEY,
  theme: darkTheme,
});

// Later: pass the full set of props again. rerender replaces, it does not merge.
widget.rerender({ apiKey: YIELD_API_KEY, theme: darkTheme });

// When your page removes the widget:
widget.unmount();
```

Only one widget can be mounted on a page at a time. Unmount it before you mount another.

### From a script tag

Without a bundler, load the bundle and its stylesheet from a CDN:

```html theme={null}
<link rel="stylesheet" href="https://unpkg.com/@stakekit/widget@0.0.290/dist/bundle/index.bundle.css" />

<div id="widget"></div>

<script type="module">
  import {
    lightTheme,
    renderSKWidget,
  } from "https://unpkg.com/@stakekit/widget@0.0.290/dist/bundle/index.bundle.js";

  renderSKWidget({
    container: document.getElementById("widget"),
    apiKey: "YOUR_API_KEY",
    theme: lightTheme,
  });
</script>
```

If your page's styles leak into the widget, mount the widget in a container inside a shadow root and pass that container as `portalContainer` so that dialogs and menus also render inside it.

## Wallet and signing

By default the widget renders its own connect-wallet flow and signs with the wallet the user connects. To sign with your own signer, custody provider or embedded wallet instead, pass `externalProviders`:

```tsx theme={null}
<SKApp
  apiKey={YIELD_API_KEY}
  externalProviders={{
    type: "generic",
    currentAddress: address ?? "", // "" while disconnected, never null
    currentChain: chainId,
    supportedChainIds: [1, 8453],
    provider: {
      signMessage: async (message) => yourWallet.signMessage(message),
      switchChain: async (chainId) => yourWallet.switchChain(chainId),
      sendTransaction: async (tx, txMeta) => {
        // Inspect tx before you send it. Never modify it.
        const txHash = await yourWallet.sendTransaction(tx);
        return { type: "success", txHash };
      },
    },
  }}
/>
```

* **`sendTransaction(tx, txMeta)`** signs and broadcasts one transaction. `tx.type` is `evm`, `solana`, `ton`, `tron` or `bittensor`. Once the transaction is broadcast, resolve with `{ type: "success", txHash }`. Resolve with `{ type: "cancelled" }` when the user declines, or `{ type: "error", error }` on failure. A plain hash string also works.
* **`signMessage(message)`** returns the signature string, or the same `success`, `cancelled` or `error` result.
* **`switchChain(chainId)`** resolves once your wallet is on that chain. Update `currentChain` afterward.
* **`currentAddress`** is `""` while the wallet is disconnected. Keep `externalProviders` in place; adding or removing it requires a remount.

The widget constructs each transaction, and your provider signs and sends it. As with direct API use, your provider inspects every transaction before sending it. `txMeta` carries the action type, transaction type, amounts and validators, so you can label the request that your users or approvers see.

To offer Zama confidential vaults with your own wallet, give the provider a `signZamaPermit(typedData, meta)` method (type `SKZamaWallet`). Without it, Zama deposits are blocked. See [Zama](/documentation/earn/defi/vaults/zama).

To add Borrow to the same widget, see the [Borrow widget](/guides/borrow/widget) guide.

## Tracking

Pass `tracking` to receive the widget's analytics events:

```tsx theme={null}
<SKApp
  apiKey={YIELD_API_KEY}
  tracking={{
    trackEvent: (event, properties) => yourAnalytics.track(event, properties),
    trackPageView: (page, properties) => yourAnalytics.page(page, properties),
  }}
/>
```

`trackEvent` fires on interactions such as `"Connect wallet clicked"`, `"Yield selected"`, `"Transaction signed"` and `"Transaction submitted"`. `trackPageView` fires on screens such as `"Earn"`, `"Positions"`, `"Stake review"` and `"Stake complete"`. The `SKTrackEvent` and `SKTrackPage` types list every value.

## Theming

`lightTheme` and `darkTheme` are the built-in themes. Pass a partial theme as `theme`: it is deep-merged over the light theme, so you set only the tokens you change.

```tsx theme={null}
import "@stakekit/widget/style.css";
import { darkTheme, SKApp } from "@stakekit/widget";

<SKApp
  apiKey={YIELD_API_KEY}
  theme={{
    ...darkTheme,
    font: { body: '"IBM Plex Mono", monospace' },
    color: {
      ...darkTheme.color,
      primaryButtonBackground: "#8323fd",
      primaryButtonColor: "#ffffff",
    },
    borderRadius: {
      baseContract: { ...darkTheme.borderRadius?.baseContract, primaryButton: "0", widgetBorderRadius: "10px" },
    },
  }}
/>;
```

To follow the user's light or dark preference, choose `lightTheme` or `darkTheme` based on `prefers-color-scheme` in your app and pass it as `theme`.

<Accordion title="Theme tokens">
  Every token is a CSS value string. All groups are optional.

  | Group | Tokens |
  | - | - |
  | `color` | `white`, `transparent`, `primary`, `accent`, `disabled`, `text`, `textMuted`, `textDanger`, `statusSuccess`, `statusWarning`, `background`, `backgroundMuted`, `tokenSelectBackground`, `tokenSelectHoverBackground`, `tokenSelectBorder`, `tokenSelect`, `skeletonLoaderBase`, `skeletonLoaderHighlight`, `tabBorder`, `stakeSectionBackground`, `dropdownBackground`, `selectValidatorMultiSelectedBackground`, `selectValidatorMultiDefaultBackground`, `warningBoxBackground`, `errorBoxBackground`, `positionsClaimRewardsBackground`, `positionsActionRequiredBackground`, `positionsPendingBackground`, `positionsRewardRate`, `modalOverlayBackground`, `modalBodyBackground`, `tooltipBackground`, `primaryButtonColor`, `primaryButtonBackground`, `secondaryButtonColor`, `secondaryButtonBackground`, `smallButtonColor`, `smallButtonBackground`, `smallLightButtonColor`, `smallLightButtonBackground`, `disabledButtonColor`, `disabledButtonBackground`, `dashboardDetailsSectionBackground`, `summaryItemBackground`, `summaryLabelStakedBackground`, `summaryLabelStakedColor`, `summaryLabelApyBackground`, `summaryLabelApyColor`, `summaryLabelAvailableBackground`, `summaryLabelAvailableColor` |
  | `font` | `body` |
  | `fontSize` | `xs`, `sm`, `md`, `lg`, `lgx`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl` |
  | `fontWeight` | `normal`, `medium`, `semibold`, `bold`, `extrabold`, `modalHeading`, `tokenSelect`, `primaryButton`, `secondaryButton` |
  | `letterSpacing` | `tighter`, `tight`, `normal`, `wide`, `wider`, `widest` |
  | `lineHeight` | `none`, `shorter`, `short`, `base`, `tall`, `taller`, `xs`, `sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`, `6xl` |
  | `borderRadius.baseContract` | `none`, `sm`, `base`, `md`, `lg`, `xl`, `2xl`, `3xl`, `full`, `half`, `widgetBorderRadius`, `primaryButton`, `secondaryButton`, `smallButton` |
  | `space` | `0` to `10`, `12`, `14`, `16`, `20`, `24`, `28`, `32`, `36`, `40`, `44`, `48`, `px`, `full`, `unset`, `auto`, `buttonMinHeight` |
  | `heading` | `h1` to `h4`, each with `mobile.fontSize` and `tablet.fontSize` |
  | `text` | `large`, `medium`, `small`, each with `mobile.fontSize` and `tablet.fontSize` |
  | `zIndices` | `hide`, `auto`, `simple`, `base`, `docked`, `dropdown`, `sticky`, `banner`, `overlay`, `modal`, `skipLink` |

  The `connectKit` color and radius groups were removed in 0.0.290. Remove them from your theme if you set them.
</Accordion>

## Configuration reference

Every prop below is optional except `apiKey`. Props marked **Mount** are read when the widget mounts; remount it to change them. The rest update live.

<Accordion title="All props">
  | Prop | What it does |
  | - | - |
  | `apiKey` | Your project API key. **Mount.** |
  | `theme` | Theme tokens, deep-merged over the light theme. |
  | `tracking` | `trackEvent` and `trackPageView` callbacks. |
  | `externalProviders` | Your own wallet adapter. Its presence is fixed at mount; address, chain and callbacks update live. |
  | `language` | `"en"` or `"fr"`. Defaults to the browser language, then English. |
  | `customTranslations` | Translation overrides per language, as `{ en: { translation: { ... } } }`. |
  | `walletPolicy` | Filters, orders and groups the built-in wallet list by wallet id: `allow`, `deny`, `order`, `groups` and `groupOrder`. **Mount.** |
  | `mapWalletFn` | Changes a wallet's name, icon or icon background in the wallet list. **Mount.** |
  | `institutionalWallets` | Offers institutional wallets instead of the regular wallet list. **Mount.** |
  | `isSafe` | Runs inside a Safe app and connects through the Safe wallet. **Mount.** |
  | `disableInjectedProviderDiscovery` | Ignores injected EVM wallets announced through EIP-6963. **Mount.** |
  | `tonConnectManifestUrl` | Your TON Connect manifest URL. **Mount.** |
  | `initialChain` | Chain to request when the user connects a wallet. |
  | `preferredTokenYieldsPerNetwork` | The yield to preselect for a token, as `{ [network]: { "network-tokenAddress": yieldId } }`. |
  | `validatorsConfig` | Validator rules per network id, or `"*"` for every network: `allowed`, `blocked`, `preferred`, `mergePreferredWithDefault` (default `true`) and `preferredOnly` (default `false`). |
  | `tokenIconMapping` | Token icon URLs by symbol, or a function that returns one. |
  | `chainIconMapping` | Network icon URLs by network id, or a function that returns one. |
  | `hideNetworkLogo` | Hides the network badge on token icons. |
  | `hideChainSelector` | Hides the chain selector in the header. |
  | `dashboardVariant` | Switches to the dashboard layout. See [Widget Pro](/guides/widgets-dashboard/yield-dashboard). |
  | `dashboardYieldCategoryOrder` | Order of yield categories in the dashboard. |
  | `yieldGrouping` | `"flat"` or `"category"`. Defaults to `"category"` with `dashboardVariant`, otherwise `"flat"`. |
  | `hideAccountAndChainSelector` | Hides the account and chain selector in the dashboard header. |
  | `borrowEnabled`, `borrowMarketsScope`, `borrowApiUrl` | Borrow settings. See the [Borrow widget](/guides/borrow/widget) guide. |
  | `portalContainer` | Element that hosts the widget's dialogs, menus and tooltips. |
  | `onMountAnimationComplete` | Called once the first mount animation finishes. |
  | `disableInitLayoutAnimation` | Skips the first layout and reveal animation. |
  | `disableResizingInputFontSize` | Keeps the amount input font size fixed for long values. |
  | `disableAutoScrollToTop` | Stops the widget from scrolling the window to the top on navigation. |
  | `baseUrl`, `yieldsApiUrl` | API endpoints. Leave unset to use the production APIs. **Mount.** |
  | `variant` | Partner layout presets set up with Yield.xyz. Leave unset. |
</Accordion>

The package exports the chain id constants (`EvmChainIds`, `MiscChainIds`, `SubstrateChainIds`), `DashboardYieldCategory`, the themes, and a named type for every prop. Import them rather than copying their shapes.

## Upgrading to 0.0.290

<Accordion title="Changes that can affect an existing integration">
  * **React 19.** The `react` and `react-dom` peers are `>=19`.
  * **Wallet dialogs.** RainbowKit is replaced by the widget's own connect, account and chain dialogs and its own WalletConnect. Existing Tron, Cosmos and Polkadot WalletConnect sessions reconnect once after the update.
  * **Removed:** `forceWalletConnectOnly`, the `color.connectKit` and `borderRadius.connectKit` theme groups, `wagmi.__customConnectors__` and `mapWalletListFn` (use `walletPolicy`), `disableGasCheck`, and the `createWallet`, `evmChainGroup` and `TrackingContextProvider` exports.
  * **Adapter results.** `sendTransaction` and `signMessage` can resolve `{ type: "cancelled" }` when the user declines; the widget shows a retryable notice.
  * **Browser renderer.** `renderSKWidget` returns `{ rerender, unmount }`.
  * **Deprecated, no effect:** `tokensForEnabledYieldsOnly` and `externalProviders.supportsBorrow`. Remove them.
</Accordion>

## Verify

Run your app and confirm three things. The widget loads your project's yields, matching what `GET /v1/yields` returns for the same API key. Connecting a wallet, or passing `externalProviders`, shows a balance. A transaction signs and settles as described in [Enter and exit flows](/guides/earn/enter-exit-flows).

## Next steps

<Columns cols={2}>
  <Card title="Widget Pro" icon="gauge" href="/guides/widgets-dashboard/yield-dashboard">
    The dashboard layout of the same widget, with Borrow, Manage and Activity tabs.
  </Card>

  <Card title="Borrow widget" icon="window-maximize" href="/guides/borrow/widget">
    Turn on Borrow in the widget.
  </Card>

  <Card title="Enter and exit flows" icon="arrow-right-arrow-left" href="/guides/earn/enter-exit-flows">
    What the widget's enter, exit and manage flows do at the API level.
  </Card>

  <Card title="Discover yields" icon="magnifying-glass" href="/guides/earn/discover-yields">
    Confirm which yields your project's API key exposes.
  </Card>
</Columns>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.