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 theDocumentation Index
Fetch the complete documentation index at: https://docs.hyperauth.dev/llms.txt
Use this file to discover all available pages before exploring further.
useHyperAuth hook.
What you’ll build
A single-page React app that:- Wraps the app in
HyperAuthProviderso every component can reach the client. - Reads the client status with
useHyperAuth. - Creates a passkey and generates an identity with
client.generate(). - 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.wasmand/vault.wasmin your app’spublic/directory.
Steps
Install the packages
Open a terminal at your project root and run:
@hyperauth/sdk is the core client. @hyperauth/react provides the React bindings.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:VITE_WASM_BASE_URL to point at the R2 CDN and pass the URLs through to the provider: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.Read the client with useHyperAuth
Create
src/App.tsx with the following content:src/App.tsx
useHyperAuth returns three values you’ll use constantly:| Value | Type | Meaning |
|---|---|---|
client | HyperAuthClient | null | The initialised client, or null while loading |
status | 'initializing' | 'ready' | 'error' | Current provider state |
isReady | boolean | true when status === 'ready' and client !== null |
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.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.