with one click
mobile-framework-expo
Expo managed workflow
Menu
Expo managed workflow
| name | mobile-framework-expo |
| description | Expo managed workflow |
Quick Guide: Build production-ready React Native apps with Expo. Use managed workflow with Continuous Native Generation for most projects, Expo Router for file-based navigation, and EAS for builds/updates. Development builds replace Expo Go for production testing.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST use development builds for production testing - Expo Go is for prototyping only)
(You MUST update runtimeVersion when making native dependency changes to prevent OTA update crashes)
(You MUST use config plugins for native customization - NEVER manually edit android/ios directories in managed workflow)
(You MUST use EXPO_PUBLIC_ prefix for client-side environment variables - NEVER store secrets in these variables)
</critical_requirements>
Auto-detection: Expo, expo-router, EAS Build, EAS Update, expo-dev-client, app.config.js, app.json, expo prebuild, npx expo, eas.json, expo-constants, expo-notifications, Continuous Native Generation, CNG
When to use:
Key patterns covered:
When NOT to use:
Expo transforms React Native development from "write once, debug everywhere" to "write once, deploy confidently." The key insight is that most apps don't need direct native access - they need well-maintained native modules with consistent APIs.
Core principles:
Mental model:
Expo is NOT a limitation on React Native - it's a professional-grade abstraction. You can always drop down to native code via Expo Modules API or prebuild, but most apps never need to.
app.config.tsUse app.config.ts for environment-specific builds. Use named constants for SDK versions and build numbers.
// app.config.ts - Environment-aware config
const IS_PRODUCTION = process.env.APP_ENV === "production";
const BUILD_NUMBER = 1;
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: IS_PRODUCTION ? "MyApp" : "MyApp (Dev)",
ios: {
bundleIdentifier: IS_PRODUCTION ? "com.app" : "com.app.dev",
buildNumber: String(BUILD_NUMBER),
},
android: {
package: IS_PRODUCTION ? "com.app" : "com.app.dev",
versionCode: BUILD_NUMBER,
},
});
Full examples: examples/core.md - App Configuration section
Modify native code declaratively -- changes survive expo prebuild --clean. Use config plugins for permissions, SDK versions, and native settings.
// app.config.ts plugins array
plugins: [
[
"expo-camera",
{ cameraPermission: "Allow $(PRODUCT_NAME) to access your camera." },
],
[
"expo-build-properties",
{ android: { minSdkVersion: 24 }, ios: { deploymentTarget: "15.1" } },
],
];
Full examples: examples/core.md - Config Plugins section
Use EXPO_PUBLIC_ prefix for client-side variables. Metro requires direct property access -- destructuring and bracket notation don't work.
// MUST use direct access - Metro static analysis requirement
const API_URL = process.env.EXPO_PUBLIC_API_URL; // Works
// const { EXPO_PUBLIC_API_URL } = process.env; // BROKEN - undefined at runtime
Full examples: examples/core.md - Environment Variables section
Use expo-dev-client for production-accurate testing. Expo Go is for prototyping only -- it lacks your native dependencies, push notifications, and accurate splash screens.
# Cloud build
eas build --profile development --platform ios
# Local build
npx expo run:ios
Full configuration: examples/eas.md - Development Builds section
Block splash screen while loading fonts, use expo-image for remote images with blur hash placeholders and disk caching.
SplashScreen.preventAutoHideAsync();
// Load fonts, then call SplashScreen.hideAsync() when ready
Full examples: examples/core.md - Font Loading and Image Handling sections
<red_flags>
"fingerprint" policy for automatic detection.EXPO_PUBLIC_ variables -- embedded in JS bundle, visible to anyone who decompiles. Use EAS Secrets and backend proxies.expo prebuild --clean. Use config plugins.process.env -- Metro requires direct property access (process.env.EXPO_PUBLIC_*). Destructuring and bracket notation produce undefined.expo-av -- removed in SDK 55. Migrate to expo-video and expo-audio.Full anti-patterns and gotchas: reference.md
</red_flags>
Detailed Resources:
<critical_reminders>
All code must follow project conventions in CLAUDE.md
(You MUST use development builds for production testing - Expo Go is for prototyping only)
(You MUST update runtimeVersion when making native dependency changes to prevent OTA update crashes)
(You MUST use config plugins for native customization - NEVER manually edit android/ios directories in managed workflow)
(You MUST use EXPO_PUBLIC_ prefix for client-side environment variables - NEVER store secrets in these variables)
Failure to follow these rules will cause OTA update crashes, broken builds, and security vulnerabilities.
</critical_reminders>
Generate AI videos with Luma Dream Machine via AceDataCloud API. Use when creating videos from text prompts, generating videos from reference images, extending existing videos, or any video generation task with Luma. Supports text-to-video, image-to-video, and video extension.
Single-pass post-processing, URP Renderer Features, and mobile-safe screen effects for Unity
GPU architecture, precision types, fillrate, overdraw, baked lighting, and LOD optimization for Unity mobile/WebGL shaders
Node budgets, custom lighting, sub-graphs, precision control, and mobile workflows for Unity Shader Graph
Channel packing, variant reduction, shader_feature vs multi_compile, and build size optimization for Unity
Mobile-optimized water shaders with depth coloring, foam, Gerstner waves, refraction, and caustics for Unity URP