# Quickstart React — Passkey recovery

<div className="flex flex-wrap items-center justify-end gap-3 mb-6">
  <MultiOptionDisplay
    options={[
    { id: 'ethereum', label: 'Ethereum' },
    { id: 'solana', label: 'Solana' },
  ]}
    defaultSelectedId="ethereum"
    storageKey="openfort-chain-preference"
    className="!pt-0 shrink-0 w-[180px]"
  />
</div>

This guide walks you through the React quickstart with **passkey recovery** enabled out of the box.

Prefer another recovery flow? Switch to the [automatic guide](/docs/products/embedded-wallet/react) or the [password guide](/docs/products/embedded-wallet/react/quickstart/password#choose-your-recovery-method).

## Install Openfort with the CLI

:::code-group

```sh [pnpm]
pnpm create openfort
```

```sh [npm]
npm create openfort
```

```sh [yarn]
yarn create openfort
```

:::

The **Openfort CLI** helps you set up a new project with all dependencies and configurations. You can select framework (Vite or Next.js), authentication providers, embedded wallet, and UI theming.

## Install manually (step by step)

::::steps

### Install dependencies

<span data-chain="ethereum" className="hidden [&>*]:mb-6!">
  Install [@openfort/react](https://www.npmjs.com/package/@openfort/react) with wagmi, TanStack Query, and viem:

  :::code-group

  ```sh [pnpm]
  pnpm add @openfort/react wagmi viem@^2.22.0 @tanstack/react-query
  ```

  ```sh [npm]
  npm install @openfort/react wagmi viem@^2.22.0 @tanstack/react-query
  ```

  ```sh [yarn]
  yarn add @openfort/react wagmi viem@^2.22.0 @tanstack/react-query
  ```

  :::
</span>

<span data-chain="solana" className="hidden [&>*]:mb-6!">
  Install [@openfort/react](https://www.npmjs.com/package/@openfort/react) with [@solana/kit](https://www.npmjs.com/package/@solana/kit):

  :::code-group

  ```sh [pnpm]
  pnpm add @openfort/react @solana/kit
  ```

  ```sh [npm]
  npm install @openfort/react @solana/kit
  ```

  ```sh [yarn]
  yarn add @openfort/react @solana/kit
  ```

  :::
</span>

### Get your Openfort API keys

In the [API keys](https://dashboard.openfort.io/api-keys) section of [Openfort dashboard](https://dashboard.openfort.io), you will find:

* **Publishable Key**: Safe to expose in client-side environment
* **Secret Key**: Must be kept secure and used only server-side

To generate non-custodial wallets:

1. Scroll to the Shield section and click **Create Shield keys**
2. **Store the encryption share** safely when it appears (you'll only see it once)
3. You'll receive:
   * **Shield Publishable Key**: Safe for client-side use
   * **Shield Secret Key**: Keep secure, server-side only

<span id="choose-your-recovery-method" className="hidden" />

### Choose your recovery method

Decide which wallet recovery experience you want to ship:

* [Automatic recovery](/docs/products/embedded-wallet/react) — no action from the user required.
* **Passkey recovery** — biometric or device authentication with no backend endpoint.
* [Password recovery](/docs/products/embedded-wallet/react/quickstart/password#choose-your-recovery-method) — user sets their own password with no backend endpoint.

:::info\[About passkeys]
Passkeys let users authenticate with device biometrics (Face ID, Touch ID, fingerprint). Keys are stored in the device's secure enclave and sync across devices via iCloud Keychain or Google Password Manager.
:::

:::warning\[Domain-bound credentials]
WebAuthn credentials are bound to a specific domain. Credentials created for your domain (e.g., `example.com`) only work on that domain and its subdomains—they cannot be used on other domains.

**This means users cannot use the same passkey wallet on other applications.** If your product spans multiple domains, consider using [automatic recovery](/docs/products/embedded-wallet/react#choose-your-recovery-method) instead.
:::

### Set up providers

<span data-chain="ethereum" className="hidden [&>*]:mb-6!">
  Use `getDefaultConfig` from `@openfort/react/wagmi`, wrap with `WagmiProvider`, `QueryClientProvider`, and `OpenfortWagmiBridge`. More information on the wallet configuration can be found [here](/docs/products/embedded-wallet/react/wallet).

  :::info
  If using Next.js, add `'use client'` at the top of the file.
  :::

  ```tsx [Providers.tsx]
  import React from "react";
  import {
    AuthProvider,
    OpenfortProvider,
    RecoveryMethod,
  } from "@openfort/react";
  import { getDefaultConfig, OpenfortWagmiBridge } from "@openfort/react/wagmi";
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
  import { WagmiProvider, createConfig } from "wagmi";
  import { baseSepolia } from "viem/chains";

  const config = createConfig(
    getDefaultConfig({
      appName: "Openfort Demo App",
      chains: [baseSepolia],
      ssr: true,
    })
  );

  const queryClient = new QueryClient();

  export function Providers({ children }: { children: React.ReactNode }) {
    return (
      <QueryClientProvider client={queryClient}>
        <WagmiProvider config={config}>
          <OpenfortWagmiBridge>
            <OpenfortProvider
              publishableKey={"YOUR_OPENFORT_PUBLISHABLE_KEY"}
              walletConfig={{
                shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
                ethereum: { chainId: 84532 },
                // Optional: customize the passkey display names
                // passkeyRpName: "Your App Name",
                // passkeyDisplayName: "My Wallet",
              }}
              uiConfig={{
                authProviders: [
                  AuthProvider.EMAIL_OTP,
                  AuthProvider.GUEST,
                  AuthProvider.GOOGLE,
                  AuthProvider.WALLET,
                  // More: https://www.openfort.io/docs/products/embedded-wallet/react/auth
                ],
                walletRecovery: {
                  defaultMethod: RecoveryMethod.PASSKEY,
                },
              }}
            >
              {children}
            </OpenfortProvider>
          </OpenfortWagmiBridge>
        </WagmiProvider>
      </QueryClientProvider>
    );
  }
  ```

  <details>
    <summary style={{ margin: '20px 0 12px 0', fontSize: 16, fontWeight: 500 }}>Need WalletConnect support?</summary>

    Add `walletConnectProjectId` to `getDefaultConfig`. Get a project ID from the [WalletConnect dashboard](https://cloud.reown.com/sign-in).
  </details>
</span>

<span data-chain="solana" className="hidden [&>*]:mb-6!">
  Use `OpenfortProvider` with `solana` in `walletConfig`. No Wagmi required. More information on the wallet configuration can be found [here](/docs/products/embedded-wallet/react/wallet).

  :::info
  If using Next.js, add `'use client'` at the top of the file.
  :::

  ```tsx [Providers.tsx]
  import React from "react";
  import {
    AuthProvider,
    OpenfortProvider,
    RecoveryMethod,
  } from "@openfort/react";
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

  const queryClient = new QueryClient();

  export function Providers({ children }: { children: React.ReactNode }) {
    return (
      <QueryClientProvider client={queryClient}>
        <OpenfortProvider
          publishableKey={"YOUR_OPENFORT_PUBLISHABLE_KEY"}
          walletConfig={{
            shieldPublishableKey: "YOUR_SHIELD_PUBLISHABLE_KEY",
            solana: { cluster: "devnet" },
            // Optional: customize the passkey display names
            // passkeyRpName: "Your App Name",
            // passkeyDisplayName: "My Wallet",
          }}
          uiConfig={{
            authProviders: [
              AuthProvider.EMAIL_OTP,
              AuthProvider.GUEST,
              AuthProvider.GOOGLE,
              // External wallets (WALLET) are not supported on Solana
              // More: https://www.openfort.io/docs/products/embedded-wallet/react/auth
            ],
            walletRecovery: {
              defaultMethod: RecoveryMethod.PASSKEY,
            },
          }}
        >
          {children}
        </OpenfortProvider>
      </QueryClientProvider>
    );
  }
  ```
</span>

### You're good to go!

Once you've configured your app, wrap it in the `Providers` component and drop in Openfort UI elements where you need them.

```tsx [App.tsx]
import React from "react";
import { Providers } from "./Providers";
import { OpenfortButton } from "@openfort/react";

export default function App() {
  return (
    <Providers>
      {/* Your app content */}
      <OpenfortButton />
    </Providers>
  );
}
```

::::

## Next steps

Now that you've set up Openfort, you can explore more features and customization options:

* [UI Configuration](/docs/products/embedded-wallet/react/ui)
