Official PersonQL SDK for React Native applications. Provides authentication, multi-tenant organization management, secure storage, and biometric authentication for iOS and Android.
npm install @personql/react-native
# or
yarn add @personql/react-native
# or
pnpm add @personql/react-native
Install required peer dependencies:
npm install react react-native @react-native-async-storage/async-storage react-native-keychain react-native-biometrics
cd ios && pod install
Add to your Info.plist:
<key>NSFaceIDUsageDescription</key>
<string>Authenticate to sign in to PersonQL</string>
No additional setup required for basic functionality.
Wrap your app with PersonQLProvider:
import { PersonQLProvider } from '@personql/react-native';
function App() {
return (
<PersonQLProvider apiUrl="https://app.personql.com">
<AppContent />
</PersonQLProvider>
);
}
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 />;
}
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>
);
}
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),
});
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();
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"
/>
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>
)}
/>
);
}
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>
);
}
refreshToken() as neededMake sure youβve added NSFaceIDUsageDescription to Info.plist:
<key>NSFaceIDUsageDescription</key>
<string>Authenticate to sign in</string>
If you encounter keystore errors, try clearing app data or reinstalling.
Ensure your refresh token hasnβt expired. Tokens have a limited lifetime.
Make sure the user has access to the organization and itβs in active status.