Skip to main content
Add the Dynamic docs MCP to your AI editor first — your agent can then query the docs directly. Instructions are on the Welcome page.
Copy this prompt into your LLM (e.g. Claude, ChatGPT, Cursor) to implement Dynamic in your React app.
# React SDK Quickstart

## Purpose and Usage

This document provides structured quickstart information for the Dynamic React SDK. It is designed to be consumed by LLMs to generate accurate installation commands and code examples based on user requirements.

**How to use this document:**

Start by asking the user which path they want:

> "Would you like a **Quick start** (EVM + DynamicWidget UI, zero configuration — recommended if you're just getting started) or a **Custom setup** (choose your chains, Wagmi integration, and EVM client library)?"

- If the user chooses **Quick start**: follow the Quick Start Path section exactly. Do not ask any configuration questions — execute the happy path as written.
- If the user chooses **Custom setup**: follow the Custom Setup Path section and ask all configuration questions before proceeding.

---

## Quick Start Path

> Use this path when the user chooses Quick start. Execute every step in order. Do not skip steps. Do not ask configuration questions.

**Stack:** Vite 5 + npm + EVM only + DynamicWidget (no Wagmi)

### Step 1 — Prerequisites

Tell the user:
- Node.js 18+ is required
- A Dynamic environment ID is required — get one at https://app.dynamic.xyz/dashboard/developer

Ask the user for their environment ID before proceeding.

### Step 2 — Scaffold the project

Use Vite 5 explicitly. Do not use `npm create vite@latest` — it installs Vite 8 which is incompatible with the Dynamic SDK due to a missing native binary.

```bash
npm create vite@5 my-app -- --template react-ts
cd my-app
```

### Step 3 — Install the SDK

```bash
npm i @dynamic-labs/sdk-react-core @dynamic-labs/ethereum
```

### Step 4 — Fix Vite polyfills

The Dynamic SDK requires Node globals (`process`, `Buffer`) that Vite does not provide by default. Add the following `define` block to `vite.config.ts`. Do not use `@esbuild-plugins/node-globals-polyfill` — it is incompatible with Vite 5.

```typescript
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  define: {
    'process.env': {},
    global: 'globalThis',
  },
});
```

### Step 5 — Set up the provider

Wrap your app in `DynamicContextProvider` at the root with `EthereumWalletConnectors`:

```typescript
// src/main.tsx
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { DynamicContextProvider } from '@dynamic-labs/sdk-react-core';
import { EthereumWalletConnectors } from '@dynamic-labs/ethereum';
import App from './App';

createRoot(document.getElementById('root')!).render(
  <StrictMode>
    <DynamicContextProvider
      settings={{
        environmentId: 'YOUR_ENVIRONMENT_ID',
        walletConnectors: [EthereumWalletConnectors],
      }}
    >
      <App />
    </DynamicContextProvider>
  </StrictMode>
);
```

### Step 6 — Add the widget

Drop `DynamicWidget` into your app component. This provides the complete auth and wallet connection UI out of the box:

```typescript
// src/App.tsx
import { DynamicWidget } from '@dynamic-labs/sdk-react-core';

export default function App() {
  return (
    <div>
      <DynamicWidget />
    </div>
  );
}
```

### Step 7 — Post-login patterns

After the user authenticates, use these hooks to access wallet and user state:

```typescript
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';

export default function WalletInfo() {
  const { primaryWallet, user, handleLogOut } = useDynamicContext();

  if (!primaryWallet) return <p>Not connected</p>;

  return (
    <div>
      <p>Address: {primaryWallet.address}</p>
      <p>Chain ID: {primaryWallet.chain}</p>
      <p>Email: {user?.email}</p>
      <button onClick={handleLogOut}>Disconnect</button>
    </div>
  );
}
```

> Note: `primaryWallet.chain` returns the chain ID (e.g. `1` for Ethereum mainnet), not a human-readable name. Map it to a name yourself if needed.

---

## Custom Setup Path

> Use this path when the user chooses Custom setup. Ask ALL questions below before generating any code.

**Questions to ask the user:**

1. Which package manager do you prefer? (npm, yarn, pnpm, bun)
2. Which chains do you want to support? (EVM, SVM, Bitcoin, Algorand, Flow Cadence, Starknet, Cosmos, Sui, Spark, Tron — one or more)
3. If EVM: do you want Wagmi integration for React hooks?
4. If EVM: which EVM client library do you prefer? (viem or ethers)

**Only after receiving answers**, use the sections below to generate the correct setup.

### Scaffolding note
Always scaffold with a pinned Vite version. Do not use `vite@latest` — use `vite@5`:
```bash
npm create vite@5 my-app -- --template react-ts
```

### Vite polyfill (required for all Vite setups)
Add to `vite.config.ts` — do not use `@esbuild-plugins/node-globals-polyfill`, it is incompatible with Vite 5:
```typescript
define: {
  'process.env': {},
  global: 'globalThis',
},
```

### Package Manager Commands
- `npm`: `npm i`
- `yarn`: `yarn add`
- `pnpm`: `pnpm add`
- `bun`: `bun add`

### Package Mapping
- Core (always required): `@dynamic-labs/sdk-react-core`
- EVM: `@dynamic-labs/ethereum`
- SVM: `@dynamic-labs/solana`
- Bitcoin: `@dynamic-labs/bitcoin`
- Algorand: `@dynamic-labs/algorand`
- Flow Cadence: `@dynamic-labs/flow`
- Starknet: `@dynamic-labs/starknet`
- Cosmos: `@dynamic-labs/cosmos`
- Sui: `@dynamic-labs/sui`
- Spark: `@dynamic-labs/spark`
- Tron: `@dynamic-labs/tron`
- Wagmi (EVM only, optional): `@dynamic-labs/wagmi-connector wagmi@2 @tanstack/react-query`

> **Wagmi version:** Always install `wagmi@2` explicitly. `wagmi@3` is incompatible with the Dynamic connector.

### Chain Connector Mapping
- `EVM``EthereumWalletConnectors` from `@dynamic-labs/ethereum`
- `SVM``SolanaWalletConnectors` from `@dynamic-labs/solana`
- `Bitcoin``BitcoinWalletConnectors` from `@dynamic-labs/bitcoin`
- `Algorand``AlgorandWalletConnectors` from `@dynamic-labs/algorand`
- `Flow Cadence``FlowWalletConnectors` from `@dynamic-labs/flow`
- `Starknet``StarknetWalletConnectors` from `@dynamic-labs/starknet`
- `Cosmos``CosmosWalletConnectors` from `@dynamic-labs/cosmos`
- `Sui``SuiWalletConnectors` from `@dynamic-labs/sui`
- `Spark``SparkWalletConnectors` from `@dynamic-labs/spark`
- `Tron``TronWalletConnectors` from `@dynamic-labs/tron`

### Component Structure

**Without Wagmi**:
```typescript
export default function App() {
  return (
    <DynamicContextProvider
      settings={{
        environmentId: 'YOUR_ENVIRONMENT_ID',
        walletConnectors: [EthereumWalletConnectors],
      }}
    >
      <DynamicWidget />
    </DynamicContextProvider>
  );
}
```

**With Wagmi**:
```typescript
const config = createConfig({
  chains: [mainnet],
  multiInjectedProviderDiscovery: false,
  transports: { [mainnet.id]: http() },
});

const queryClient = new QueryClient();

export default function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <WagmiProvider config={config}>
        <DynamicContextProvider
          settings={{
            environmentId: 'YOUR_ENVIRONMENT_ID',
            walletConnectors: [EthereumWalletConnectors],
          }}
        >
          <DynamicWagmiConnector>
            <DynamicWidget />
          </DynamicWagmiConnector>
        </DynamicContextProvider>
      </WagmiProvider>
    </QueryClientProvider>
  );
}
```

### Post-login patterns (apply to all setups)

```typescript
import { useDynamicContext } from '@dynamic-labs/sdk-react-core';

const { primaryWallet, user, handleLogOut } = useDynamicContext();

// Wallet address
primaryWallet?.address

// Chain ID (returns a number, not a name — map it yourself if you need a human-readable name)
primaryWallet?.chain

// Authenticated user
user?.email

// Logout
handleLogOut()
```

### Valid Combinations
- Any combination of chains is valid
- Wagmi only applies when EVM is selected
- Ethers connector only applies when EVM client is set to `ethers`

### Documentation
All docs for this SDK: https://docs.dynamic.xyz (paths starting with `/react/`)
Environment ID: https://app.dynamic.xyz/dashboard/developer

---

## Troubleshooting — Dashboard Configuration

If the app builds successfully but login fails, the widget doesn't open, wallets don't appear, or you see network/auth errors, the most common causes are Dynamic dashboard settings that haven't been configured. Ask the user to verify each of the following in their Dynamic dashboard at https://app.dynamic.xyz:

### 1 — Chains not enabled
The EVM chain (or any other chain used in the quickstart) must be enabled under **Chains & Networks** in the dashboard. If the chain isn't toggled on, wallet connection and signing will silently fail or return empty results.

### 2 — Login method not enabled
The login method the app uses (e.g. email OTP, social login, external wallets) must be toggled on under **Sign-in Methods**. If it isn't enabled, the auth flow will not appear or will fail silently inside the widget.

### 3 — Embedded wallets not enabled
If the app uses embedded (WaaS) wallets, the **Embedded Wallets** feature must be enabled under **Wallets** in the dashboard. Without it, no embedded wallet will be created after login.

### 4 — CORS origin not allowlisted
The URL the app is running on (e.g. `http://localhost:5173`) must be added to the **Allowed Origins** list in the dashboard under **Security**. Without it, all SDK requests will be blocked by CORS. Add the exact origin including port.

If all four are configured and the app is still not working, check the browser console for error codes and refer to https://docs.dynamic.xyz/overview/troubleshooting/general.