expo-config

Use this skill when configuring Expo applications using app.json, app.config.js/ts, and EAS (Expo Application Services) configuration files.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "expo-config" with this command: npx skills add thebushidocollective/han/thebushidocollective-han-expo-config

Expo Configuration

Use this skill when configuring Expo applications using app.json, app.config.js/ts, and EAS (Expo Application Services) configuration files.

Key Concepts

app.json Configuration

Basic static configuration:

{ "expo": { "name": "MyApp", "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": "com.mycompany.myapp", "buildNumber": "1" }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon.png", "backgroundColor": "#ffffff" }, "package": "com.mycompany.myapp", "versionCode": 1 }, "web": { "favicon": "./assets/favicon.png" } } }

Dynamic Configuration (app.config.js)

Use JavaScript for dynamic configuration:

export default ({ config }) => ({ ...config, name: process.env.APP_NAME || 'MyApp', slug: 'my-app', version: '1.0.0', extra: { apiUrl: process.env.API_URL, environment: process.env.NODE_ENV, }, ios: { bundleIdentifier: process.env.NODE_ENV === 'production' ? 'com.mycompany.myapp' : 'com.mycompany.myapp.dev', }, android: { package: process.env.NODE_ENV === 'production' ? 'com.mycompany.myapp' : 'com.mycompany.myapp.dev', }, });

TypeScript Configuration

Use TypeScript for type-safe config:

// app.config.ts import { ExpoConfig, ConfigContext } from '@expo/config';

export default ({ config }: ConfigContext): ExpoConfig => ({ ...config, name: 'MyApp', slug: 'my-app', version: '1.0.0', orientation: 'portrait', icon: './assets/icon.png', splash: { image: './assets/splash.png', resizeMode: 'contain', backgroundColor: '#ffffff', }, plugins: [ 'expo-router', [ 'expo-camera', { cameraPermission: 'Allow $(PRODUCT_NAME) to access your camera.', }, ], ], extra: { apiUrl: process.env.API_URL, }, });

Best Practices

Environment Variables

Use environment-specific configuration:

// app.config.ts import { ExpoConfig, ConfigContext } from '@expo/config';

const IS_DEV = process.env.NODE_ENV === 'development'; const IS_PROD = process.env.NODE_ENV === 'production';

export default ({ config }: ConfigContext): ExpoConfig => ({ ...config, name: IS_PROD ? 'MyApp' : 'MyApp (Dev)', slug: 'my-app', extra: { apiUrl: IS_PROD ? 'https://api.myapp.com' : 'https://dev-api.myapp.com', environment: process.env.NODE_ENV, eas: { projectId: process.env.EAS_PROJECT_ID, }, }, ios: { bundleIdentifier: IS_PROD ? 'com.mycompany.myapp' : 'com.mycompany.myapp.dev', }, android: { package: IS_PROD ? 'com.mycompany.myapp' : 'com.mycompany.myapp.dev', }, });

Plugin Configuration

Configure Expo plugins:

{ "expo": { "plugins": [ "expo-router", [ "expo-camera", { "cameraPermission": "Allow $(PRODUCT_NAME) to access camera" } ], [ "expo-location", { "locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location" } ], [ "expo-notifications", { "icon": "./assets/notification-icon.png", "color": "#ffffff" } ] ] } }

EAS Build Configuration

Configure EAS builds with eas.json:

{ "cli": { "version": ">= 5.9.0" }, "build": { "development": { "developmentClient": true, "distribution": "internal", "ios": { "simulator": true } }, "preview": { "distribution": "internal", "ios": { "simulator": false }, "android": { "buildType": "apk" } }, "production": { "autoIncrement": true } }, "submit": { "production": {} } }

Access Config in Code

Access configuration at runtime:

import Constants from 'expo-constants';

export function App() { const apiUrl = Constants.expoConfig?.extra?.apiUrl; const environment = Constants.expoConfig?.extra?.environment;

console.log('API URL:', apiUrl); console.log('Environment:', environment);

return <View />; }

Common Patterns

Multi-Environment Setup

// app.config.ts import { ExpoConfig, ConfigContext } from '@expo/config';

type Environment = 'development' | 'staging' | 'production';

const ENV: Environment = (process.env.APP_ENV as Environment) || 'development';

const config: Record<Environment, { apiUrl: string; name: string }> = { development: { apiUrl: 'http://localhost:3000', name: 'MyApp (Dev)', }, staging: { apiUrl: 'https://staging-api.myapp.com', name: 'MyApp (Staging)', }, production: { apiUrl: 'https://api.myapp.com', name: 'MyApp', }, };

export default ({ config: baseConfig }: ConfigContext): ExpoConfig => ({ ...baseConfig, name: config[ENV].name, slug: 'my-app', extra: { apiUrl: config[ENV].apiUrl, environment: ENV, }, });

Feature Flags

// app.config.ts export default ({ config }: ConfigContext): ExpoConfig => ({ ...config, extra: { features: { enableNewUI: process.env.ENABLE_NEW_UI === 'true', enableAnalytics: process.env.ENABLE_ANALYTICS !== 'false', enableBetaFeatures: process.env.ENABLE_BETA === 'true', }, }, });

// In code import Constants from 'expo-constants';

const features = Constants.expoConfig?.extra?.features;

if (features?.enableNewUI) { // Show new UI }

Platform-Specific Assets

{ "expo": { "ios": { "icon": "./assets/icon-ios.png", "splash": { "image": "./assets/splash-ios.png" } }, "android": { "adaptiveIcon": { "foregroundImage": "./assets/adaptive-icon-android.png", "backgroundColor": "#ffffff" }, "splash": { "image": "./assets/splash-android.png" } } } }

Deep Linking Configuration

{ "expo": { "scheme": "myapp", "slug": "my-app", "web": { "bundler": "metro" }, "ios": { "associatedDomains": ["applinks:myapp.com"] }, "android": { "intentFilters": [ { "action": "VIEW", "autoVerify": true, "data": [ { "scheme": "https", "host": "myapp.com", "pathPrefix": "/app" } ], "category": ["BROWSABLE", "DEFAULT"] } ] } } }

Version Management

// app.config.ts import packageJson from './package.json';

export default ({ config }: ConfigContext): ExpoConfig => ({ ...config, version: packageJson.version, ios: { buildNumber: process.env.IOS_BUILD_NUMBER || '1', }, android: { versionCode: parseInt(process.env.ANDROID_VERSION_CODE || '1', 10), }, });

Anti-Patterns

Don't Hardcode Secrets

// Bad - Secrets in config export default { extra: { apiKey: 'sk_live_1234567890', apiSecret: 'secret_key_here', }, };

// Good - Use environment variables export default { extra: { apiKey: process.env.API_KEY, // Never commit secrets }, };

Don't Use app.json for Dynamic Config

// Bad - Can't use dynamic values in app.json { "expo": { "name": process.env.APP_NAME } }

// Good - Use app.config.js/ts // app.config.ts export default { name: process.env.APP_NAME || 'MyApp', };

Don't Forget Platform-Specific Requirements

// Bad - Missing required fields { "expo": { "name": "MyApp", "slug": "my-app" } }

// Good - Include all required fields { "expo": { "name": "MyApp", "slug": "my-app", "ios": { "bundleIdentifier": "com.mycompany.myapp" }, "android": { "package": "com.mycompany.myapp" } } }

Don't Mix Config Types

// Bad - Mixing static and dynamic // app.json { "expo": { "name": "MyApp" } } // app.config.js also exists - creates conflicts

// Good - Use one or the other // Either app.json for static config // Or app.config.js/ts for dynamic config

Related Skills

  • expo-modules: Using Expo modules configured via plugins

  • expo-build: Building apps with EAS Build

  • expo-updates: Configuring OTA updates

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

android-jetpack-compose

No summary provided by upstream source.

Repository SourceNeeds Review
General

fastapi-async-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
General

storybook-story-writing

No summary provided by upstream source.

Repository SourceNeeds Review
General

atomic-design-fundamentals

No summary provided by upstream source.

Repository SourceNeeds Review