> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# React Quickstart

<Card title="Recommended: JavaScript SDK with React Hooks" icon="react" href="/javascript/reference/react-quickstart" color="#4779FE">
  For new React apps, we recommend the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) instead of the legacy React SDK documented here. The JS SDK comes with many benefits such as a much smaller bundle size and other optimizations. Use the [React quickstart (JavaScript SDK)](/javascript/reference/react-quickstart) to get started.
</Card>

Get started with Dynamic's React SDK to add embedded wallets, multi-chain support, and flexible authentication (email, social login, passkeys) to your app in just a few lines.

<Note>
  Before you start: You’ll need Node.js 18+ and a Dynamic environment ID from the [Dynamic dashboard](https://app.dynamic.xyz/dashboard/developer).
</Note>

<Tabs>
  <Tab title="Agent-friendly">
    <Tip>
      Add the Dynamic docs MCP to your AI editor first — your agent can then query the docs directly.
    </Tip>

    <Tabs>
      <Tab title="Cursor">
        [Click here to add the MCP to Cursor.](https://cursor.com/en/install-mcp?name=dynamic\&config=eyJ1cmwiOiJodHRwczovL3d3dy5keW5hbWljLnh5ei9kb2NzL21jcCJ9)
      </Tab>

      <Tab title="Claude Code">
        ```bash theme={"system"}
        claude mcp add --transport http dynamic https://www.dynamic.xyz/docs/mcp
        ```
      </Tab>

      <Tab title="Codex">
        ```bash theme={"system"}
        codex mcp add dynamic --url https://www.dynamic.xyz/docs/mcp
        ```
      </Tab>

      <Tab title="Other">
        If your editor or agent supports remote HTTP MCP, add a server that points at `https://www.dynamic.xyz/docs/mcp`. The exact steps depend on the product; use its MCP documentation for URL-based or HTTP transport setup.
      </Tab>
    </Tabs>

    <Warning>
      **New React app?** Use the agent prompt on the [React quickstart (JavaScript SDK)](/javascript/reference/react-quickstart) instead. Dynamic recommends the JavaScript SDK with React Hooks (`@dynamic-labs-sdk/react-hooks`) over the React SDK on this page.
    </Warning>

    Copy this prompt into your LLM only if the project already uses or explicitly requires the React SDK (`@dynamic-labs/sdk-react-core`).

    <div data-llm-quickstart>
      ````markdown theme={"system"}
      # React SDK Quickstart

      ## Default for React apps — use the JavaScript SDK instead

      **Stop and read this first.** If the user wants to add Dynamic to a **React** app, the default is **not** this document.

      **Preferred path for React:** Use the **JavaScript SDK with React Hooks** (`@dynamic-labs-sdk/react-hooks`). Follow the agent prompt in the [React quickstart (JavaScript SDK)](https://www.dynamic.xyz/docs/javascript/reference/react-quickstart) (agent prompt id: `javascript-react`).

      **Use this React SDK quickstart only when:**
      - The codebase already uses `@dynamic-labs/sdk-react-core`
      - The user explicitly requests the React SDK, `DynamicContextProvider`, `DynamicWidget`, or React SDK + Wagmi integration

      If neither applies, tell the user you are using the JavaScript SDK path and switch to the JavaScript SDK React quickstart before writing any code.

      ---

      ## Purpose and Usage

      This document provides structured quickstart information for the Dynamic React SDK (`@dynamic-labs/sdk-react-core`). It is designed to be consumed by LLMs to generate accurate installation commands and code examples based on user requirements.

      **Do not use this document for new React integrations** unless the user meets the criteria in **Default for React apps** above.

      **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/api

      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, TON, Aptos, Aleo — 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`
      - TON: `@dynamic-labs/ton`
      - Aptos: `@dynamic-labs/aptos`
      - Aleo: `@dynamic-labs/aleo`
      - Wagmi (EVM only, optional): `@dynamic-labs/wagmi-connector wagmi @tanstack/react-query`

      > **Wagmi version:** The latest compatible version is Wagmi v3 (v3.1.0+). You may see some dependency warnings related to `DynamicWagmiConnector` because the package still uses some Wagmi v2 packages internally — these are safe to ignore and will be updated in a future release.

      ### 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`
      - `TON` → `TonWalletConnectors` from `@dynamic-labs/ton`
      - `Aptos` → `AptosWalletConnectors` from `@dynamic-labs/aptos`
      - `Aleo` → `AleoWalletConnectors` from `@dynamic-labs/aleo`

      ### 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/api

      ---

      ## Building a headless integration?

      If you're building without the Dynamic Widget, see the [Authentication screens](/react/authentication-methods/headless-authentication) for a full list of screens your app needs to handle.

      ---

      ## Step-Up Authentication

      **Required before accepting the `2026_04_01` API version** — verify your
      minimum API version in [Dashboard > Developers > API & SDK Keys](https://app.dynamic.xyz/dashboard/developer/api).

      If using `DynamicWidget` or Dynamic's built-in UI, step-up prompts are
      handled automatically. **If building a headless/custom UI, you must handle
      step-up authentication manually** using the `useStepUpAuthentication` hook
      — check requirements, trigger verification, and wait for the elevated token
      before proceeding with the sensitive operation.

      See [Step-up authentication](/react/authentication-methods/step-up-auth/overview) for the full implementation guide.

      ---

      ## Device Registration

      **Required before accepting the `2026_04_01` API version** — verify your
      minimum API version in [Dashboard > Developers > API & SDK Keys](https://app.dynamic.xyz/dashboard/developer/api).

      If using Dynamic's built-in UI (default), device registration is handled
      automatically — no code required. **If building a headless/custom UI**
      (`deviceRegistrationModal: { enabled: false }`), **you must manually check
      whether the current device needs registration and handle the completion
      event yourself.**

      Full guide: https://docs.dynamic.xyz/react/authentication-methods/device-registration

      ---

      ## 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.
      ````
    </div>
  </Tab>

  <Tab title="Visual">
    ## Install and initialize the SDK

    <iframe frameBorder="0" width="100%" height="600px" src="https://documentation-quickstarts.vercel.app/react?color-scheme=dark" allow="clipboard-write" className="rn-qs-dark">
      {' '}
    </iframe>

    <iframe frameBorder="0" width="100%" height="600px" src="https://documentation-quickstarts.vercel.app/react?color-scheme=light" allow="clipboard-write" className="rn-qs-light">
      {' '}
    </iframe>

    <Tip>
      EthereumWalletConnectors also includes all EVM compatible chains including
      layer 2's i.e. Base as well as [Dynamic Embedded
      Wallets](/react/wallets/embedded-wallets/mpc/setup). Learn more about WalletConnectors [here](/react/reference/providers/dynamiccontextprovider#walletconnectors).
    </Tip>

    ## Configure your UI and signup

    The quickstart embed above includes the DynamicWidget, which provides out of the box UI. If you prefer to use your own UI, remove `DynamicWidget` from the code, and refer to the "Using Your UI" section of any guide to see how to add it in a custom UI. Below we've listed some of the common signup options for you to configure in your own Dynamic environment.

    <CardGroup>
      <Card href="/react/authentication-methods/email">
        Add email signup
      </Card>

      <Card href="/react/authentication-methods/sms">
        Add sms signup
      </Card>

      <Card href="/react/authentication-methods/social">
        Add social signup
      </Card>

      <Card href="/react/authentication-methods/passkey">
        Add passkey signup
      </Card>

      <Card href="/react/authentication-methods/external-wallets">
        Add external wallet signup
      </Card>
    </CardGroup>

    <Note>
      If you are using Wagmi, make sure to read our [full Wagmi
      guide](/react/reference/using-wagmi) for more setup instructions.
    </Note>

    <Tip>
      If you're using Vite, you'll need to check out [the polyfills guide](/overview/troubleshooting/react/vitejs-polyfills-necessary-for-dynamic-sdk).

      If you see any other errors, it's worth checking out [Dynamic Doctor](/overview/troubleshooting/dynamic-doctor) for quick debugging tips!
    </Tip>

    <Tip>
      To quickly test the login flow, you can enable [Test
      Accounts](/overview/developer-dashboard/test-accounts) in Sandbox mode.
    </Tip>

    ## Next Steps

    <Warning>
      **Step-up authentication** and **device registration** are required
      before accepting the `2026_04_01` API version. If you have a headless
      integration, you must implement both manually.
      See the [upgrade guide](/overview/migrations/api/2026_04_01).
    </Warning>

    * [Step-up authentication](/react/authentication-methods/step-up-auth/overview)
    * [Device registration](/react/authentication-methods/device-registration)

    <Info>
      Building without the Dynamic Widget? See the [Authentication screens](/react/authentication-methods/headless-authentication) for a full list of screens your app needs to handle.
    </Info>
  </Tab>
</Tabs>
