Skip to main content
In this tutorial you’ll build a minimal React application that authenticates a user with a passkey, reads their decentralized identity, and prints it to the console. By the end you’ll have a running HyperAuth integration and a clear mental model of the three pieces that make it work: the provider, the client, and the useHyperAuth hook.

What you’ll build

A single-page React app that:
  1. Wraps the app in HyperAuthProvider so every component can reach the client.
  2. Reads the client status with useHyperAuth.
  3. Creates a passkey and generates an identity with client.generate().
  4. Logs the resulting DID and Ethereum address to the browser console.

Prerequisites

  • Node 18+ and a package manager (npm, pnpm, or bun).
  • A React project bootstrapped with Vite.
  • A browser that supports WebAuthn (Chrome, Firefox, or Safari).
  • The WASM artifacts available at /enclave.wasm and /vault.wasm in your app’s public/ directory.

Steps

1

Install the packages

Open a terminal at your project root and run:
@hyperauth/sdk is the core client. @hyperauth/react provides the React bindings.
2

Set up the WASM artifacts

HyperAuthProvider spawns two browser workers when it initialises: a Dedicated Worker that loads enclave.wasm (the stateless signer) and a SharedWorker that loads vault.wasm (the stateful vault). Both binaries must be reachable by your app.For local development, copy the binaries into your app’s public/ directory:
For production, set VITE_WASM_BASE_URL to point at the R2 CDN and pass the URLs through to the provider:
If VITE_WASM_BASE_URL is unset, the SDK defaults to relative paths — the local-dev path served from public/.
3

Wrap your app in HyperAuthProvider

Open your root file — typically src/main.tsx — and wrap your <App /> in HyperAuthProvider:
src/main.tsx
HyperAuthProvider accepts an optional config prop. Omitting it uses the defaults, which is correct for local development when the WASM binaries are in public/. The provider spawns both workers in the background; your app continues rendering immediately.
4

Read the client with useHyperAuth

Create src/App.tsx with the following content:
src/App.tsx
useHyperAuth returns three values you’ll use constantly:
5

Create a passkey and generate an identity

Add the CreatePasskeyButton component to the same file, below App:
src/App.tsx
client.generate() returns a GenerateResult:
Keep result.shares — it is the encrypted key material you’ll pass to client.sign() in later operations.
6

Run the app and see your identity

Start the dev server:
Open http://localhost:5173, click Create passkey, and follow the browser’s WebAuthn prompt. You’ll see two lines appear in the browser console:
No server round-trip is needed to generate the identity. The DID and address are derived entirely inside the signer Dedicated Worker running in your browser.

What you have built

You now have a working HyperAuth integration with passkey authentication. HyperAuthProvider manages both worker lifecycles: a Dedicated Worker per tab for stateless signing (enclave.wasm) and a SharedWorker per origin for stateful vault storage (vault.wasm). useHyperAuth gives any component access to the client, and client.generate() ties a passkey credential to a self-sovereign identity. The shares value returned by generate() is the key you’ll carry into signing and registration. The next tutorial, Build a Registration Flow, shows how to use it to publish your identity on-chain.