React SDK (@hyperyai/sdk)

Drop-in React authentication and billing components — sign-in, user profile, conditional rendering, hooks, and mode-aware funds popups for any app that authenticates through the Hypery gateway.

@hyperyai/sdk is a drop-in React/Next.js library for signing users in through the Hypery gateway and reacting to billing state. The API is intentionally Clerk-like: wrap your app in one provider, then use <SignedIn> / <SignedOut>, <UserButton>, useUser(), and friends.

Installation

Install the package from npm. It ships compiled JavaScript plus type declarations, so no extra transpilation step is required.

npm install @hyperyai/sdk

Setup

Wrap your app once in HyperyProvider. Every component and hook reads from it.

// app/layout.tsx (Next.js App Router)
import { HyperyProvider } from '@hyperyai/sdk';
 
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <HyperyProvider
          config={{
            clientId: process.env.NEXT_PUBLIC_OAUTH_CLIENT_ID!,
            redirectUri: process.env.NEXT_PUBLIC_REDIRECT_URI!,   // e.g. https://yourapp.com/callback
            gatewayUrl: process.env.NEXT_PUBLIC_AUTH_URL!,        // the Hypery gateway, e.g. https://hypery.ai
            scopes: ['read', 'write', 'ai:chat', 'billing:read'],
            storage: 'localStorage',
          }}
        >
          {children}
        </HyperyProvider>
      </body>
    </html>
  );
}

The gateway issues 1-hour access tokens plus a refresh token. The provider refreshes silently in the background, so you generally never touch tokens directly — use useAuth().getAccessToken() when you need one for a fetch.

The full component gallery below is rendered from the auth-demo example app (in hyperyai/hypery-examples):

Component gallery overview

Authentication components

SignInForm

An embedded email/password + social login card. Use it when you want sign-in to live inline on a page rather than behind a modal or redirect.

SignInForm

import { SignInForm } from '@hyperyai/sdk';
 
<SignInForm
  showSocial            // Continue with Google / GitHub
  showEmailPassword
  title="Welcome back"
  description="Sign in to continue"
  onSuccess={(user) => router.push('/dashboard')}
  onError={(err) => toast.error(err.message)}
/>
PropTypeDescription
showCardbooleanWrap in a card surface (default true)
showSocialbooleanShow Google/GitHub buttons
showEmailPasswordbooleanShow the email/password form
title / descriptionstringHeading copy
onSuccess / onError(arg) => voidResult callbacks

AuthModal

A controlled modal for sign-in / sign-up — ideal for a "Sign in" button in a navbar. Supports custom branding (logo, app name, primary color).

AuthModal (open)

import { AuthModal } from '@hyperyai/sdk';
 
const [open, setOpen] = useState(false);
 
<button onClick={() => setOpen(true)}>Sign in</button>
<AuthModal
  isOpen={open}
  onClose={() => setOpen(false)}
  initialMode="signin"            // or "signup"
  showSocial
  showEmailPassword
  branding={{ appName: 'Acme', primaryColor: '#06b6d4' }}
  onSuccess={() => setOpen(false)}
/>

SignIn / SignUp / AuthButton

Drop-in buttons that start the sign-in / sign-up flow (modal or redirect). Three visual variants: primary, secondary, outline. AuthButton is the lower-level button both are built on.

<SignIn /><SignUp />
SignInSignUp
import { SignIn, SignUp } from '@hyperyai/sdk';
 
<SignIn buttonText="Try Sign In" variant="primary" />
<SignUp buttonText="Try Sign Up" variant="secondary" />

UserButton / UserProfile

UserButton is an avatar + dropdown (profile, billing, sign out); UserProfile is an inline profile card. Both render only when the user is authenticated — signed out, they show a placeholder.

<UserButton /><UserProfile />
UserButtonUserProfile
import { UserButton, UserProfile } from '@hyperyai/sdk';
 
<UserButton showUserInfo size="md" />   // size: 'sm' | 'md' | 'lg'
<UserProfile />

WorkspaceSwitcher

A dropdown for users who belong to multiple teams / workspaces. Reads from useMemberships() and switches the active workspace used for billing and scoping.

import { WorkspaceSwitcher } from '@hyperyai/sdk';
 
<WorkspaceSwitcher
  onChange={(workspace) => console.log('active:', workspace.slug)}
/>

Conditional rendering

Render-gate components — they have no UI of their own; they show or hide children based on auth state.

import { SignedIn, SignedOut, Protect, RedirectToSignIn } from '@hyperyai/sdk';
 
<SignedIn><Dashboard /></SignedIn>
<SignedOut><SignIn /></SignedOut>
 
{/* Require a scope/permission, with a fallback */}
<Protect scope="billing:read" fallback={<p>No access</p>}>
  <BillingPanel />
</Protect>
 
{/* Force a redirect to sign-in when signed out */}
<SignedOut><RedirectToSignIn /></SignedOut>
ComponentRenders children when
<SignedIn>the user is authenticated
<SignedOut>the user is not authenticated
<Protect scope="...">the user holds the given scope (else fallback)
<RedirectToSignIn>always — triggers the OAuth redirect

Hooks

import { useUser, useAuth, useError, useWallet, useMemberships } from '@hyperyai/sdk';
 
const { user, isLoading } = useUser();
const { isAuthenticated, login, logout, getAccessToken } = useAuth();
 
// Structured gateway errors (spending limit / insufficient credits / payment method)
const { error, setError, clearError, isBillingRestriction } = useError();
 
// Wallet state + 1-click funding (see Billing components)
const { wallet, addFunds, addPaymentMethod } = useWallet();
 
// The user's teams + workspaces (for a workspace switcher)
const { data } = useMemberships();
HookReturns
useUser(){ user, isLoading }
useAuth(){ isAuthenticated, login, logout, getAccessToken }
useWallet(){ wallet, addFunds, addPaymentMethod }wallet.mode is 'vag_passthrough', 'metered', or 'prepaid' (funds actions apply to the wallet modes only)
useError(){ error, setError, clearError, isBillingRestriction }
useMemberships(){ data } — teams + workspaces the user belongs to

Billing components

These render on a consumer site when a request hits a billing limit. They are mode-aware (prepaid vs. metered) and read live wallet state from the gateway.

These components apply only to the credit-wallet modes (metered / prepaid). In vag_passthrough (the default) there is no wallet — usage is metered to Stripe directly by the Vercel AI Gateway — so useWallet() reports mode: 'vag_passthrough' with a null balance and the funds popups do not apply. See Billing & Credits.

In metered mode the popup offers "Add a payment method" (Stripe-hosted Checkout — no Elements), after which usage is auto-billed. In prepaid mode it offers true 1-click "Add $X" that charges the saved card in place. See Billing & Credits for how the mode is chosen.

  • <RestrictionModal /> — pops up on INSUFFICIENT_CREDITS, PAYMENT_METHOD_REQUIRED, or SPENDING_LIMIT_EXCEEDED.
  • <SpendingLimitAlert />, <InsufficientCreditsAlert /> — inline alert variants for the same conditions.
  • <ErrorBoundary /> — catches render errors and surfaces a friendly fallback.
import { RestrictionModal, useError, useAuth } from '@hyperyai/sdk';
 
const { error, clearError } = useError();
const { getAccessToken } = useAuth();
 
<RestrictionModal
  error={error}
  gatewayUrl={process.env.NEXT_PUBLIC_AUTH_URL!}
  getAccessToken={getAccessToken}
  onClose={clearError}
  onRetry={retryRequest}
/>

The matching error codes are parsed for you by useError() / parseError():

CodeHTTPMeaning
INSUFFICIENT_CREDITS402Prepaid balance is empty
PAYMENT_METHOD_REQUIRED402Metered mode, no card on file
PAYMENT_DECLINED402Metered auto-charge was declined
SPENDING_LIMIT_EXCEEDED429A configured spending limit was hit

Screenshots above are generated from the auth-demo example app (in hyperyai/hypery-examples, /examples). To regenerate, run the demo and re-capture into the SDK's docs/screenshots/.