This content originally appeared on DEV Community and was authored by Cathy Lai
If you’ve ever shipped an update with Expo and suddenly hit this dreaded runtime error:
Error: supabaseUrl is required., js engine: hermes
…you’re not alone. This happens when your environment variables don’t make it into the runtime bundle. With Expo’s OTA updates (eas update
), only JavaScript and assets get updated — no new native code. If your Supabase keys aren’t baked into the binary, they’ll resolve as undefined
.
The fix is simple: move your Supabase config into Expo’s extra
config via app.config.ts
.
Why app.json
fails with env variables
By default, Expo projects ship with an app.json
. It works great for static values, but JSON doesn’t understand JavaScript or process.env
.
Example ❌ (this will break):
{
"expo": {
"name": "my-app",
"slug": "my-app",
"extra": {
"supabaseUrl": process.env.SUPABASE_URL,
"supabaseAnonKey": process.env.SUPABASE_ANON_KEY
}
}
}
That throws SyntaxError: invalid character 'p'
because process.env
is not valid JSON.
Step 1 — Use app.config.ts
instead
Rename your config file:
mv app.json app.config.ts
Then set it up like this:
import 'dotenv/config';
export default {
expo: {
name: "my-app",
slug: "my-app",
version: "1.0.0",
runtimeVersion: { policy: "sdkVersion" },
extra: {
supabaseUrl: process.env.SUPABASE_URL,
supabaseAnonKey: process.env.SUPABASE_ANON_KEY,
unsplashKey: process.env.UNSPLASH_KEY,
},
owner: "your-expo-username"
}
};
Now Expo will pull in your .env
values and bake them into the app.
Step 2 — Expose them in your code
Create or update your env.ts
:
import Constants from 'expo-constants';
const extra = Constants.expoConfig?.extra || {};
export const CONFIG = {
supabaseUrl: extra.supabaseUrl as string,
supabaseAnonKey: extra.supabaseAnonKey as string,
unsplashKey: extra.unsplashKey as string,
};
This way, your Supabase client always gets defined values:
import { createClient } from '@supabase/supabase-js';
import { CONFIG } from './env';
export const supabase = createClient(CONFIG.supabaseUrl, CONFIG.supabaseAnonKey);
Step 3 — Add secrets to EAS
When you build or submit your app, Expo’s cloud build environment needs access to those same values. You don’t want to commit .env
into GitHub. Instead, use EAS secrets:
eas secret:create --name SUPABASE_URL --value https://xxxx.supabase.co
eas secret:create --name SUPABASE_ANON_KEY --value your-anon-key
eas secret:create --name UNSPLASH_KEY --value your-unsplash-key
On build, Expo will inject them into process.env
, and app.config.ts
will pick them up.
Step 4 — Rebuild once, then enjoy OTA updates
The key detail: OTA updates can’t add new env variables. You need one full native build that includes your Supabase keys. After that, all future eas update
commands can safely push new JS/asset changes without breaking Supabase.
Final Thoughts
If you rely on Supabase (or any API key) in Expo apps:
- ❌ Don’t put
process.env
directly inapp.json
. - ✅ Do move your config into
app.config.ts
withextra
. - ✅ Use
expo-constants
in your app to read them. - ✅ Store keys securely in EAS secrets.
That small change will save you hours of debugging the next time you ship an OTA update. 🚀
This content originally appeared on DEV Community and was authored by Cathy Lai

Cathy Lai | Sciencx (2025-10-03T22:55:31+00:00) Supabase config in your Expo project – the proper way. Retrieved from https://www.scien.cx/2025/10/03/supabase-config-in-your-expo-project-the-proper-way/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.