> ## 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.

# Setup on Expo

> Install and configure the JavaScript SDK in an Expo React Native app.

This guide sets up the JavaScript SDK in an [Expo](https://expo.dev) app. These steps configure the native modules and polyfills the SDK needs for cross-platform compatibility.

<Note>
  Before you start: an Expo app and a Dynamic environment ID from the [Dynamic dashboard](https://app.dynamic.xyz). For a bare React Native app, use [Setup on Bare React Native](/docs/javascript/react-native/bare-react-native) instead.
</Note>

<Warning>
  Expo Go is not supported. The SDK depends on native modules that are linked only when you build the native app with `npx expo prebuild`. Use a development build or EAS Build.
</Warning>

## Install dependencies

<Steps>
  <Step title="Install the core packages">
    Install the SDK packages and their peer dependencies.

    ```shell theme={"system"}
    npx expo install \
      @dynamic-labs-sdk/client \
      @dynamic-labs-sdk/react-hooks \
      @tanstack/react-query \
      @react-native-async-storage/async-storage \
      react-native-keychain \
      expo-linking
    ```
  </Step>

  <Step title="Install the polyfills">
    Install the polyfills required for secure operations.

    ```shell theme={"system"}
    npx expo install \
      expo-crypto \
      buffer
    ```

    <Note>
      You may already have some of these polyfills installed. Install only the ones your project is missing.
    </Note>
  </Step>
</Steps>

## Feature packages

The packages above cover email, wallet, and session basics. Each feature below needs an extra package — install it only when you use that feature, then follow its guide.

| Feature                    | Install                                                                         | Guide                                                                                |
| -------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
| Social / OAuth login       | `react-native-inappbrowser-reborn`                                              | [Social login](/docs/javascript/authentication-methods/social)                            |
| WalletConnect              | `@walletconnect/react-native-compat`                                            | [WalletConnect integration](/docs/javascript/reference/wallets/walletconnect-integration) |
| Passkeys                   | `react-native-passkey`                                                          | [React Native Passkeys](/docs/javascript/react-native/passkeys)                           |
| EVM / Solana chains        | `@dynamic-labs-sdk/evm`, `@dynamic-labs-sdk/solana`                             | [Add the EVM extension](/docs/javascript/reference/evm/adding-evm-extensions)             |
| Export embedded wallet key | `@dynamic-labs-sdk/react-native-embedded-wallet-export`, `react-native-webview` | [Export WaaS private key](/docs/javascript/reference/waas/exporting-waas-private-key)     |

## Create a polyfills file

Create a `polyfills.ts` file at the root of your project. It shims the Buffer implementation and the Crypto API that secure operations rely on.

```ts polyfills.ts theme={"system"}
import { Buffer } from 'buffer';
import { getRandomValues, randomUUID } from 'expo-crypto';

/**
 * Base polyfill for crypto.
 */
if (!global.crypto) {
  // @ts-expect-error — partial Crypto implementation
  global.crypto = {};
}
if (!global.crypto.getRandomValues) {
  // @ts-expect-error — partial Crypto implementation
  global.crypto.getRandomValues = getRandomValues;
}
if (!global.crypto.randomUUID) {
  // @ts-expect-error — partial Crypto implementation
  global.crypto.randomUUID = randomUUID;
}

/**
 * Buffer polyfill for Solana and various cryptographic operations.
 */
global.Buffer = Buffer;
```

<Note>
  Using WalletConnect? Install `@walletconnect/react-native-compat` and add `import '@walletconnect/react-native-compat';` as the **first** import in `polyfills.ts`, above the crypto shims — the WalletConnect relay client requires it to load before anything WalletConnect-related. See [WalletConnect integration](/docs/javascript/reference/wallets/walletconnect-integration).
</Note>

## Configure a custom entry point

To guarantee the polyfills run before any other code, add a custom entry point.

<Steps>
  <Step title="Create index.ts">
    Create an `index.ts` file at the root of your project:

    ```ts index.ts theme={"system"}
    // Polyfills must run before any other import
    import './polyfills';
    import 'expo-router/entry';
    ```
  </Step>

  <Step title="Point package.json to it">
    Update the `main` field in `package.json`:

    ```json package.json theme={"system"}
    {
      "main": "./index.ts"
    }
    ```
  </Step>
</Steps>

## Rebuild the native app

After adding native modules such as `expo-crypto`, rebuild your development build so the native code is linked.

```shell theme={"system"}
# Clean and prebuild native directories
npx expo prebuild --clean

# Run on your preferred platform
npx expo run:ios
npx expo run:android
```

## Initialize the Dynamic client

Create a `dynamicClient.ts` file in your project root or a shared configuration folder. This client is your primary interface to the SDK.

```ts dynamicClient.ts theme={"system"}
import { createDynamicClient } from '@dynamic-labs-sdk/client';

export const dynamicClient = createDynamicClient({
  environmentId: 'YOUR_ENVIRONMENT_ID', // Found in your Dynamic dashboard
  /* Additional configuration options */
});
```

For a full reference of the options, see [Creating a Dynamic Client](/docs/javascript/reference/client/create-dynamic-client) and [Initializing the Dynamic Client](/docs/javascript/reference/client/initialize-dynamic-client).

## Next steps

Your Expo app is set up. From here, wrap your app in the React hooks provider, add the chains you support, and the rest of your integration works the same as on the web — the guides below apply unchanged unless they show an **Expo** tab.

<CardGroup cols={2}>
  <Card title="Set up the React hooks" icon="react" href="/docs/javascript/reference/react-hooks">
    Wrap your app in `QueryClientProvider` and `DynamicProvider` to use the hooks.
  </Card>

  <Card title="Add the EVM extension" icon="puzzle-piece" href="/docs/javascript/reference/evm/adding-evm-extensions">
    Register EVM (or another chain) so the client can connect wallets and sign.
  </Card>

  <Card title="WalletConnect integration" icon="link" href="/docs/javascript/reference/wallets/walletconnect-integration">
    Connect external wallets over WalletConnect — see the **Expo** tab for deep linking.
  </Card>

  <Card title="Authenticate with email" icon="envelope" href="/docs/javascript/authentication-methods/email">
    Send an email OTP and verify the user.
  </Card>

  <Card title="Build a wallet picker" icon="wallet" href="/docs/javascript/reference/wallets/build-wallet-picker">
    List wallet providers and connect a wallet.
  </Card>
</CardGroup>

<Tip>
  Running into issues? See [Troubleshooting](/docs/overview/troubleshooting/general) in the Overview docs.
</Tip>
