Peakiq Blog
How to Set Up Supabase in a Bare React Native App
Learn how to integrate Supabase into your bare React Native app. This guide covers installation, polyfills, secure authentication, database queries, and more.
This guide covers everything needed to integrate Supabase into a bare React Native project:
- Installing Supabase and required polyfill packages
- Setting up polyfills for Node and Web APIs
- Securely persisting auth sessions using
react-native-keychain - Querying data from your Supabase tables
Works with React Native 0.80+ and Supabase JS v2+ (2025)
Prerequisites
- Node.js and React Native CLI installed
- A Supabase account and project
- A bare React Native app (not using Expo)
Step 1 — Install Supabase and Required Packages
Install the core libraries:
npm install @supabase/supabase-js react-native-get-random-values react-native-url-polyfill base-64 react-native-keychainThen install iOS pods:
npx pod-installStep 2 — Create Polyfills for Node-like APIs
React Native does not include Node.js globals like Buffer, process, btoa, or atob. Create a polyfill file to patch them.
Create src/polyfills.ts:
// src/polyfills.ts
import 'react-native-url-polyfill/auto';
import 'react-native-get-random-values';
import { decode, encode } from 'base-64';
import { Buffer } from 'buffer';
import process from 'process';
// Base64 support
if (!global.btoa) global.btoa = encode;
if (!global.atob) global.atob = decode;
// Buffer and process globals
if (!global.Buffer) global.Buffer = Buffer;
if (!global.process) global.process = process;Then import this file at the very top of index.ts or index.js, before any other import:
// index.ts
import './src/polyfills';
import { AppRegistry } from 'react-native';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);The polyfill import must come first. Placing it after other imports can cause subtle runtime errors with URL parsing or random value generation.
Step 3 — Secure Auth Storage Using Keychain
Supabase needs a storage adapter to persist the auth session between app launches. Using react-native-keychain stores tokens in the iOS Keychain and Android EncryptedSharedPreferences — far safer than AsyncStorage.
Create src/utils/SecureStorage.ts:
// src/utils/SecureStorage.ts
import * as Keychain from 'react-native-keychain';
export const SecureStorage = {
getItem: async (key: string) => {
const credentials = await Keychain.getGenericPassword({ service: key });
return credentials ? credentials.password : null;
},
setItem: async (key: string, value: string) => {
await Keychain.setGenericPassword('user', value, { service: key });
},
removeItem: async (key: string) => {
await Keychain.resetGenericPassword({ service: key });
},
};Step 4 — Set Up the Supabase Client
Create src/lib/supabase.ts and pass SecureStorage as the auth storage adapter:
// src/lib/supabase.ts
import { createClient } from '@supabase/supabase-js';
import { SecureStorage } from '../utils/SecureStorage';
const supabaseUrl = 'https://your-project.supabase.co';
const supabaseAnonKey = 'your-anon-key'; // Supabase dashboard > Settings > API
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
auth: {
storage: SecureStorage,
autoRefreshToken: true,
persistSession: true,
detectSessionInUrl: false, // Not needed in mobile apps
},
});Step 5 — Test a Supabase Query
Import the client and run a query to confirm everything is wired up correctly:
import { supabase } from './lib/supabase';
const fetchData = async () => {
const { data, error } = await supabase.from('test').select('*');
if (error) {
console.error('Supabase Error:', error.message);
} else {
console.log('Data:', data);
}
};Summary
| Step | What you set up |
|---|---|
| Install packages | supabase-js, polyfills, react-native-keychain |
| Polyfills | Buffer, process, btoa/atob, URL support |
| Secure storage | Keychain adapter for iOS and Android |
| Supabase client | createClient with secure storage and auto token refresh |
| Query | .from('table').select('*') |
Troubleshooting
No network on iOS 18.4+
If Supabase requests are silently failing on the iOS simulator or device running iOS 18.4+, use Proxyman to inspect network traffic and confirm requests are leaving the device correctly. This is a known iOS 18.4 simulator networking quirk.