Phantom Ecosystem Wallets & Mobile

setup-browser-app

Scaffold a vanilla JS/TS app with Phantom Browser SDK for wallet integration, without any framework dependency

Ecosystem skill — independently developed and maintained by Phantom, not the Solana Foundation. No security review is performed; evaluate before use.

One command for Claude Code, Cursor, Codex, Windsurf and other agents — installs from the upstream repo (current HEAD; it ships 8 skills — pick setup-browser-app when prompted).

$npx skills add phantom/phantom-connect-cursor-plugin

Skill contents

Scaffold Browser App with Phantom Connect

When to use

  • User asks to set up a vanilla JS app with Phantom Connect
  • User wants to create a framework-agnostic wallet integration
  • User wants to use the Browser SDK directly

Workflow

Step 1: Install Dependencies

npm install @phantom/browser-sdk @solana/web3.js

Step 2: Create the SDK Singleton

Initialize a single BrowserSDK instance for your application:

import { BrowserSDK, AddressType } from "@phantom/browser-sdk";

const sdk = new BrowserSDK({
  appId: "your-app-id-from-phantom-portal",
  providers: ["google", "apple"],
  addressTypes: [AddressType.Solana, AddressType.Ethereum],
});

Important: Create only ONE BrowserSDK instance per application. Reuse this singleton everywhere.

Step 3: Implement Connect / Disconnect

async function connectWallet() {
  try {
    const accounts = await sdk.connect();
    console.log("Connected accounts:", accounts);

    const solanaAccount = accounts.find((a) => a.chain === "solana");
    if (solanaAccount) {
      console.log("Solana address:", solanaAccount.address);
    }
  } catch (error) {
    console.error("Connection failed:", error);
  }
}

async function disconnectWallet() {
  try {
    await sdk.disconnect();
    console.log("Disconnected");
  } catch (error) {
    console.error("Disconnect failed:", error);
  }
}

Step 4: Access Chain-Specific APIs

Use sdk.solana for Solana operations and sdk.ethereum for EVM operations:

// Solana operations
const solana = sdk.solana;

// Sign and send a transaction
const { signature } = await solana.signAndSendTransaction(transaction);

// Sign a message
const { signature: msgSig } = await solana.signMessage(
  new TextEncoder().encode("Hello from Phantom!")
);

Step 5: Check Connection State

function isWalletConnected(): boolean {
  return sdk.isConnected;
}

function getAccounts() {
  return sdk.accounts;
}

Step 6: HTML Setup (Minimal Example)

<!DOCTYPE html>
<html>
  <body>
    <button id="connect">Connect Wallet</button>
    <button id="disconnect" style="display:none">Disconnect</button>
    <p id="address"></p>
    <script type="module" src="./main.ts"></script>
  </body>
</html>

Important Notes

  • Import AddressType from @phantom/browser-sdk, not from other packages.
  • Always use signAndSendTransactionsignTransaction is NOT supported for embedded wallets.
  • The SDK singleton should be created once and reused across your application.
  • Register your app at Phantom Portal to get an appId.