Overview
HappyView provides JavaScript packages for building third-party apps that authenticate with a HappyView instance and make XRPC requests on behalf of users.
| Package | Purpose |
|---|---|
@happyview/lex-agent | Recommended: type-safe XRPC via @atproto/lex Client with HappyView DPoP auth |
@happyview/oauth-client | Platform-agnostic core: DPoP key provisioning, session management, authenticated fetch |
@happyview/oauth-client-browser | Browser OAuth client whose API matches @atproto/oauth-client-browser |
@happyview/oauth-client-node | Node.js OAuth client for server-side apps, matching @atproto/oauth-client-node |
Choosing a package
Section titled “Choosing a package”Starting a new app? Use @happyview/lex-agent with @atproto/lex. It gives you type-safe XRPC calls through a Client that routes requests to your HappyView instance with DPoP authentication.
Already using @atproto/api? HappyViewSession works directly as a session manager for @atproto/api’s Agent: pass it to new Agent(session). See Using with @atproto/api.
Already using @atproto/oauth-client-browser? Switch to @happyview/oauth-client-browser. Its HappyViewBrowserClient has the same shape of API, and runs the atproto OAuth flow itself with HappyView’s DPoP key provisioning and session registration added.
Building a server-side (Node.js) app? Use @happyview/oauth-client-node. It handles handle resolution, DID resolution, PDS discovery, and the full OAuth flow server-side. Matches the API surface of @atproto/oauth-client-node.
Building something more custom? Use @happyview/oauth-client directly and provide your own StorageAdapter.
How it works
Section titled “How it works”Third-party apps authenticate using HappyView’s DPoP key provisioning flow:
- The SDK requests a DPoP keypair from the HappyView instance.
- Your app runs a standard atproto OAuth flow with the user’s PDS using that keypair.
- The SDK registers the resulting tokens with HappyView.
- All subsequent XRPC requests are authenticated with DPoP proofs. HappyView handles its own lexicons locally and passes any other method to its XRPC proxy, which forwards it to the user’s PDS as the user only when the instance’s proxy routing is
serviceproxy.
If your app is a confidential atproto OAuth client, step 2 also needs a signed private_key_jwt assertion for its PAR and token-exchange requests. @happyview/oauth-client’s getClientAssertion() mints one. See Client assertions.
Quick start
Section titled “Quick start”npm install @happyview/lex-agent @happyview/oauth-client-browser @atproto/leximport { Client } from "@atproto/lex";import { HappyViewBrowserClient } from "@happyview/oauth-client-browser";import { createAgent } from "@happyview/lex-agent";
// Set up the OAuth clientconst oauthClient = new HappyViewBrowserClient({ instanceUrl: "https://happyview.example.com", clientId: "https://example.com/oauth-client-metadata.json", clientKey: "hvc_your_client_key",});
// Sign in: redirects to the user's PDSawait oauthClient.signIn("alice.bsky.social");
// On page load: restore session or process callbackconst result = await oauthClient.init();const session = result?.session;if (!session) throw new Error("Not signed in");
// Create a type-safe Lex clientconst agent = createAgent(session);const lex = new Client(agent);
// Make type-safe XRPC callsconst game = await lex.xrpc(myLexicons.com.example.getGame, { params: { slug: "celeste" },});Next steps
Section titled “Next steps”- Lex agent: type-safe XRPC with
@atproto/lex - OAuth client: platform-agnostic core client
- Browser client: browser OAuth redirect flow
- Node client: server-side OAuth flow
- Authentication: full details on DPoP key provisioning and API client types
© HappyProto

