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

# How to Embed a Swap Widget in Your App

> Add a full-featured token swap to your app with one script tag. No RPC, no wallet infrastructure, no UI to build.

## TL;DR

Jupiter Plugin gives you the same swap experience as [jup.ag](https://jup.ag), embedded directly in your app. One script tag, one function call. No RPC node, no wallet adapter code, no UI to build. Powered by [Ultra](/ultra/index), which handles routing, slippage, MEV protection, and transaction sending.

<Tip>
  **Video walkthrough + source code:** Watch the [video walkthrough](https://x.com/JupDevRel/status/2033528378134028756) and grab the [demo app source code](https://github.com/jup-ag/api-examples/tree/main/apps/plugin-community-site) on GitHub.
</Tip>

***

## Prerequisites

No API key or RPC node required. Jupiter Plugin handles all infrastructure.

For framework-based apps, you need **Node.js and npm** installed from [nodejs.org](https://nodejs.org). For plain HTML, you just need a browser.

***

## Quick start

The simplest way to add a swap widget: a single HTML file:

```html theme={null}
<!DOCTYPE html>
<html>
<head>
  <script src="https://plugin.jup.ag/plugin-v1.js" data-preload defer></script>
</head>
<body>
  <h1>My App</h1>
  <div id="jupiter-plugin"></div>
  <script>
    window.onload = function() {
      window.Jupiter.init({
        displayMode: "integrated",
        integratedTargetId: "jupiter-plugin",
      });
    };
  </script>
</body>
</html>
```

Save this as `swap.html`, serve it locally, and open it in your browser:

```bash theme={null}
npx http-server -o /swap.html
```

## Try it yourself

Not ready to write code? The [Plugin Playground](https://plugin.jup.ag/) lets you experience the full swap widget live in your browser. Switch display modes, set token defaults, tweak colours, and copy the generated code when you're ready to integrate.

<Frame>
  <a href="https://plugin.jup.ag/" target="_blank" rel="noopener noreferrer" style={{ display: 'block' }}>
    <img
      src="https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=ef4ff667cff780774d3da617a9022a3b"
      alt="Plugin Playground"
      noZoom
      style={{
    cursor: 'pointer',
    transition: 'opacity 0.2s ease-in-out, border 0.2s ease-in-out',
    border: '2px solid transparent',
    borderRadius: '10px'
  }}
      onMouseEnter={(e) => {
    e.target.style.opacity = '1';
    e.target.style.border = '2px solid #C8F284';
  }}
      onMouseLeave={(e) => {
    e.target.style.opacity = '1';
    e.target.style.border = '2px solid transparent';
  }}
      data-og-width="3546"
      width="3546"
      data-og-height="2052"
      height="2052"
      data-path="static/images/plugin-playground.png"
      data-optimize="true"
      data-opv="3"
      srcset="https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=280&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=8395349bbf7f758ca18591330ca87fc7 280w, https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=560&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=46e08b413d1673216c5a1c4d57126c91 560w, https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=840&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=2914dd9f251c0f3df220e1a31e04f63c 840w, https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=1100&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=9d4185743a5a3991ac7e595443788fc8 1100w, https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=1650&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=a7ebc84c3d7e2d259f20c50d8fb2cb13 1650w, https://mintcdn.com/jupiter/mrenEfoqnubhOTHf/static/images/plugin-playground.png?w=2500&fit=max&auto=format&n=mrenEfoqnubhOTHf&q=85&s=ce6b355f81e4a7e0d9e69945e8c0a5a7 2500w"
    />
  </a>
</Frame>

***

## When you need this

You want to add swap functionality to your app or website without building any of it yourself:

* **App with swap:** Your app needs token swaps but you don't want to build the UI, handle transactions, or run an RPC node.
* **Community token site:** Let your community buy your token directly on your website by locking the output mint with `fixedMint`.
* **Quick swap access:** Add a floating widget to any page for convenient swapping.

Common searches that lead here:

* "embed swap widget solana"
* "add token swap to my website"
* "jupiter plugin integration"
* "buy token widget solana"
* "solana swap widget no backend"
* "drop-in swap component solana"
* "add jupiter swap to react app"
* "token swap widget html"

***

## Why Jupiter Plugin

Building a swap interface from scratch means:

* Running an RPC node
* Integrating a wallet adapter
* Building the swap UI
* Handling quoting, routing, slippage, and MEV protection
* Managing transaction errors and retries

Jupiter Plugin handles all of this. You get the full [jup.ag](https://jup.ag) swap experience as a drop-in component:

* **No RPC:** Powered by Ultra, which handles all transaction sending.
* **No wallet code:** Plugin provides wallet connection out of the box (users connect their existing browser wallet like Phantom or Backpack).
* **No UI to build:** Complete swap interface with token search, price display, and transaction status.
* **No error handling:** Plugin manages slippage, retries, and transaction failures.

***

## Code examples

Add the plugin script to your page, then call `window.Jupiter.init()`. Here's a complete working example for each framework:

<CodeGroup>
  ```html HTML theme={null}
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Jupiter Plugin Demo</title>
      <script src="https://plugin.jup.ag/plugin-v1.js" data-preload defer></script>
  </head>
  <body>
      <h1>Jupiter Plugin Demo</h1>
      <div id="jupiter-plugin"></div>

      <script>
          window.onload = function() {
              window.Jupiter.init({
                  displayMode: "integrated",
                  integratedTargetId: "jupiter-plugin",
              });
          };
      </script>
  </body>
  </html>
  ```

  ```tsx React theme={null}
  import { useEffect } from "react";

  // Add to public/index.html <head>:
  // <script src="https://plugin.jup.ag/plugin-v1.js" data-preload defer></script>

  export default function App() {
    useEffect(() => {
      window.Jupiter.init({
        displayMode: "integrated",
        integratedTargetId: "jupiter-plugin",
      });
    }, []);

    return (
      <div>
        <h1>Jupiter Plugin Demo</h1>
        <div id="jupiter-plugin" />
      </div>
    );
  }
  ```

  ```tsx Next.js theme={null}
  "use client";
  import { useEffect } from "react";
  import Script from "next/script";

  export default function SwapPage() {
    return (
      <>
        <Script
          src="https://plugin.jup.ag/plugin-v1.js"
          data-preload
          strategy="afterInteractive"
          onReady={() => {
            window.Jupiter.init({
              displayMode: "integrated",
              integratedTargetId: "jupiter-plugin",
            });
          }}
        />
        <h1>Jupiter Plugin Demo</h1>
        <div id="jupiter-plugin" />
      </>
    );
  }
  ```
</CodeGroup>

For a full step-by-step walkthrough with TypeScript support and project setup:

<CardGroup cols={3}>
  <Card href="/tool-kits/plugin/nextjs-app-example" icon="N" horizontal title="Next.js" />

  <Card href="/tool-kits/plugin/react-app-example" icon="react" horizontal title="React" />

  <Card href="/tool-kits/plugin/html-app-example" icon="html5" horizontal title="HTML" />
</CardGroup>

***

## Configuration

### Display modes

Jupiter Plugin offers three display modes:

| Mode         | Description                                 | Use case                              |
| ------------ | ------------------------------------------- | ------------------------------------- |
| `integrated` | Embeds directly in your page layout         | Dedicated swap page or section        |
| `widget`     | Floating button that expands to a swap form | Quick access on any page              |
| `modal`      | Popup overlay triggered by your app         | On-demand swap without layout changes |

```javascript theme={null}
// Integrated: renders inside a target element
window.Jupiter.init({
  displayMode: "integrated",
  integratedTargetId: "jupiter-plugin", // ID of your container div
});

// Widget: floating in a corner
window.Jupiter.init({
  displayMode: "widget",
  widgetStyle: {
    position: "bottom-right", // bottom-left, bottom-right, top-left, top-right
    size: "default",          // sm, default
  },
});

// Modal: popup overlay
window.Jupiter.init({
  displayMode: "modal",
});
```

### Form props

Pre-configure the swap form with `formProps`:

```javascript theme={null}
window.Jupiter.init({
  displayMode: "integrated",
  integratedTargetId: "jupiter-plugin",
  formProps: {
    initialInputMint: "So11111111111111111111111111111111111111112",  // SOL
    initialOutputMint: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", // JUP
    initialAmount: "1",
    fixedMint: "JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN", // Lock output to JUP
    fixedAmount: false,
  },
});
```

| Prop                | Type      | Description                                              |
| ------------------- | --------- | -------------------------------------------------------- |
| `initialInputMint`  | `string`  | Pre-select the input token (mint address)                |
| `initialOutputMint` | `string`  | Pre-select the output token (mint address)               |
| `initialAmount`     | `string`  | Pre-fill the swap amount                                 |
| `fixedMint`         | `string`  | Lock one side of the swap to a specific token            |
| `fixedAmount`       | `boolean` | Prevent users from changing the amount                   |
| `swapMode`          | `string`  | `"ExactIn"`, `"ExactOut"`, or `"ExactInOrOut"` (default) |

**Community token site example:** Let your community buy your token directly:

```javascript theme={null}
window.Jupiter.init({
  displayMode: "integrated",
  integratedTargetId: "jupiter-plugin",
  formProps: {
    initialOutputMint: "YOUR_TOKEN_MINT_ADDRESS",
    fixedMint: "YOUR_TOKEN_MINT_ADDRESS",
  },
});
```

### Wallet passthrough

If your app already has a wallet provider (e.g. via `@solana/wallet-adapter`), you can pass the wallet state through to Plugin instead of having users connect twice:

```javascript theme={null}
window.Jupiter.init({
  displayMode: "integrated",
  integratedTargetId: "jupiter-plugin",
  enableWalletPassthrough: true,
});

// Sync wallet state when it changes
window.Jupiter.syncProps({
  passthroughWalletContextState: walletContextState,
});
```

If you don't enable passthrough, Plugin provides its own wallet connection. Users connect their browser wallet (Phantom, Backpack, etc.) directly through the widget.

### Referral fees

Earn fees on swaps through the [Jupiter Referral Program](/tool-kits/referral-program):

```javascript theme={null}
window.Jupiter.init({
  displayMode: "widget",
  formProps: {
    referralAccount: "YOUR_REFERRAL_ACCOUNT",
    referralFee: 50, // Basis points (50 = 0.5%)
  },
});
```

### Branding

Add your logo and name to the Plugin:

```javascript theme={null}
window.Jupiter.init({
  displayMode: "widget",
  branding: {
    logoUri: "https://your-app.com/logo.png",
    name: "Your App",
  },
});
```

### Colour theme

Customise colours via CSS variables in your global stylesheet:

```css theme={null}
:root {
  --jupiter-plugin-primary: 199, 242, 132;
  --jupiter-plugin-background: 0, 0, 0;
  --jupiter-plugin-primaryText: 232, 249, 255;
  --jupiter-plugin-warning: 251, 191, 36;
  --jupiter-plugin-interactive: 33, 42, 54;
  --jupiter-plugin-module: 16, 23, 31;
}
```

### Event handling

Track swap results in your app:

```javascript theme={null}
window.Jupiter.init({
  displayMode: "widget",
  onSuccess: ({ txid, swapResult, quoteResponseMeta }) => {
    console.log("Swap successful:", txid);
  },
  onSwapError: ({ error, quoteResponseMeta }) => {
    console.error("Swap failed:", error);
  },
});
```

***

## Common questions

<AccordionGroup>
  <Accordion title="Do I need an API key or RPC node?">
    No. Jupiter Plugin handles all infrastructure through Ultra. No API key, no RPC node, no backend required.
  </Accordion>

  <Accordion title="Can I lock the swap to a specific token?">
    Yes. Use `formProps.fixedMint` to lock one side of the swap to a specific token mint address. Combine with `fixedAmount` to also lock the amount (useful for payment flows).
  </Accordion>

  <Accordion title="How do users connect their wallet?">
    Plugin provides wallet connection out of the box. Users click the connect button in the widget and select their browser wallet (Phantom, Backpack, etc.). If your app already has a wallet provider, use `enableWalletPassthrough` to avoid a double connection.
  </Accordion>

  <Accordion title="How do I test before deploying?">
    Use the [Plugin Playground](https://plugin.jup.ag/) to experiment with display modes, form props, and colour themes. It generates the configuration code for you.
  </Accordion>

  <Accordion title="Why does integrated mode have no height?">
    The integrated mode container needs a fixed height. Set it on your target div:

    ```html theme={null}
    <div id="jupiter-plugin" style="height: 600px;"></div>
    ```
  </Accordion>
</AccordionGroup>

***

## Next steps

* **[Plugin Playground](https://plugin.jup.ag/):** Experiment with configuration and get code snippets.
* **[Customisation Reference](/tool-kits/plugin/customization):** Full configuration options and TypeScript types.
* **[Framework Walkthroughs](/tool-kits/plugin/nextjs-app-example):** Step-by-step guides for Next.js, React, and HTML.
* **[Referral Program](/tool-kits/referral-program):** Earn fees on swaps through your integration.
* **[Jupiter Dev Notifications](https://t.me/jup_dev):** Plugin updates and announcements.
