Working with Environment Variables
1. Using .env Files
| Variable | Value | Description |
|---|---|---|
| EXPO_PUBLIC_API_URL | https://api.example.com |
Public API endpoint used in the app |
| EXPO_PUBLIC_APP_NAME | MyApp |
Application name exposed to the client |
Example: Loading environment variables in a React component
<div>
<h1>{process.env.EXPO_PUBLIC_APP_NAME}</h1>
<p>API URL: {process.env.EXPO_PUBLIC_API_URL}</p>
</div>
Note: Environment variables prefixed with
EXPO_PUBLIC_ are accessible in the client-side code. Other variables are only available on the server or during build time.
2. Configuring expo-constants
| Property | Description | Usage |
|---|---|---|
| EXPO_PUBLIC_ | Environment variables prefixed with EXPO_PUBLIC_ are available in the app at runtime. |
process.env.EXPO_PUBLIC_API_URL |
| EXPO_PUBLIC_ | These variables are embedded into the app at build time and can be accessed in both development and production. | EXPO_PUBLIC_API_URL=https://api.example.com |
Example: Using Environment Variables in Expo
import Constants from 'expo-constants';
const apiUrl = Constants.expoConfig?.extra?.API_URL || process.env.EXPO_PUBLIC_API_URL;
console.log('API URL:', apiUrl);
Note: Variables prefixed with
EXPO_PUBLIC_ are available in both development and production builds.
Warning: Never store sensitive credentials like API keys or passwords in
EXPO_PUBLIC_ variables as they are exposed to the client.
3. Setting Build Variables
| Variable | Type | Description | Usage |
|---|---|---|---|
| EXPO_PUBLIC_* | String | Public environment variables available at runtime | process.env.EXPO_PUBLIC_API_URL |
| EXPO_ENV_* | String | Environment-specific variables (e.g., dev, staging) | process.env.EXPO_ENV_STAGING |
| EXPO_SECRET_* | String | Secrets not exposed to client-side code | process.env.EXPO_SECRET_API_KEY |
Example: Using Public Variables in App
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
console.log("API URL:", apiUrl);
Example: Setting Variables in .env File
EXPO_PUBLIC_API_URL=https://api.example.com
EXPO_SECRET_API_KEY=your-secret-key
Note: Variables must start with
EXPO_PUBLIC_ or EXPO_SECRET_ to be recognized by Expo.
Warning: Never commit secret keys to version control. Use
.env.local or CI/CD variables.
4. Using Platform-Specific Variables
| Variable Name | Platform | Description | Example Value |
|---|---|---|---|
| EXPO_IOS_ENV | iOS | Environment variable specific to iOS builds | production |
| EXPO_ANDROID_ENV | Android | Environment variable specific to Android builds | staging |
| EXPO_WEB_ENV | Web | Environment variable specific to Web builds | development |
Example: Setting Platform-Specific Variables in .env
EXPO_IOS_ENV=production
EXPO_ANDROID_ENV=staging
EXPO_WEB_ENV=development
Note: These variables are automatically injected into the app at build time and can be accessed via
process.env in your JavaScript/TypeScript code.
5. Accessing Variables
| Variable | Access Method | Description |
|---|---|---|
| EXPO_PUBLIC_* | process.env.EXPO_PUBLIC_* |
Public environment variables accessible in both client and server code |
| EXPO_* | process.env.EXPO_* |
Expo-specific environment variables (e.g., EXPO_APP_ID) |
Example: Reading Public Environment Variables
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
console.log("API URL:", apiUrl);
Note: Variables prefixed with
EXPO_PUBLIC_ are embedded into the app at build time and can be safely accessed in client-side code.
6. Securing Sensitive Variables
Note: Environment variables in Expo are not encrypted by default and should never contain sensitive data like API keys or passwords in production builds.
| Variable | Description | Security Level | Usage |
|---|---|---|---|
| EXPO_ENV | Indicates the environment (e.g., development, staging, production) |
NEW | Used to conditionally load configurations or endpoints |
| EXPO_PUBLIC_* | Publicly exposed variables (prefixed with EXPO_PUBLIC_) |
Low | Safe to use in frontend code, client-side logic |
| EXPO_SECRET_* | Secret variables (prefixed with EXPO_SECRET_) |
High | Should be used only in backend or server-side logic |
Example: Using Public Variables in Client Code
const apiUrl = process.env.EXPO_PUBLIC_API_URL || "https://api.example.com";
console.log("API URL:", apiUrl);
Example: Using Secret Variables in Server Code
const secretKey = process.env.EXPO_SECRET_API_KEY;
if (!secretKey) {
throw new Error("API key not found");
}
Best Practices for Securing Variables
- Never store sensitive keys in client-side code or public repositories
- Use
EXPO_SECRET_*prefix for server-side only variables - Use
EXPO_PUBLIC_*prefix for client-side accessible variables - Use environment-specific configuration files (e.g.,
.env.development,.env.production) - Ensure CI/CD pipelines do not expose secrets in logs or build artifacts
7. Using Different Environments
| Environment | File | Description |
|---|---|---|
| development | .env.local |
Local development environment variables |
| production | .env.production |
Production environment variables |
| staging | .env.staging |
Staging environment variables |
Example: Setting up environment-specific variables
echo 'EXPO_PUBLIC_API_URL=https://api.dev.example.com' > .env.local
echo 'EXPO_PUBLIC_API_URL=https://api.prod.example.com' > .env.production
Note: Environment variables are loaded at build time and cannot be changed at runtime.
8. Setting Variables in CI/CD
Example: Setting Environment Variables in GitHub Actions
name: Build and Deploy
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18"
- name: Install dependencies
run: npm install
- name: Set environment variables
run: |
echo "EXPO_PUBLIC_API_URL=https://api.example.com" &>> $GITHUB_ENV
echo "EXPO_PUBLIC_APP_VERSION=1.0.0" &>> $GITHUB_ENV
- name: Build Expo app
run: npx expo build:web
| Variable | Usage | Notes |
|---|---|---|
| EXPO_PUBLIC_API_URL | https://api.example.com |
Base URL for API calls in Expo app |
| EXPO_PUBLIC_APP_VERSION | 1.0.0 |
Version string for the app |
Note: Variables prefixed with
EXPO_PUBLIC_ are embedded into the app bundle and accessible at runtime.Warning: Never store sensitive credentials (e.g., API keys, secrets) in
EXPO_PUBLIC_ variables as they are exposed to the client.Best Practices for CI/CD Variables
- Use
EXPO_PUBLIC_prefix for client-accessible variables - Store secrets in CI/CD service secrets (e.g., GitHub Secrets)
- Do not hardcode sensitive values in configuration files
- Use environment-specific variables (e.g.,
EXPO_PUBLIC_API_URL_DEV)
9. Using Runtime Configuration
| Property | Description | Example |
|---|---|---|
| EXPO_RUNTIME_CONFIG | Environment variable to pass runtime configuration to the app | EXPO_RUNTIME_CONFIG={"apiUrl":"https://api.example.com"} |
Example: Setting Runtime Config in Environment
EXPO_RUNTIME_CONFIG="{"apiUrl":"https://api.example.com"}" npx expo start
Note: Runtime configuration is merged with the static configuration at build time.
10. Implementing Feature Flags
| Flag Name | Value Type | Description | Default |
|---|---|---|---|
| FEATURE_NEW_UI | boolean |
Enables new UI components | false |
| FEATURE_API_V2 | boolean |
Enables new API endpoints | false |
| FEATURE_ANALYTICS | string |
Analytics provider ID | "none" |
Example: Reading Feature Flags in Code
import Constants from "expo-constants";
const featureFlags = {
NEW_UI: Constants.expoConfig?.extra?.FEATURE_NEW_UI || false,
API_V2: Constants.expoConfig?.extra?.FEATURE_API_V2 || false,
ANALYTICS: Constants.expoConfig?.extra?.FEATURE_ANALYTICS || "none"
};
export { featureFlags };
Example: Using Feature Flags in Conditional Rendering
import { featureFlags } from "./featureFlags";
function App() {
return (
<>
{featureFlags.NEW_UI && <NewUIComponent />}
{featureFlags.API_V2 && <NewAPIComponent />}
</>
);
}
Note: Feature flags are read from
app.json or app.config.js under the extra key.
Warning: Feature flags are not dynamically updated at runtime. Changes require a new build.
11. Validating Environment Variables
| Property | Values | Description |
|---|---|---|
| EXPO_ENV | development, production |
Defines the environment for the app |
| EXPO_PUBLIC_* | Any string | Public environment variables accessible in the client-side code |
| EXPO_PRIVATE_* | Any string | Private environment variables, not accessible in client-side code |
Example: Setting up environment variables in Expo
EXPO_PUBLIC_API_URL=https://api.example.com
EXPO_PRIVATE_DATABASE_PASSWORD=secret123
Note: Environment variables in Expo are managed through the
.env files and loaded at build time.
Warning: Never commit sensitive environment variables to version control.
| Validation Rule | Check | Status |
|---|---|---|
| EXPO_PUBLIC_API_URL | Must start with https:// |
NEW Required |
| EXPO_PRIVATE_DATABASE_PASSWORD | Must not be empty | DEPRECATED Use secure storage instead |
12. Using Dynamic Configuration
| Property | Description | Usage |
|---|---|---|
| config | Dynamic configuration object that can be modified at runtime | { expo: { config: { ... } } } |
| env | Environment variables accessible at runtime | process.env.MY_VAR |
Example: Dynamic Configuration in Expo
export default {
expo: {
config: {
name: "MyApp",
slug: "my-app",
version: "1.0.0",
platforms: ["ios", "android"],
env: {
API_URL: process.env.API_URL || "https://api.example.com"
}
}
}
}
Note: Dynamic configuration allows runtime modification of app properties, useful for feature flags or environment-specific settings.