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.

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

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.

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.

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