docs›Guides›Expo / React Native Use Aurabase in an Expo / React Native app
Create the client with EXPO_PUBLIC_* variables, keep the session across app restarts, and subscribe to database changes.
5 min read·Level intermediate·Revised on Oct 22, 2026
This English text was generated automatically from the French original and has not been reviewed yet.
#Status
1. What was verified
@aurabase/aurabase-js bundles without error for Android in an Expo project (npx expo export --platform android, Expo SDK 58, React Native 0.88). Running the app on a device or a simulator has not been verified yet: treat the session and realtime examples below as the intended usage, and report anything that differs.
Aurabase has no Flutter or Dart package on pub.dev yet: for Flutter, call the REST API (see REST API).
#Setup
2. Install and configure
terminalbash
npx expo install expo-secure-store
npm install @aurabase/aurabase-js
Expo exposes to the app only the variables whose name starts with EXPO_PUBLIC_. Put the project URL and the anon key (never the service_role key: it would ship inside the app) in .env:
.envbash
EXPO_PUBLIC_AURABASE_URL=https://<slug>.aurabase.cloud
EXPO_PUBLIC_AURABASE_ANON_KEY=aura_anon_…
#Session
3. Keep the session
On the web the SDK keeps the session in localStorage; React Native has none. Give the client an auth store that writes the session to expo-secure-store. The store is read at start-up, before the client is created:
lib/aurabase.tstypescript
import * as SecureStore from 'expo-secure-store'
import { BaseAuthStore, createClient } from '@aurabase/aurabase-js'
import type { User } from '@aurabase/aurabase-js'
const KEY = 'aurabase-session'
class SecureStoreAuthStore extends BaseAuthStore {
override save(token: string, refreshToken: string, user: User): void {
super.save(token, refreshToken, user)
void SecureStore.setItemAsync(KEY, JSON.stringify({ token, refreshToken, user }))
}
override clear(): void {
super.clear()
void SecureStore.deleteItemAsync(KEY)
}
}
/** Read the saved session once, at app start, before rendering anything that needs it. */
export async function createAuraClient() {
const store = new SecureStoreAuthStore()
const saved = await SecureStore.getItemAsync(KEY)
if (saved) {
const { token, refreshToken, user } = JSON.parse(saved) as {
token: string
refreshToken: string
user: User
}
store.save(token, refreshToken, user)
}
return createClient(
process.env.EXPO_PUBLIC_AURABASE_URL!,
process.env.EXPO_PUBLIC_AURABASE_ANON_KEY!,
{ auth: { storage: store } },
)
}
Attention
expo-secure-store limits the size of a value on some devices (about 2 KB). If your session carries a lot of user metadata and save fails, store it with @react-native-async-storage/async-storage instead (less protected) or keep only the tokens.
React Native provides a WebSocket, which the SDK uses. A channel opened before the user signs in is re-authenticated when the session changes, so the order of subscribe() and signInWithPassword() does not matter.
components/Todos.tsxtypescript
import { useEffect } from 'react'
import type { AuraClient } from '@aurabase/aurabase-js'
export function useTodoChanges(aura: AuraClient, onChange: (type: string) => void) {
useEffect(() => {
const channel = aura.realtime
.channel('todos')
.on('postgres_changes', { event: '*', schema: 'public', table: 'todos' }, (change) =>
onChange(change.eventType),
)
.subscribe((status) => {
if (status === 'CHANNEL_ERROR') console.warn('realtime refused')
})
return () => {
channel.unsubscribe()
}
}, [aura, onChange])
}
Last updated · Oct 22, 2026