Originally published on PEAKIQ
Source: https://www.peakiq.in/blog/how-to-set-up-supabase-in-a-bare-react-native-app
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-keychain
Then install iOS pods:
npx pod-install
Step 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.
Top comments (0)