kavachOS

React hooks

Client-side React hooks for KavachOS auth.

Overview

@kavachos/react provides React hooks and a context provider for building auth UIs on top of KavachOS. It works with Next.js App Router, Next.js Pages Router, Vite, and any React 18+ setup.

The package itself has no Node.js dependencies — it runs entirely in the browser. Your KavachOS API handler can sit behind Next.js Edge Runtime, Cloudflare Workers, Deno Deploy, or any other edge runtime, and the hooks talk to it over standard fetch.

All hooks must be rendered inside KavachProvider. The provider talks to your KavachOS API route — no direct database access from the browser.

Installation

pnpm add @kavachos/react

Provider setup

Wrap your app with KavachProvider. In Next.js App Router, create a client component and import it from your root layout.

// app/providers.tsx
'use client';
import { KavachProvider } from '@kavachos/react';

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <KavachProvider basePath="/api/kavach">
      {children}
    </KavachProvider>
  );
}
// app/layout.tsx
import { Providers } from './providers';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}

Prop

Type

Sessions are stored in localStorage under the key kavach_session. The hooks automatically restore the session on page reload.

useSession

Returns the raw session object. Useful when you need the session token or expiry directly.

import { useSession } from '@kavachos/react';

function SessionDebug() {
  const { session, isLoading } = useSession();

  if (isLoading) return <p>Loading...</p>;
  if (!session) return <p>No active session.</p>;

  return (
    <p>
      Session expires: {new Date(session.expiresAt).toLocaleString()}
    </p>
  );
}

Prop

Type

useUser

Returns the authenticated user and a boolean flag. This is the most common hook for protecting UI.

import { useUser } from '@kavachos/react';

function ProfileCard() {
  const { user, isAuthenticated, isLoading } = useUser();

  if (isLoading) return <Skeleton />;
  if (!isAuthenticated) return <SignInPrompt />;

  return (
    <div>
      <p>{user.name}</p>
      <p>{user.email}</p>
    </div>
  );
}

Prop

Type

useSignIn

Handles email and password sign-in. Returns a signIn function and state fields.

The hook posts to POST /api/kavach/auth/sign-in (not /sign-in/email). Make sure your adapter is mounted at /api/kavach.

import { useSignIn } from '@kavachos/react';
import { useRouter } from 'next/navigation';

function SignInForm() {
  const { signIn, isLoading, error } = useSignIn();
  const router = useRouter();

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    const result = await signIn({
      email: form.get('email') as string,
      password: form.get('password') as string,
    });
    if (result.success) router.push('/dashboard');
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="email" type="email" />
      <input name="password" type="password" />
      {error && <p>{error.message}</p>}
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Signing in...' : 'Sign in'}
      </button>
    </form>
  );
}

useSignUp

Handles new account registration. Posts to POST /api/kavach/auth/sign-up (not /sign-up/email).

import { useSignUp } from '@kavachos/react';

function SignUpForm() {
  const { signUp, isLoading, error } = useSignUp();

  async function handleSubmit(e: React.FormEvent<HTMLFormElement>) {
    e.preventDefault();
    const form = new FormData(e.currentTarget);
    await signUp({
      email: form.get('email') as string,
      password: form.get('password') as string,
      name: form.get('name') as string,
    });
  }

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" type="text" />
      <input name="email" type="email" />
      <input name="password" type="password" />
      {error && <p>{error.message}</p>}
      <button type="submit" disabled={isLoading}>Create account</button>
    </form>
  );
}

useSignOut

Signs the user out and clears the local session. Optionally redirects after sign-out.

import { useSignOut } from '@kavachos/react';

function NavBar() {
  const { signOut } = useSignOut();

  return (
    <nav>
      <button onClick={() => signOut({ redirectTo: '/login' })}>
        Sign out
      </button>
    </nav>
  );
}

useAgents

Lets your UI create, list, and revoke agents without going through a custom API route.

import { useAgents } from '@kavachos/react';

function Dashboard() {
  const { user, isAuthenticated, isLoading } = useUser();
  const { agents, create, revoke, isLoading: agentsLoading } = useAgents();

  if (!isAuthenticated) return null;

  async function handleCreate() {
    await create({
      name: 'my-bot',
      type: 'autonomous',
      permissions: [
        { resource: 'reports:*', actions: ['read'] },
      ],
    });
  }

  return (
    <div>
      <button onClick={handleCreate}>New agent</button>
      {agentsLoading && <p>Loading agents...</p>}
      {agents.map((agent) => (
        <div key={agent.id}>
          <span>{agent.name}</span>
          <button onClick={() => revoke(agent.id)}>Revoke</button>
        </div>
      ))}
    </div>
  );
}

Prop

Type

Next steps

On this page