🎯

expo-config-setup

🎯Skill

from dengineproblem/agents-monorepo

VibeIndex|
What it does

Configures Expo React Native projects with dynamic app.json settings, platform-specific overrides, and environment-aware deployment strategies.

📦

Part of

dengineproblem/agents-monorepo(106 items)

expo-config-setup

Installation

2Installs
-
AddedFeb 4, 2026

Skill Details

SKILL.md

Эксперт Expo конфигурации. Используй для React Native Expo, app.json и EAS Build.

Overview

# Expo Config Setup Expert

Expert at configuring Expo projects with app.json, app.config.js, and platform-specific settings for optimal development and production builds.

Core Configuration Principles

Static vs Dynamic Configuration

  • Use app.json for static configuration that doesn't change between environments
  • Use app.config.js for dynamic configuration requiring environment variables or conditional logic
  • Never mix sensitive data directly in configuration files - use environment variables

Platform-Specific Settings

  • Always configure both iOS and Android platforms explicitly
  • Use platform-specific overrides for different requirements
  • Consider platform differences in permissions, capabilities, and UI guidelines

Essential App Configuration Structure

```javascript

// app.config.js

export default {

expo: {

name: process.env.APP_NAME || "My App",

slug: "my-app",

version: "1.0.0",

orientation: "portrait",

icon: "./assets/icon.png",

userInterfaceStyle: "automatic",

splash: {

image: "./assets/splash.png",

resizeMode: "contain",

backgroundColor: "#ffffff"

},

assetBundlePatterns: [

"*/"

],

ios: {

supportsTablet: true,

bundleIdentifier: process.env.IOS_BUNDLE_ID || "com.company.myapp",

buildNumber: process.env.IOS_BUILD_NUMBER || "1",

infoPlist: {

NSCameraUsageDescription: "This app uses the camera to take photos.",

NSLocationWhenInUseUsageDescription: "This app uses location to provide location-based features."

}

},

android: {

adaptiveIcon: {

foregroundImage: "./assets/adaptive-icon.png",

backgroundColor: "#FFFFFF"

},

package: process.env.ANDROID_PACKAGE || "com.company.myapp",

versionCode: parseInt(process.env.ANDROID_VERSION_CODE) || 1,

permissions: [

"android.permission.CAMERA",

"android.permission.ACCESS_FINE_LOCATION"

]

},

web: {

favicon: "./assets/favicon.png",

bundler: "metro"

}

}

};

```

Environment-Specific Configuration

```javascript

// app.config.js with environment handling

const IS_DEV = process.env.APP_VARIANT === 'development';

const IS_PREVIEW = process.env.APP_VARIANT === 'preview';

const getAppName = () => {

if (IS_DEV) return 'MyApp (Dev)';

if (IS_PREVIEW) return 'MyApp (Preview)';

return 'MyApp';

};

const getBundleId = () => {

if (IS_DEV) return 'com.company.myapp.dev';

if (IS_PREVIEW) return 'com.company.myapp.preview';

return 'com.company.myapp';

};

export default {

expo: {

name: getAppName(),

slug: IS_DEV ? 'myapp-dev' : IS_PREVIEW ? 'myapp-preview' : 'myapp',

scheme: IS_DEV ? 'myapp-dev' : IS_PREVIEW ? 'myapp-preview' : 'myapp',

version: process.env.APP_VERSION || '1.0.0',

ios: {

bundleIdentifier: getBundleId(),

},

android: {

package: getBundleId(),

},

extra: {

apiUrl: process.env.API_URL,

environment: process.env.APP_VARIANT || 'production',

eas: {

projectId: process.env.EAS_PROJECT_ID

}

},

updates: {

url: https://u.expo.dev/${process.env.EAS_PROJECT_ID}

},

runtimeVersion: {

policy: 'sdkVersion'

}

}

};

```

EAS Build Configuration

```json

// eas.json

{

"cli": {

"version": ">= 5.0.0"

},

"build": {

"development": {

"developmentClient": true,

"distribution": "internal",

"ios": {

"simulator": true

},

"env": {

"APP_VARIANT": "development"

}

},

"preview": {

"distribution": "internal",

"ios": {

"resourceClass": "m-medium"

},

"android": {

"buildType": "apk"

},

"env": {

"APP_VARIANT": "preview"

}

},

"production": {

"ios": {

"resourceClass": "m-medium"

},

"env": {

"APP_VARIANT": "production"

}

}

},

"submit": {

"production": {

"ios": {

"appleId": "your@email.com",

"ascAppId": "1234567890",

"appleTeamId": "ABCD1234"

},

"android": {

"serviceAccountKeyPath": "./google-services.json",

"track": "internal"

}

}

}

}

```

Plugin Configuration Best Practices

```javascript

// Advanced plugin configuration

export default {

expo: {

plugins: [

"expo-font",

"expo-router",

[

"expo-camera",

{

"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",

"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",

"recordAudioAndroid": true

}

],

[

"expo-location",

{

"locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location.",

"locationAlwaysPermission": "Allow $(PRODUCT_NAME) to use your location.",

"locationWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location."

}

],

[

"expo-notifications",

{

"icon": "./assets/notification-icon.png",

"color": "#ffffff",

"sounds": ["./assets/notification-sound.wav"],

"mode": "production"

}

],

[

"expo-build-properties",

{

"ios": {

"deploymentTarget": "13.4",

"useFrameworks": "static"

},

"android": {

"compileSdkVersion": 34,

"targetSdkVersion": 34,

"buildToolsVersion": "34.0.0",

"minSdkVersion": 23,

"kotlinVersion": "1.9.0"

}

}

],

[

"expo-image-picker",

{

"photosPermission": "Allow $(PRODUCT_NAME) to access your photos",

"cameraPermission": "Allow $(PRODUCT_NAME) to take pictures"

}

]

]

}

};

```

Asset and Icon Configuration

```javascript

// Comprehensive asset configuration

export default {

expo: {

icon: "./assets/images/icon.png", // 1024x1024

splash: {

image: "./assets/images/splash.png", // 1284x2778 for iPhone 13 Pro Max

resizeMode: "contain",

backgroundColor: "#ffffff"

},

ios: {

icon: "./assets/images/icon-ios.png", // iOS-specific icon if needed

splash: {

image: "./assets/images/splash-ios.png",

resizeMode: "cover",

backgroundColor: "#ffffff",

tabletImage: "./assets/images/splash-tablet.png"

}

},

android: {

icon: "./assets/images/icon-android.png",

adaptiveIcon: {

foregroundImage: "./assets/images/adaptive-icon.png", // 1024x1024

backgroundImage: "./assets/images/adaptive-icon-background.png",

backgroundColor: "#FFFFFF"

},

splash: {

image: "./assets/images/splash-android.png",

resizeMode: "cover",

backgroundColor: "#ffffff",

mdpi: "./assets/images/splash-mdpi.png", // 320x480

hdpi: "./assets/images/splash-hdpi.png", // 480x800

xhdpi: "./assets/images/splash-xhdpi.png", // 720x1280

xxhdpi: "./assets/images/splash-xxhdpi.png", // 960x1600

xxxhdpi: "./assets/images/splash-xxxhdpi.png" // 1280x1920

}

}

}

};

```

Deep Linking and Scheme Configuration

```javascript

// Complete deep linking setup

export default {

expo: {

scheme: "myapp",

web: {

bundler: "metro"

},

ios: {

bundleIdentifier: "com.company.myapp",

associatedDomains: [

"applinks:myapp.com",

"applinks:www.myapp.com"

]

},

android: {

package: "com.company.myapp",

intentFilters: [

{

action: "VIEW",

autoVerify: true,

data: [

{

scheme: "https",

host: "myapp.com",

pathPrefix: "/app"

},

{

scheme: "https",

host: "www.myapp.com",

pathPrefix: "/app"

}

],

category: ["BROWSABLE", "DEFAULT"]

},

{

action: "VIEW",

data: [

{

scheme: "myapp"

}

],

category: ["BROWSABLE", "DEFAULT"]

}

]

}

}

};

```

OTA Updates Configuration

```javascript

// Over-the-air updates setup

export default {

expo: {

updates: {

enabled: true,

checkAutomatically: "ON_LOAD",

fallbackToCacheTimeout: 30000,

url: https://u.expo.dev/${process.env.EAS_PROJECT_ID}

},

runtimeVersion: {

policy: "appVersion" // or "sdkVersion", "nativeVersion", "fingerprint"

},

// For custom update logic

extra: {

updateChannel: process.env.APP_VARIANT || 'production'

}

}

};

```

Update Logic in App

```javascript

// App.js or updates hook

import * as Updates from 'expo-updates';

async function checkForUpdates() {

if (__DEV__) return;

try {

const update = await Updates.checkForUpdateAsync();

if (update.isAvailable) {

await Updates.fetchUpdateAsync();

await Updates.reloadAsync();

}

} catch (error) {

console.error('Error checking for updates:', error);

}

}

```

Notifications Configuration

```javascript

// Push notifications setup

export default {

expo: {

notification: {

icon: "./assets/notification-icon.png", // 96x96, white on transparent

color: "#3498db",

androidMode: "default",

androidCollapsedTitle: "#{unread_notifications} new notifications"

},

ios: {

infoPlist: {

UIBackgroundModes: ["remote-notification"]

}

},

android: {

googleServicesFile: "./google-services.json",

useNextNotificationsApi: true

},

plugins: [

[

"expo-notifications",

{

icon: "./assets/notification-icon.png",

color: "#3498db",

sounds: ["./assets/sounds/notification.wav"],

mode: "production"

}

]

]

}

};

```

Security Best Practices

```javascript

// Secure configuration patterns

export default ({ config }) => {

// Validate required env vars

const requiredEnvVars = ['API_URL', 'EAS_PROJECT_ID'];

for (const envVar of requiredEnvVars) {

if (!process.env[envVar]) {

console.warn(Warning: ${envVar} is not set);

}

}

return {

...config,

expo: {

...config.expo,

// Never expose sensitive keys in extra

extra: {

apiUrl: process.env.API_URL,

// Use EAS Secrets for sensitive values

// NOT: apiKey: process.env.API_KEY

},

// Certificate pinning for production

ios: {

...config.expo?.ios,

infoPlist: {

NSAppTransportSecurity: {

NSAllowsArbitraryLoads: false,

NSExceptionDomains: {

"myapp.com": {

NSExceptionRequiresForwardSecrecy: true,

NSIncludesSubdomains: true

}

}

}

}

}

}

};

};

```

Common Configuration Pitfalls

```yaml

Missing Bundle Identifiers:

problem: Build fails with "missing bundleIdentifier"

solution: Always set ios.bundleIdentifier and android.package

Incorrect Asset Dimensions:

problem: Icons/splash screens look blurry or cropped

solution: Follow exact size requirements (icon: 1024x1024)

Version Code Issues:

problem: Store rejects upload due to version code

solution: Increment android.versionCode for each upload

Missing Permissions:

problem: Feature crashes on first use

solution: Declare all required permissions with descriptions

OTA Update Failures:

problem: Updates not applying

solution: Check runtimeVersion policy matches native builds

```

Validation and Testing

```bash

# Validate configuration

npx expo doctor

# Check for common issues

npx expo-cli diagnostics

# Test deep links

# iOS

xcrun simctl openurl booted "myapp://path"

# Android

adb shell am start -a android.intent.action.VIEW -d "myapp://path"

# Preview configuration

npx expo config --type public

npx expo config --type introspect

```

Лучшие практики

  1. Environment separation — разные конфиги для dev/preview/prod
  2. Dynamic config — app.config.js для переменных окружения
  3. EAS Secrets — храните sensitive данные в EAS Secrets
  4. Version management — автоматизируйте версии через CI/CD
  5. Plugin audit — регулярно обновляйте и проверяйте плагины
  6. Test deep links — тестируйте на обеих платформах

More from this repository10

🎯
k6-load-test🎯Skill

Generates and runs performance load tests using k6 to simulate user traffic and measure system response under various load conditions.

🎯
creative-copywriter🎯Skill

Generates high-converting storytelling, offers, posts, and video texts by extracting key business context and applying targeted copywriting techniques.

🎯
b2b-saas-marketing🎯Skill

Provides expert B2B SaaS marketing strategies for demand generation, growth marketing, lead optimization, and key performance metrics.

🎯
ios-unit-test🎯Skill

Generates comprehensive iOS unit tests using XCTest, following best practices like AAA pattern, mocking, and dependency injection for robust test coverage.

🎯
influencer-outreach-template🎯Skill

Generates personalized, high-converting influencer outreach templates with strategic personalization and compelling communication approaches.

🎯
abm-specialist🎯Skill

Enables AI agents to perform advanced account-based marketing (ABM) strategies, targeting and analyzing potential enterprise clients with precision.

🎯
openapi-documentation🎯Skill

openapi-documentation skill from dengineproblem/agents-monorepo

🎯
code-documentation-generator🎯Skill

code-documentation-generator skill from dengineproblem/agents-monorepo

🎯
feature-documentation🎯Skill

feature-documentation skill from dengineproblem/agents-monorepo

🎯
android-notification-builder🎯Skill

Builds and manages Android notifications with advanced configuration for channels, styles, and interaction patterns.