💻Widget
Easily integrate Panora's swap functionality into your application with our lightweight, plug-and-play SDK — enabling seamless token swaps and real-time data directly within your platform.
Key Features
Quick Setup — Add swaps to your app in under 5 minutes
Three Display Modes — Integrated (inline), Widget (floating button), or Modal (popup)
Fully Customizable — Theme colors, default tokens, locale, slippage, and more
Multi-Language — Supports 11 locales out of the box
Wallet Support — Built-in wallet connection UI, or bring your own
Display Modes
INTEGRATED
Renders inline inside a target <div> you provide
WIDGET
Renders a floating button (configurable corner). Click to open the swap UI
MODAL
Opens a centered popup dialog with a backdrop overlay
Supported Frameworks
Plain HTML / Vanilla JS
React (Vite, CRA)
Next.js (App Router & Pages Router)
Any framework that can run JavaScript
Getting an API Key
A default public API key is available for development and typical usage:
For production or high-traffic use cases, open a ticket on Discord to request a dedicated key.
Installation
npm
yarn
pnpm
CDN (no bundler needed)

Quick Start
Option A: NPM (React / Next.js)
Option B: CDN (plain HTML)
React App Example
A complete guide to integrating Panora Widget SDK into a React + Vite application.
1. Create a New Project
2. Install the SDK
3. Add the Widget
Replace src/App.tsx with:
4. Run
Using the React Component
If you prefer a declarative approach instead of the imperative init() / close() API, the SDK also exports a <PanoraWidget /> React component:
Note:
<PanoraWidget />always renders inINTEGRATEDmode. ForWIDGETorMODALmodes, use the imperativeinit()/close()API.
Key Points
Always call
close()before re-initializing to avoid duplicate instancesThe
100mstimeout gives the DOM time to settle before the widget mountsStore your API key in
.envasVITE_PANORA_API_KEY
Next.js Example (App Router)
A complete guide to integrating Panora Widget SDK into a Next.js App Router application.
1. Create a New Project
2. Install the SDK
3. Add the Widget
Create or replace src/app/page.tsx:
Important: The
"use client"directive is required. The widget uses browser APIs (document,window) and cannot run during server-side rendering.
Widget Mode Example
Modal Mode Example
Next.js Pages Router
If you use the Pages Router instead of App Router, the code is nearly identical — just drop the "use client" directive and place your file in src/pages/index.tsx. No other changes needed.
Key Points
Store your API key in
.env.localasNEXT_PUBLIC_PANORA_API_KEYAlways call
close()in theuseEffectcleanup to prevent memory leaksThe widget loads its UI from the CDN at runtime, so your Next.js bundle size is unaffected
HTML App Example
The simplest integration — no bundler, no framework, just a single <script> tag.
1. Create an HTML File
2. Serve It
Use any static file server:
Widget Mode (Floating Button)
Modal Mode (Popup)
API Reference (CDN)
When using the CDN script, the global PanoraWidget object is available on window:
PanoraWidget.render(container, config?)
Render the widget into a DOM element or CSS selector. Returns { unmount }
Key Points
The
deferattribute ensures the script loads after HTML parsingPanoraWidget.render()accepts either a DOM element or a CSS selector (#id,.class)The CDN bundle is fully self-contained (includes React) — no other dependencies needed
Configuration
Complete reference for all WidgetConfig options.
API & RPC
panoraApiKey
string
Public key
Your Panora API key
rpcUrl
string
Panora default
Custom Aptos RPC URL. Must use https:// (except localhost)
Display
displayMode
"INTEGRATED" | "WIDGET" | "MODAL"
"WIDGET"
How the widget is presented
integratedTargetId
string
"panora-widget"
DOM element ID for INTEGRATED mode (used with init() only)
width
CSS value
450px (max)
Widget width in INTEGRATED mode
height
CSS value
630px
Widget height in INTEGRATED mode
Widget Button (WIDGET mode only)
widgetBtnSize
"SMALL" | "DEFAULT"
"DEFAULT"
Floating button size
widgetBtnDirection
"left-top" | "left-bottom" | "right-top" | "right-bottom"
"right-bottom"
Corner position
widgetBtnOffset
{ x: number; y: number }
—
Pixel offset from the corner
Tokens
defaultFromTokenAddress
`0x${string}`
—
Pre-selected "from" token
defaultToTokenAddress
`0x${string}`
—
Pre-selected "to" token
defaultFavoriteTokens
`0x${string}`[]
—
Tokens pinned as favorites in the token picker
customTokens
`0x${string}`[]
—
Additional token addresses shown in the picker
allowedTokens
`0x${string}`[]
—
Restrict the token list to only these addresses
showTokenCategorization
boolean
—
Show/hide token category tabs in the picker
Swap Settings
defaultSlippagePercentage
string
—
Default slippage tolerance (0–50). Must be a numeric string
showPercentageSlider
boolean
—
Show the percentage slider on the input field
Wallet
account
Account
undefined
Pre-configured Aptos account for direct transaction signing without wallet popup. Accepts any Account subclass from @aptos-labs/ts-sdk (Ed25519Account, SingleKeyAccount, KeylessAccount, etc.). When set, the widget signs transactions directly — no wallet connection needed.
independentWalletConnection
boolean
true
When false, hides the widget's built-in wallet connect button. Use when the host app manages wallet connection externally.
useExternalWallet
boolean
false
When true, the widget skips creating its own AptosWalletAdapterProvider and uses useWallet() from the nearest parent provider. The integrator must wrap the widget in their own <AptosWalletAdapterProvider>. Ideal for wallet extensions/apps embedding the widget. Only works with npm package (not CDN).
disableWalletButton
boolean
false
Hide the "Connect Wallet" button
enabledWallets
string[]
All wallets
Restrict which wallets appear in the connection dialog
Integrator Fees
integratorWalletAddress
`0x${string}`
—
Wallet address that receives integrator fees
integratorFeePercentage
number
—
Fee percentage per transaction (0–5)
Transaction Options
transactionOptions.maxGasAmount
number
—
Maximum gas units. Must be a positive integer
transactionOptions.gasUnitPrice
number
—
Price per gas unit (octas). Must be a positive integer
Localization
locale
string
"en"
UI language
Supported locales:
en
English
es
Spanish
hi
Hindi
id
Indonesian
ja
Japanese
ko
Korean
ru
Russian
tr
Turkish
vi
Vietnamese
zh
Chinese (Simplified)
zh-HK
Chinese (Traditional)
Notifications
showNotifications
boolean
false
Show toast notifications for swap success/failure
Validation Rules
The widget validates your config at runtime. Invalid values are silently ignored with a console warning:
defaultSlippagePercentage
Must be a numeric string between 0 and 50
integratorFeePercentage
Must be a number between 0 and 5
rpcUrl
Must start with https:// (except localhost / 127.0.0.1)
transactionOptions.maxGasAmount
Must be a positive integer
transactionOptions.gasUnitPrice
Must be a positive integer
Theming
Customize the widget's appearance to match your app's design system.
Pass a partial theme object in your config — any property you omit will use the default Panora theme.
Usage
Theme Properties
basicBgColor
rgba(255, 255, 255, .05)
Primary background
secondaryBgColor
#010D09
Secondary background (outer areas)
tertiaryBgColor
#000704
Tertiary background (cards, dropdowns)
primaryColor
#5fdfac
Main accent color (buttons, highlights)
subtleColor
rgba(255, 255, 255, .05)
Subtle UI elements
primaryButtonTextColor
#000000
Text color on primary buttons
borderColor
rgba(255, 255, 255, .05)
Border color
inputColor
#0d110d
Input field background
inputBorderColor
#2a3a2a
Input field border
primaryTextColor
#FFFFFF
Main text color
secondaryTextColor
#6B7280
Muted/secondary text
placeholderTextColor
#3a4a3a
Input placeholder text
textUpColor
#5fdfac
Positive values (gains)
textDownColor
#F6465D
Negative values (losses)
successColor
#5fdfac
Success states
errorColor
#F6465D
Error states
warningColor
#EF8E19
Warning states
Default Theme
Tip: You can import the default theme object in code:
API Reference
NPM Package Exports
init(config?)
Initialize and render the widget.
config
WidgetConfig
Widget configuration (see Configuration)
config.integratedTargetId
string
DOM element ID for INTEGRATED mode. Defaults to "panora-widget"
Returns: Promise<{ unmount: () => void }> — call unmount() to remove the widget.
Behavior by display mode:
INTEGRATED
Renders into the element matching integratedTargetId. Throws if element not found.
WIDGET
Creates a floating button. A panora-widget-root container is auto-created in document.body if needed.
MODAL
Opens a centered dialog with backdrop. Container auto-created like WIDGET.
render(container, config?)
Lower-level alternative to init() for full control over where the widget mounts.
container
HTMLElement | string
A DOM element or CSS selector ("#my-div", ".my-class")
config
WidgetConfig
Widget configuration
Note:
render()is primarily used with the CDN bundle (PanoraWidget.render()). When using the npm package, preferinit().
close()
Unmount and clean up the widget.
Always call close() before re-initializing, or in your component's cleanup function to prevent duplicate instances.
resume()
Re-show the widget with the last configuration passed to init().
If a widget instance is already mounted, this is a no-op.
<PanoraWidget />
React component for declarative rendering. Always uses INTEGRATED mode.
Automatically creates a container
<div>and callsinit()on mountAutomatically calls
close()on unmountRe-initializes when
widgetConfigchanges
CDN Global: PanoraWidget
When using the CDN <script> tag, a global PanoraWidget object is available on window.
container
HTMLElement | string
DOM element or CSS selector
config
WidgetConfig
Widget configuration
The CDN bundle is fully self-contained — it includes its own copy of React and all dependencies.
Attribution
Include "Powered by Panora" when using this SDK in your application. The widget displays this by default.
Last updated