Why This Matters
Building DeFi UIs from scratch takes weeks: wallet connections, chain switching, deposit/withdraw flows, position tracking, P&L display. Our React widgets handle all of this. You drop in a component, and your users can start earning yield.Widget Builder Studio
The Widget Builder Studio lets you pick a widget, choose a theme preset, tweak colors and fonts, and see a live preview. When you’re happy with how it looks, switch to the code tab and copy the generated integration code.Widget Builder Studio
Customize and preview widgets visually. Copy production-ready code.
How It Works
The widgets are React components that talk to the Compass API through your server. Here’s the flow:- Your user opens your app and connects their wallet
- The widget shows available yield opportunities (vaults, Aave markets, Pendle markets)
- The user picks a market, enters an amount, and signs a transaction
- Your server relays the signed transaction to the Compass API, which handles execution
- Gas is sponsored by you (optional) so the user doesn’t need ETH for fees
Installation
Quick Start
Setting up the widgets takes three steps:- Wrap your app with providers - connects the wallet to the widgets
- Add a server-side API route - keeps your API key secure
- Drop in a widget - render it on a page
Step 1: Client-side Providers
Create a providers file that connects your wallet library to theCompassProvider. The CompassProvider is the wrapper that gives all widgets access to wallet state, chain selection, and theming.
Step 2: Server-side API Route
The widgets call the Compass API through your server. This keeps your API key out of the browser. Create a catch-all API route in your Next.js app:createCompassHandler function creates a request handler that:
- Proxies widget requests to the Compass API with your API key
- Handles gas sponsorship if you provide a
gasSponsorPrivateKey - Supports all widget operations (account creation, deposits, withdrawals, swaps, transfers)
Step 3: Environment Variables
Step 4: Add Layout and Widgets
Import the widget styles in your layout, then add any widget to a page:Step 5: Configure Tailwind (if using)
If your app uses Tailwind CSS, add the widgets package to your content config so Tailwind picks up the classes used by the widgets:Available Widgets
EarnAccount
A banking-style savings account widget. This is the primary widget - it gives users a single place to deposit funds, choose between variable-rate and fixed-rate markets, and track their earnings. Behind the scenes it creates a product account for the user, handles token approvals, swaps, and deposits across Aave, Morpho vaults, and Pendle. The widget shows:- Total balance across all positions and available tokens in the account
- Market selector with Variable (Aave, Morpho vaults) and Fixed (Pendle) tabs
- Deposit/Withdraw forms with token selection and auto-swapping
- Top Up button to transfer tokens from the user’s wallet to their earn account
- Earnings summary with per-position P&L
| Prop | Type | Default | Description |
|---|---|---|---|
title | string | ’Savings Account’ | Title shown in the header |
showHeader | boolean | true | Show the header with title and wallet status |
showInterestRate | boolean | true | Show the interest rate badge |
showTopUpButton | boolean | true | Show the “Top Up” button to transfer from wallet |
showTrustBadge | boolean | true | Show “Non-custodial” and “Audited protocols” badges |
compact | boolean | false | Use compact layout with reduced spacing |
defaultMarketTab | ’variable’ | ‘fixed' | 'variable’ | Which market tab to show first |
allowedVariableMarkets | string[] | undefined | Filter which variable markets to show. Undefined shows all. |
allowedFixedMarkets | string[] | undefined | Filter which fixed markets to show. Undefined shows all. |
chain | string | undefined | Lock to a specific chain. Hides the chain selector when set. |
onDeposit | function | undefined | Callback after successful deposit |
onWithdraw | function | undefined | Callback after successful withdraw |
SwapWidget
A token swap interface. Users pick a token pair, enter an amount, and get a real-time quote. Transactions are signed with EIP-712 and can be gas-sponsored.| Prop | Type | Default | Description |
|---|---|---|---|
layout | ’compact’ | ‘full' | 'full’ | Widget size. Compact is smaller for sidebars. |
defaultFromToken | string | ’ETH’ | Default input token |
defaultToToken | string | ’USDC’ | Default output token |
allowedTokens | string[] | [‘USDC’, ‘ETH’, ‘WETH’, ‘WBTC’, ‘DAI’, ‘USDT’, ‘AUSD’, ‘SBC’] | Tokens available for swap |
showReverseButton | boolean | true | Show button to flip the token pair |
showSettings | boolean | false | Show slippage settings |
onSwapSuccess | function | undefined | Called after a successful swap with token details and tx hash |
onSwapError | function | undefined | Called when a swap fails |
Shared Components
These building-block components are exported for custom layouts. Use them if you want to build your own widget arrangement instead of using the pre-built widgets above.| Component | What it does |
|---|---|
ChainSwitcher | Dropdown to switch between Ethereum, Base, and Arbitrum |
WalletStatus | Shows the connected wallet address and connection state |
EarnAccountGuard | Wraps content that requires an earn account. Prompts account creation if needed. |
EarnAccountBalance | Shows the earn account token balance with a transfer button |
AccountBalancesModal | Modal showing detailed token breakdown of the earn account |
ActionModal | Generic modal for deposit/withdraw/transfer actions |
DepositWithdrawForm | Reusable form for deposit and withdraw inputs |
PnLSummary | Displays profit/loss information |
TransactionHistory | Shows past deposit and withdraw transactions |
Data Hooks
If you want to fetch data without using the pre-built widgets (for example, to build a completely custom UI), these hooks give you access to the same data the widgets use:| Hook | Returns |
|---|---|
useVaultsData() | Vault list, loading state, and refetch function |
useAaveData() | Aave market list, loading state, and refetch function |
usePendleData() | Pendle market list, loading state, and refetch function |
useSwapQuote() | Swap quote for a given token pair and amount |
Context Hooks
For advanced use cases, you can access the internal context directly:| Hook | What it provides |
|---|---|
useCompassWallet() | Wallet address, connection state, signTypedData, switchChain, login, logout |
useCompassChain() | Current chain ID and setter function. Persists to localStorage. |
useCompassApi() | API client instance |
useEarnAccount() | Earn account address, deployment state, createAccount(), refetch() |
Wallet Adapter
TheCompassProvider needs a wallet prop that bridges your wallet library to the widgets. This is how the widgets know the connected address, can request signatures, and can switch chains.
signTypedData function is the most important one. Every transaction (deposit, withdraw, swap, transfer) goes through EIP-712 typed data signing. The Compass API prepares the data, the user signs it in their wallet, and the server executes the transaction (optionally sponsoring gas).
Theming
The widgets support three theming approaches:- Preset name - Use a built-in theme:
theme="compass-dark" - Preset with overrides - Start from a preset and customize specific values:
theme={{ preset: 'compass-dark', overrides: {...} }} - Full custom theme - Provide a complete theme object with all values
Built-in Theme Presets
| Preset | Description |
|---|---|
compass-dark | Default dark theme with indigo/purple accents and glassmorphism |
compass-light | Light theme with indigo primary and subtle shadows |
minimal-dark | Flat dark design with white/gray primary, sharp corners, no shadows |
minimal-light | Flat light design with black/gray primary, sharp corners |
high-contrast-dark | Accessible dark theme with blue primary, bold borders, larger text |
high-contrast-light | Accessible light theme with bold colors and larger text |
Custom Theme Overrides
You only need to override the properties you want to change. Everything else inherits from the preset.Colors
Brand Colors (colors.brand)
| Property | Description |
|---|---|
primary | Primary brand color for buttons, links, and accents |
primaryHover | Hover state for primary color |
primaryMuted | Muted/subtle variant of primary (for backgrounds, badges) |
primaryText | Text color on primary-colored backgrounds |
secondary | Secondary accent color |
secondaryHover | Hover state for secondary color |
Background Colors (colors.backgrounds)
| Property | Description |
|---|---|
background | Main page/widget background |
surface | Card and panel backgrounds |
surfaceHover | Hover state for surfaces |
overlay | Modal and overlay backdrop color |
Text Colors (colors.text)
| Property | Description |
|---|---|
text | Primary text color |
textSecondary | Secondary/muted text |
textTertiary | Tertiary/disabled text |
Border Colors (colors.borders)
| Property | Description |
|---|---|
border | Default border color |
borderHover | Border hover state |
borderFocus | Focus ring color for inputs |
Semantic Colors (colors.semantic)
Each semantic color has a DEFAULT (main color) and muted (background/subtle) variant:
| Property | Description |
|---|---|
success.DEFAULT | Success/positive state color |
success.muted | Success background/subtle color |
warning.DEFAULT | Warning/caution state color |
warning.muted | Warning background/subtle color |
error.DEFAULT | Error/negative state color |
error.muted | Error background/subtle color |
info.DEFAULT | Info/neutral state color |
info.muted | Info background/subtle color |
Typography
Font Families (typography)
| Property | Description |
|---|---|
fontFamily | Primary font stack for all text |
fontFamilyMono | Monospace font for code and numbers |
Text Scales
Each scale (heading, subheading, body, caption, label) supports:
| Property | Description |
|---|---|
fontSize | Font size (e.g., '1.5rem') |
lineHeight | Line height (e.g., '1.4') |
fontWeight | Font weight (e.g., '600') |
letterSpacing | Letter spacing (e.g., '-0.02em') - optional |
Spacing
| Property | Description |
|---|---|
unit | Base spacing unit (e.g., '4px') |
containerPadding | Outer container padding |
cardPadding | Padding inside cards and panels |
inputPadding | Padding inside input fields and buttons |
Shape
Border Radius (shape.borderRadius)
| Property | Description |
|---|---|
none | No radius (e.g., '0') |
sm | Small radius for subtle rounding |
md | Medium radius for inputs and buttons |
lg | Large radius for cards |
xl | Extra large radius for modals |
full | Fully rounded (e.g., '9999px') |
Border Width (shape.borderWidth)
| Property | Description |
|---|---|
borderWidth | Default border width (e.g., '1px') |
Effects
Shadows (effects.shadow)
| Property | Description |
|---|---|
sm | Subtle shadow for hover states |
md | Medium shadow for cards |
lg | Large shadow for modals and dropdowns |
Blur (effects.blur)
| Property | Description |
|---|---|
sm | Subtle blur for overlays |
md | Medium blur for glassmorphism |
lg | Heavy blur for backgrounds |
Transitions (effects.transition)
| Property | Description |
|---|---|
fast | Quick interactions (150ms) |
normal | Standard transitions (200ms) |
slow | Deliberate animations (300ms) |
Full Theme Example
Here is a complete example showing all customizable properties:Supported Chains
| Chain | ID |
|---|---|
| Ethereum | ethereum |
| Base | base |
| Arbitrum | arbitrum |
chain prop on EarnAccount, the chain selector is hidden and the widget is locked to that chain.
Gas Sponsorship
To sponsor gas so your users don’t need ETH for transaction fees:- Set
gasSponsorPrivateKeyin the server handler (a wallet with ETH on each chain you support) - Set
rpcUrlsfor each chain
Use Cases
Embedded Savings Account: Drop in theEarnAccount widget to give users a bank-like savings experience. They deposit stablecoins, pick a yield market, and start earning - all within your app.
Wallet Integration: Add an “Earn” tab to your wallet app. Users see their positions, P&L, and can manage deposits without leaving your app.
DEX Integration: Add the SwapWidget to let users swap tokens directly within your app with gas-sponsored transactions.