DOCS / EMBED THE CHAT

Embed the chat

Drop the full Pantessa chat into your own site as an iframe — scoped to the MCPs you pick, with transaction building, guardrails, receipts, and wallet signing intact. Visitors chat immediately as guests (no sign-in); signing a swap or vote connects a wallet inside the frame.

The iframe URL

https://www.yeetful.com/embed
  ?mcps=cow-free,snapshot-free     # comma-separated directory slugs (max 4)
  &key=yfe_…                       # your PUBLIC embed key (dashboard → Keys)
  &address=0xYourUsersWallet       # optional wallet-address context
  &theme=dark                      # dark (default) | light
  &host=https%3A%2F%2Fyour.app     # URL-encoded parent origin (enables messaging)
  &page=https%3A%2F%2Fyour.app%2Fswap  # URL-encoded page URL (embed analytics)
  • key — a publishable embed key (yfe_…), minted on the dashboard. It's safe in page source (it can read nothing and spend nothing that isn't already yours): it attributes the embed to your account, lists the site under Your embeds, and bills house-model answers to your plan's YEET credits instead of each visitor's free tier. Keyless embeds still work — tracked anonymously by origin, metered per visitor.
  • mcps — directory slugs resolved against the catalog; unknown slugs are dropped, capped at 4. If none resolve, the chat falls back to its normal default set.
  • address — context only: it feeds $USER_ADDRESS in the router ("show my open orders") and shows as a small context: 0x12…ab indicator. It can never sign— signatures come from a connected wallet: the host page's wallet over the bridge below, or one connected inside the iframe.
  • host— your page's origin. postMessage is exchanged only with this origin; without it the embed doesn't listen at all and only posts ready/resize (nothing sensitive) with a * target.

postMessage API (contract v1)

Every payload is an object tagged { source: 'yeetful-embed', v: 1, type: … }.

Embed → your page:

{ source: 'yeetful-embed', v: 1, type: 'ready' }                          // mounted
{ source: 'yeetful-embed', v: 1, type: 'resize', height: 620 }            // content height changed
{ source: 'yeetful-embed', v: 1, type: 'event', name: 'order-signed',     // notable moments
  data: { orderUid: '0x…', explorerUrl: 'https://explorer.cow.fi/…' } }

Your page → embed (send to the iframe's contentWindow, targeting the Pantessa origin):

{ source: 'yeetful-embed', v: 1, type: 'address', address: '0x…' | null } // update wallet context
{ source: 'yeetful-embed', v: 1, type: 'theme', theme: 'dark' | 'light' }
{ source: 'yeetful-embed', v: 1, type: 'prompt', text: 'quote 100 USDC…',  // host CTA → chat:
  send: true }                                                             // submit (or prefill w/ send:false)

Wallet bridge (contract v1.1)

With yeetful/embed≥ 0.9.0 the SDK can relay your page's EIP-1193 provider into the iframe, so the embedded chat is really wallet-connected — swap orders, transactions, and paid-call payments all sign through the user's own wallet, prompting on your page, never inside the frame. JSON-RPC rides the same origin-pinned postMessage channel:

// embed → your page (the SDK answers these)
{ source: 'yeetful-embed', v: 1, type: 'rpc', id: '…', method: 'eth_requestAccounts', params?: […] }

// your page → embed
{ source: 'yeetful-embed', v: 1, type: 'rpc:result', id: '…', result: … }
{ source: 'yeetful-embed', v: 1, type: 'rpc:error',  id: '…', error: { code: 4200, message: '…' } }

// your page → embed: announce the provider (after 'ready', and on
// accountsChanged / chainChanged / disconnect). Empty accounts = bridge
// available but not connected — the embed shows a "Connect host wallet"
// button instead of prompting uninvited.
{ source: 'yeetful-embed', v: 1, type: 'wallet', accounts: ['0x…'], chainId: '0x2105' | null }

The SDK side enforces a method allowlist — connection + signing (eth_requestAccounts, personal_sign, eth_signTypedData_v4, eth_sendTransaction, wallet_switchEthereumChain/addEthereumChain) plus read-only RPC (eth_call, gas/fee/balance/receipt lookups and the like); anything else is refused with error code 4200. Security model: the bridge grants the iframe the same dapp-level access your page already has— nothing more. There are no keys in the frame and no blanket signing authority: every signature and transaction pops the user's own wallet for explicit approval, exactly as if your page had requested it.

Or use the SDK

The yeetful npm package ships an embed helper that builds the iframe, wires the origin checks, and keeps the address context in sync:

import { mountYeetfulChat } from 'yeetful/embed'

mountYeetfulChat({
  container: document.getElementById('chat')!,
  key: 'yfe_…',              // your public embed key (>= 0.10; optional)
  mcps: ['cow-free', 'snapshot-free'],
  wallet: 'auto',            // bridge the page's EIP-1193 provider (v1.1);
                             // or pass a provider / 'off' for address-only context
  mode: 'bubble',            // 'bubble' (floating launcher) | 'inline'
})

SDK ≥ 0.10 also reports the page URL (page=) so your dashboard's Your embeds list shows exactly which pages run the chat.

What your dashboard sees

Every embed session reports turn telemetry, and /dashboard/embeds turns it into the numbers a host actually wants:

  • Money moved — signed, guardrail-priced USD notional through your embed. The headline.
  • The funnel— sessions → transactions built → transactions signed, per site and (with SDK ≥ 0.10's page= reporting) per page.
  • Dead-end sessions — visitors who hit friction and never got a build, with their verbatim asks, plus a copyable prompt that hands the whole list to Claude to diagnose which asks need a missing tool, schema, or MCP.

Deep links, before you embed

Not ready for an iframe? Any link can land a visitor in the first-party chat with your MCP set active and an ask prefilled but never auto-sent:

https://www.yeetful.com/chat
  ?mcps=robinhood-free                       # your MCP set, same slugs as the embed
  &prompt=Buy%20%242%20of%20AAPL             # prefilled — the visitor presses send

The embed's prompt postMessage (above) is the same contract with send: false — CTAs on your page can drop a ready-to-run ask into either surface.

Install with Claude

The fastest path: copy the Claude Code prompt below and paste it inside your app's repo. It installs the SDK, mounts the chat, patches your CSP if needed, and tells you how to verify. One paste, live chat. Sign in and the API Keys page generates the same prompt with your embed key baked in, so usage attributes to your account.

THE INSTALL — FIVE LINES, ANY SITEnpm i yeetful
import { mountYeetfulChat } from 'yeetful/embed'

mountYeetfulChat({
  mode: 'bubble',
  mcps: ['uniswap-free', 'snapshot-free'],
  wallet: 'auto', // the host page's wallet signs
})

The Claude prompt is the whole integration — paste it into Claude Code in your app’s repo and it installs the SDK, mounts the chat, patches your CSP, and verifies. Works keyless — a publishable key adds usage analytics later.

Notes

  • The route serves Content-Security-Policy: frame-ancestors * — any site may embed it. Scope what the chat can do with mcps, not the frame.
  • Guests run in burner mode: Pantessa's house wallet pays free-tier calls, so the chat answers with zero setup. Paid MCPs and swap/vote signatures use the bridged host wallet (v1.1) or a wallet your visitor connects inside the frame.