PersonQL React Native SDK

Official PersonQL SDK for React Native applications. Provides authentication, multi-tenant organization management, secure storage, and biometric authentication for iOS and Android.

Features

Installation

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

Peer Dependencies

Install required peer dependencies:

npm install react react-native @react-native-async-storage/async-storage react-native-keychain react-native-biometrics

iOS Setup

cd ios && pod install

Add to your Info.plist:

<key>NSFaceIDUsageDescription</key>
<string>Authenticate to sign in to PersonQL</string>

Android Setup

No additional setup required for basic functionality.

Quick Start

1. Setup Provider

Wrap your app with PersonQLProvider:

import { PersonQLProvider } from '@personql/react-native';
 
function App() {
  return (
    <PersonQLProvider apiUrl="https://app.personql.com">
      <AppContent />
    </PersonQLProvider>
  );
}

2. Use the Pre-built SignInScreen

import { SignInScreen } from '@personql/react-native';
import { useState } from 'react';
 
function AuthFlow() {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
 
  if (!isAuthenticated) {
    return (
      <SignInScreen
        apiUrl="https://app.personql.com"
        onSignInSuccess={() => setIsAuthenticated(true)}
        enableBiometric
      />
    );
  }
 
  return <Dashboard />;
}

3. Or Build Custom Auth UI

import { useAuth } from '@personql/react-native';
import { View, TextInput, Button, Text } from 'react-native';
import { useState } from 'react';
 
function CustomSignIn() {
  const {
    signIn,
    signInWithBiometric,
    loading,
    error,
    biometricAvailable,
  } = useAuth({
    apiUrl: 'https://app.personql.com',
    enableBiometric: true,
  });
 
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
 
  const handleSignIn = async () => {
    try {
      await signIn({ email, password });
      // Navigate to app
    } catch (error) {
      console.error('Sign in failed:', error);
    }
  };
 
  return (
    <View>
      <TextInput
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        autoCapitalize="none"
      />
      <TextInput
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />
      {error && <Text>{error.message}</Text>}
      <Button title="Sign In" onPress={handleSignIn} disabled={loading} />
 
      {biometricAvailable && (
        <Button
          title="Sign In with Biometric"
          onPress={signInWithBiometric}
          disabled={loading}
        />
      )}
    </View>
  );
}

API Reference

useAuth Hook

Manages authentication state and operations.

const {
  // State
  isAuthenticated,
  user,
  loading,
  error,
  biometricAvailable,
 
  // Auth methods
  signIn,
  signUp,
  signOut,
  signInWithBiometric,
 
  // Token methods
  refreshToken,
  isTokenExpired,
 
  // Biometric methods
  enableBiometricAuth,
  disableBiometricAuth,
 
  // Utility
  clearError,
} = useAuth({
  apiUrl: 'https://app.personql.com',
  enableBiometric: true,
  biometricPrompt: 'Authenticate to continue',
  onAuthStateChange: (isAuth) => console.log('Auth changed:', isAuth),
});

useOrganization Hook

Manages multi-tenant organizations and permissions.

const {
  // State
  currentOrganization,
  organizations,
  loading,
  switching,
  error,
  currentRole,
  members,
  roles,
 
  // Methods
  fetchOrganizations,
  switchOrganization,
  createOrganization,
  updateOrganization,
  hasPermission,
  loadMembers,
  loadRoles,
  refreshOrganizations,
  clearError,
} = useOrganization();

SignInScreen Component

Pre-built sign-in screen with email/password and biometric authentication.

<SignInScreen
  apiUrl="https://app.personql.com"
  onSignInSuccess={() => navigation.navigate('Dashboard')}
  onSignUpPress={() => navigation.navigate('SignUp')}
  onForgotPasswordPress={() => navigation.navigate('ForgotPassword')}
  Logo={MyLogoComponent}
  primaryColor="#007AFF"
  enableBiometric
  biometricPrompt="Sign in to continue"
/>

Multi-Tenant Examples

Organization Switcher

import { useOrganization } from '@personql/react-native';
import { View, Text, TouchableOpacity, FlatList } from 'react-native';
 
function OrganizationSwitcher() {
  const {
    currentOrganization,
    organizations,
    switchOrganization,
    switching,
  } = useOrganization();
 
  return (
    <FlatList
      data={organizations}
      keyExtractor={(org) => org.id}
      renderItem={({ item }) => (
        <TouchableOpacity
          onPress={() => switchOrganization(item.id)}
          disabled={switching || item.id === currentOrganization?.id}
        >
          <Text>{item.name}</Text>
          {item.id === currentOrganization?.id && <Text>βœ“ Active</Text>}
        </TouchableOpacity>
      )}
    />
  );
}

Permission-Based Rendering

import { useOrganization } from '@personql/react-native';
import { View, Button } from 'react-native';
 
function UserManagement() {
  const { hasPermission } = useOrganization();
 
  return (
    <View>
      {hasPermission('users:read') && (
        <Button title="View Users" onPress={viewUsers} />
      )}
 
      {hasPermission('users:write') && (
        <Button title="Add User" onPress={addUser} />
      )}
 
      {hasPermission('users:delete') && (
        <Button title="Delete User" onPress={deleteUser} />
      )}
    </View>
  );
}

Security Best Practices

  1. Never log sensitive data - Avoid logging tokens, passwords, or biometric data
  2. Use HTTPS - Always use HTTPS endpoints in production
  3. Token expiry - Tokens expire automatically; use refreshToken() as needed
  4. Biometric fallback - Always provide password fallback for biometric auth
  5. Keychain access - Data is encrypted at rest using native APIs
  6. Permission checking - Always check permissions before showing/allowing actions

Troubleshooting

iOS Biometric Not Working

Make sure you’ve added NSFaceIDUsageDescription to Info.plist:

<key>NSFaceIDUsageDescription</key>
<string>Authenticate to sign in</string>

Android Keystore Issues

If you encounter keystore errors, try clearing app data or reinstalling.

Token Refresh Fails

Ensure your refresh token hasn’t expired. Tokens have a limited lifetime.

Organization Not Switching

Make sure the user has access to the organization and it’s in active status.

Next Steps

Support