Build Configuration
The eas.json file in your project root defines how EAS Build compiles your app. This guide covers all configuration options for creating optimized builds.
eas.json Structure
{
"cli": {
"version": ">= 0.52.0",
"requireCommit": true,
"appVersionSource": "remote"
},
"build": {
"development": { /* development profile */ },
"preview": { /* preview profile */ },
"production": { /* production profile */ }
},
"submit": {
"production": { /* submission config */ }
}
}
Top-Level Sections
- cli: EAS CLI behavior and requirements
- build: Build profiles for different environments
- submit: App store submission configuration
CLI Configuration
Control EAS CLI behavior globally:
{
"cli": {
"version": ">= 0.52.0",
"requireCommit": true,
"appVersionSource": "remote",
"promptToConfigurePushNotifications": false
}
}
Options:
version: Minimum required EAS CLI version
requireCommit: Require clean git state before builds
appVersionSource: "local" | "remote" - Where to get app version
promptToConfigurePushNotifications: Auto-configure push notifications
Build Profiles
Profiles define different build configurations for various use cases.
Default Profiles
When you run eas build:configure, these profiles are created:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
},
"preview": {
"distribution": "internal"
},
"production": {}
}
}
Profile Inheritance
Extend profiles to reduce duplication:
{
"build": {
"base": {
"node": "18.17.0",
"env": {
"ENVIRONMENT": "production"
}
},
"production": {
"extends": "base",
"channel": "production"
},
"staging": {
"extends": "base",
"channel": "staging",
"env": {
"API_URL": "https://staging.api.example.com"
}
}
}
}
Common Build Options
Options available for all platforms:
Distribution
{
"distribution": "store" // or "internal"
}
"store": For app store submission (AAB for Android, IPA for iOS)
"internal": For internal distribution (APK for Android, Ad Hoc for iOS)
EAS Update Channel
{
"channel": "production"
}
Links builds to EAS Update channels for over-the-air updates.
Development Client
{
"developmentClient": true
}
Builds a development client with expo-dev-client for debugging.
Environment Variables
{
"env": {
"API_URL": "https://api.example.com",
"FEATURE_FLAG_NEW_UI": "true"
}
}
Environment variables available during build and in the app runtime (if prefixed with EXPO_PUBLIC_).
Node.js Version
Specifies Node.js version for the build.
Credentials Source
{
"credentialsSource": "remote" // or "local"
}
"remote": Use credentials from EAS servers
"local": Use credentials from credentials.json
Resource Class
{
"android": {
"resourceClass": "large"
},
"ios": {
"resourceClass": "large"
}
}
Options: "default" | "medium" | "large" - Larger classes provide more CPU/memory.
Cache Configuration
{
"cache": {
"disabled": false,
"key": "custom-cache-key",
"paths": [
"node_modules",
".expo"
]
}
}
Control build caching to speed up subsequent builds.
Android-Specific Options
Configure Android builds:
Build Type
{
"android": {
"buildType": "apk" // or "app-bundle"
}
}
"app-bundle" (default): Creates AAB for Play Store
"apk": Creates APK for direct installation
Gradle Command
{
"android": {
"gradleCommand": ":app:bundleRelease"
}
}
Custom Gradle command to run. Common commands:
:app:assembleRelease - Build release APK
:app:bundleRelease - Build release AAB
:app:assembleDebug - Build debug APK
Build Image
{
"android": {
"image": "sdk-54" // or "sdk-53", "sdk-52"
}
}
EAS Build image version (includes Android SDK, NDK, and tools).
Auto-Increment Version Code
{
"android": {
"autoIncrement": "versionCode" // or true
}
}
Automatically increments versionCode for each build.
NDK Version
{
"android": {
"ndk": "26.1.10909125"
}
}
Specific Android NDK version for native code compilation.
Without Credentials
{
"android": {
"withoutCredentials": true
}
}
Build without code signing (for testing unsigned builds).
Complete Android Example
{
"build": {
"production-android": {
"android": {
"buildType": "app-bundle",
"gradleCommand": ":app:bundleRelease",
"image": "sdk-54",
"resourceClass": "large",
"autoIncrement": "versionCode",
"env": {
"EAS_BUILD_PLATFORM": "android"
}
},
"distribution": "store",
"channel": "production"
}
}
}
iOS-Specific Options
Configure iOS builds:
Simulator Build
{
"ios": {
"simulator": true
}
}
Builds for iOS Simulator (development only, no code signing needed).
Build Configuration
{
"ios": {
"buildConfiguration": "Release" // or "Debug"
}
}
Xcode build configuration to use.
Scheme
{
"ios": {
"scheme": "MyApp" // Xcode scheme name
}
}
Specifies which Xcode scheme to build.
Build Image
{
"ios": {
"image": "sdk-54" // or "sdk-53", "sdk-52"
}
}
EAS Build image version (includes Xcode and related tools).
CocoaPods Version
{
"ios": {
"cocoapods": "1.16.2"
}
}
Specific CocoaPods version for dependency management.
Auto-Increment Build Number
{
"ios": {
"autoIncrement": "buildNumber" // or true
}
}
Automatically increments CFBundleVersion for each build.
Bundle Identifier
{
"ios": {
"bundleIdentifier": "com.example.myapp"
}
}
Override bundle identifier for this profile (useful for multi-flavor apps).
Enterprise Provisioning
{
"ios": {
"enterpriseProvisioning": "universal" // or "adhoc"
}
}
For Apple Developer Enterprise Program accounts.
Complete iOS Example
{
"build": {
"production-ios": {
"ios": {
"buildConfiguration": "Release",
"scheme": "MyApp",
"image": "sdk-54",
"cocoapods": "1.16.2",
"resourceClass": "large",
"autoIncrement": "buildNumber",
"simulator": false
},
"distribution": "store",
"channel": "production"
}
}
}
Configure both platforms with different settings:
{
"build": {
"production": {
"channel": "production",
"distribution": "store",
"env": {
"API_URL": "https://api.example.com"
},
"android": {
"buildType": "app-bundle",
"image": "sdk-54",
"resourceClass": "large",
"autoIncrement": "versionCode"
},
"ios": {
"image": "sdk-54",
"resourceClass": "medium",
"autoIncrement": "buildNumber",
"bundleIdentifier": "com.company.app"
}
},
"preview": {
"distribution": "internal",
"channel": "preview",
"android": {
"buildType": "apk",
"gradleCommand": ":app:assembleRelease"
},
"ios": {
"simulator": false
}
},
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"buildType": "apk",
"gradleCommand": ":app:assembleDebug"
},
"ios": {
"simulator": true,
"buildConfiguration": "Debug"
}
}
}
}
Environment Variables
Build-Time Variables
Available during the build process only:
{
"env": {
"BUILD_NUMBER": "123",
"CI": "true"
}
}
Runtime Variables (EXPO_PUBLIC_)
Available in your app code:
{
"env": {
"EXPO_PUBLIC_API_URL": "https://api.example.com",
"EXPO_PUBLIC_ANALYTICS_ID": "UA-12345678"
}
}
Access in your app:
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
Secret Variables
For sensitive values, use EAS Secrets:
# Set a secret
eas secret:create --name API_SECRET_KEY --value "your-secret-key"
# List secrets
eas secret:list
# Delete a secret
eas secret:delete --name API_SECRET_KEY
Secrets are available as environment variables during build:
{
"env": {
"API_KEY": "$API_SECRET_KEY"
}
}
{
"build": {
"production": {
"env": {
"GLOBAL_VAR": "value"
},
"android": {
"env": {
"ANDROID_ONLY_VAR": "android-value"
}
},
"ios": {
"env": {
"IOS_ONLY_VAR": "ios-value"
}
}
}
}
}
Advanced Configurations
Custom Build Functions
Run custom JavaScript during the build:
Create eas-hooks/custom-build.js:
module.exports = async function ({ platform }) {
console.log(`Running custom build logic for ${platform}`);
// Your custom build logic here
if (platform === 'android') {
// Android-specific logic
} else if (platform === 'ios') {
// iOS-specific logic
}
};
Reference in eas.json:
{
"build": {
"production": {
"config": "eas-hooks/custom-build.js"
}
}
}
Monorepo Configuration
For monorepo projects:
{
"cli": {
"appVersionSource": "remote"
},
"build": {
"production": {
"node": "20.11.0",
"env": {
"EXPO_MONOREPO_ROOT": "../.."
},
"cache": {
"paths": [
"../../node_modules",
"node_modules"
]
}
}
}
}
Build Variants (Android)
Build different flavors of your Android app:
{
"build": {
"production-free": {
"android": {
"gradleCommand": ":app:bundleFreeRelease",
"env": {
"APP_VARIANT": "free"
}
}
},
"production-premium": {
"android": {
"gradleCommand": ":app:bundlePremiumRelease",
"env": {
"APP_VARIANT": "premium"
}
}
}
}
}
Multiple Build Configurations
Real-world example with multiple environments:
{
"cli": {
"version": ">= 0.52.0",
"requireCommit": true
},
"build": {
"base": {
"node": "20.11.0",
"android": {
"image": "sdk-54"
},
"ios": {
"image": "sdk-54",
"cocoapods": "1.16.2"
}
},
"development": {
"extends": "base",
"developmentClient": true,
"distribution": "internal",
"channel": "development",
"env": {
"EXPO_PUBLIC_API_URL": "http://localhost:3000",
"EXPO_PUBLIC_ENV": "development"
},
"android": {
"buildType": "apk"
},
"ios": {
"simulator": true
}
},
"preview": {
"extends": "base",
"distribution": "internal",
"channel": "preview",
"env": {
"EXPO_PUBLIC_API_URL": "https://preview-api.example.com",
"EXPO_PUBLIC_ENV": "preview"
},
"android": {
"buildType": "apk"
}
},
"staging": {
"extends": "base",
"distribution": "store",
"channel": "staging",
"env": {
"EXPO_PUBLIC_API_URL": "https://staging-api.example.com",
"EXPO_PUBLIC_ENV": "staging"
},
"android": {
"buildType": "app-bundle",
"autoIncrement": "versionCode"
},
"ios": {
"autoIncrement": "buildNumber"
}
},
"production": {
"extends": "base",
"distribution": "store",
"channel": "production",
"env": {
"EXPO_PUBLIC_API_URL": "https://api.example.com",
"EXPO_PUBLIC_ENV": "production"
},
"android": {
"buildType": "app-bundle",
"resourceClass": "large",
"autoIncrement": "versionCode"
},
"ios": {
"resourceClass": "large",
"autoIncrement": "buildNumber"
}
}
},
"submit": {
"production": {
"android": {
"serviceAccountKeyPath": "./secrets/google-service-account.json",
"track": "production"
},
"ios": {
"ascAppId": "1234567890"
}
}
}
}
Troubleshooting
Invalid eas.json
EAS CLI validates eas.json against a schema. Use proper JSON syntax and valid option values.
Common errors:
- Missing commas between properties
- Trailing commas in objects/arrays
- Invalid property names
- Wrong value types (string vs boolean)
Validate your eas.json:
eas build --platform android --profile production --dry-run
Profile Not Found
Error: Build profile "staging" does not exist in eas.json
Solution: Ensure profile exists in eas.json:
eas build --platform android --profile staging
Profile must be defined:
{
"build": {
"staging": { /* ... */ }
}
}
Environment Variables Not Available
If process.env.EXPO_PUBLIC_API_URL is undefined:
- Ensure variable is prefixed with
EXPO_PUBLIC_
- Rebuild the app (env vars are embedded at build time)
- Check eas.json has the variable in the correct profile
Inheritance Issues
When using extends, child profiles override parent values:
{
"base": {
"env": { "A": "1", "B": "2" }
},
"production": {
"extends": "base",
"env": { "B": "3" } // Only B is overridden, A is inherited
}
}
Result: Production has A=1 and B=3.
Next Steps