PersonQL React SDK

A comprehensive React SDK for PersonQL authentication and user management. This SDK provides pre-built components, hooks, and utilities to quickly integrate PersonQL authentication into your React applications.

Features

Installation

npm install @personql/react
# or
yarn add @personql/react
# or
pnpm add @personql/react

Quick Start

1. Setup the Provider

Wrap your app with the PersonQLProvider:

import React from 'react';
import { PersonQLProvider } from '@personql/react';
 
const config = {
  apiUrl: 'https://app.personql.com',
  clientId: 'your-client-id',
};
 
function App() {
  return (
    <PersonQLProvider config={config}>
      <YourAppContent />
    </PersonQLProvider>
  );
}

2. Use Authentication Components

import React, { useState } from 'react';
import { SignInForm, SignUpForm, useAuth } from '@personql/react';
 
function AuthPage() {
  const [showSignUp, setShowSignUp] = useState(false);
  const { isAuthenticated } = useAuth();
 
  if (isAuthenticated) {
    return <Dashboard />;
  }
 
  return (
    <div className="min-h-screen flex items-center justify-center">
      {showSignUp ? (
        <SignUpForm
          onSuccess={() => console.log('Sign up successful!')}
          onSignIn={() => setShowSignUp(false)}
        />
      ) : (
        <SignInForm
          onSuccess={() => console.log('Sign in successful!')}
          onSignUp={() => setShowSignUp(true)}
        />
      )}
    </div>
  );
}

3. Protect Routes with AuthGuard

import React from 'react';
import { AuthGuard } from '@personql/react';
 
function ProtectedPage() {
  return (
    <AuthGuard
      fallback={<div>Please sign in to access this page</div>}
      requireVerification={true}
    >
      <h1>Protected Content</h1>
      <p>Only authenticated and verified users can see this.</p>
    </AuthGuard>
  );
}

Components

Authentication Forms

SignInForm

import { SignInForm } from '@personql/react';
 
<SignInForm
  onSuccess={() => navigate('/dashboard')}
  onSignUp={() => setShowSignUp(true)}
  onForgotPassword={() => setShowForgotPassword(true)}
  className="max-w-md mx-auto"
/>;

SignUpForm

import { SignUpForm } from '@personql/react';
 
<SignUpForm
  onSuccess={() => navigate('/dashboard')}
  onSignIn={() => setShowSignUp(false)}
  className="max-w-md mx-auto"
/>;

MFAForm

import { MFAForm } from '@personql/react';
 
<MFAForm
  onSuccess={() => navigate('/dashboard')}
  onCancel={() => navigate('/signin')}
/>;

ProfileForm

import { ProfileForm } from '@personql/react';
 
<ProfileForm
  onSuccess={() => setShowSuccess(true)}
  className="max-w-2xl mx-auto"
/>;

Route Protection

AuthGuard

import { AuthGuard } from '@personql/react';
 
<AuthGuard
  fallback={<SignInPrompt />}
  redirectTo="/signin"
  requireVerification={true}
>
  <ProtectedContent />
</AuthGuard>;

Hooks

useAuth

Main authentication hook:

import { useAuth } from '@personql/react';
 
function MyComponent() {
  const {
    // State
    isAuthenticated,
    isLoading,
    error,
    user,
    requiresMFA,
    mfaMethods,
 
    // Methods
    signIn,
    signUp,
    signOut,
    sendMFACode,
    verifyMFACode,
    forgotPassword,
    resetPassword,
    clearError,
    isSessionExpired,
  } = useAuth();
 
  const handleSignIn = async () => {
    try {
      await signIn({
        email: 'user@example.com',
        password: 'password123',
        rememberMe: true,
      });
    } catch (error) {
      console.error('Sign in failed:', error);
    }
  };
 
  return (
    <div>
      {isAuthenticated ? (
        <p>Welcome, {user?.firstName}!</p>
      ) : (
        <button onClick={handleSignIn}>Sign In</button>
      )}
    </div>
  );
}

useUser

User-specific hook:

import { useUser } from '@personql/react';
 
function UserProfile() {
  const {
    // State
    user,
    isLoading,
    error,
 
    // Methods
    updateProfile,
    refreshUser,
 
    // Computed values
    isVerified,
    fullName,
    initials,
  } = useUser();
 
  const handleUpdateProfile = async () => {
    await updateProfile({
      firstName: 'John',
      lastName: 'Doe',
    });
  };
 
  return (
    <div>
      <h1>Hello, {fullName}!</h1>
      <p>Verification status: {isVerified ? 'Verified' : 'Pending'}</p>
      <div className="avatar">{initials}</div>
    </div>
  );
}

useOrganization

Manage organizations in multi-tenant applications:

import { useOrganization } from '@personql/react';
 
function MyComponent() {
  const {
    // State
    currentOrganization,
    organizations,
    loading,
    switching,
    currentRole,
    members,
    roles,
 
    // Methods
    switchOrganization,
    createOrganization,
    updateOrganization,
    hasPermission,
    loadMembers,
    loadRoles,
    refreshOrganizations,
  } = useOrganization();
 
  return (
    <div>
      <h2>{currentOrganization?.name}</h2>
      {hasPermission('users:write') && (
        <button>Add Team Member</button>
      )}
    </div>
  );
}

Multi-Tenant Support

PersonQL React SDK includes built-in support for multi-tenant applications with organizations, roles, and permissions.

OrganizationSwitcher Component

Pre-built UI component for switching organizations:

import { OrganizationSwitcher } from '@personql/react';
 
function Header() {
  return (
    <header>
      <OrganizationSwitcher
        onOrganizationChange={(orgId) => {
          console.log('Switched to:', orgId);
        }}
        showCreateButton={true}
        onCreateClick={() => setShowCreateModal(true)}
      />
    </header>
  );
}

Permission-Based Rendering

import { useOrganization } from '@personql/react';
 
function AdminPanel() {
  const { hasPermission } = useOrganization();
 
  if (!hasPermission('settings:write')) {
    return <div>Access Denied</div>;
  }
 
  return (
    <div>
      <h1>Admin Settings</h1>
      {/* Admin content */}
    </div>
  );
}

Configuration

PersonQLConfig

interface PersonQLConfig {
  apiUrl: string; // Your Gateway Worker URL
  clientId: string; // Your application client ID
  redirectUri?: string; // Redirect URI after auth
  scopes?: string[]; // Permission scopes
  theme?: Theme; // UI customization
}
 
interface Theme {
  primaryColor?: string;
  backgroundColor?: string;
  textColor?: string;
  borderColor?: string;
  borderRadius?: string;
  fontFamily?: string;
}

Example with Custom Theme

const config = {
  apiUrl: 'https://app.personql.com',
  clientId: 'your-client-id',
  theme: {
    primaryColor: '#3b82f6',
    backgroundColor: '#ffffff',
    textColor: '#1f2937',
    borderColor: '#d1d5db',
    borderRadius: '0.375rem',
    fontFamily: 'Inter, sans-serif',
  },
};
 
<PersonQLProvider config={config}>
  <App />
</PersonQLProvider>;

Error Handling

The SDK provides comprehensive error handling:

import { useAuth } from '@personql/react';
 
function MyComponent() {
  const { error, clearError } = useAuth();
 
  if (error) {
    return (
      <Alert
        variant="error"
        title={error.code}
        message={error.message}
        dismissible
        onDismiss={clearError}
      />
    );
  }
 
  return <div>No errors</div>;
}

TypeScript Support

The SDK is fully typed with TypeScript:

import type {
  PersonQLConfig,
  AuthState,
  User,
  SignInCredentials,
  SignUpCredentials,
  MFACredentials,
  AuthError,
  Organization,
  Role,
  OrganizationMember,
} from '@personql/react';

Next Steps

Support