| name | expo-workflow |
| description | Expert in Expo SDK 54+ development workflows, EAS Build, EAS Update, native tabs, Expo Router v6, expo-video, expo-audio, dev clients, expo-cli commands, app configuration, and deployment strategies. Activates for expo, expo go, eas build, eas update, expo config, app.json, eas.json, expo dev client, expo prebuild, expo eject, over-the-air updates, expo doctor, expo install, managed workflow, bare workflow, expo router, native tabs, liquid glass. |
Expo Workflow Expert (SDK 54+)
Comprehensive expertise in Expo SDK 54+ development workflows, EAS (Expo Application Services), and optimization strategies for rapid mobile development. Specializes in native tabs, Expo Router v6, iOS Liquid Glass, Android edge-to-edge, and modern deployment pipelines.
What I Know
Expo SDK 54 Features (August 2025)
What's New in SDK 54
- Native Tab Bar Navigation: True native tabs via React Navigation 7
- iOS Liquid Glass Support: Translucent glass effects (iOS 26+)
- Android Edge-to-Edge: Default immersive display
- expo-video & expo-audio: New media APIs replacing expo-av
- expo-image v2: useImage hook for imperative loading
- React Native 0.81: Foundation with New Architecture
- Improved Developer Experience: Faster builds, better error messages
Breaking Changes from SDK 53
expo-avdeprecated → useexpo-videoandexpo-audio- Tab navigation API changes for native tabs
- Android edge-to-edge now default (adjust padding)
Expo Fundamentals
Managed vs Bare Workflow
- Managed workflow: Full Expo SDK, minimal native code
- Bare workflow: Full native code access with Expo modules
- CNG (Continuous Native Generation): Best of both worlds
- Migration strategies between workflows
Expo Go vs Development Builds
- Expo Go: Quick testing, limited native modules
- Dev Client: Full native module support, custom builds
- When to switch from Expo Go to dev builds
- Creating custom dev clients with EAS Build
Expo SDK & Modules
- Core Expo modules (expo-camera, expo-location, expo-video, expo-audio)
- Third-party native module compatibility
- Module installation:
npx expo install <package> - Autolinking handles native setup automatically
EAS Build (Cloud Builds)
Build Profiles
- Development builds: Fast iteration, dev client
- Preview builds: Internal testing, TestFlight/Internal Testing
- Production builds: App Store/Play Store submission
- Custom build profiles in eas.json
Platform-Specific Configuration
- iOS credentials management
- Android keystore handling
- Build caching strategies
- Environment variable injection
Build Optimization
- Caching node_modules and gradle dependencies
- Incremental builds
- Build machine types (M1, Ubuntu)
- Build time reduction strategies
EAS Update (OTA Updates)
Over-The-Air Updates
- JavaScript bundle updates without app store submission
- Update channels and branches
- Rollout strategies (gradual rollout, instant rollout)
- Rollback capabilities
Update Workflows
- Development channel: Continuous updates
- Preview channel: QA testing
- Production channel: Staged rollouts
- Emergency hotfix workflows
Update Best Practices
- Version compatibility management
- Update frequency optimization
- Monitoring update adoption
- Handling update failures gracefully
App Configuration
app.json / app.config.js
- App metadata (name, slug, version)
- Platform-specific configurations
- Asset and icon configuration
- Splash screen customization
- Deep linking setup (scheme, associated domains)
- Permissions configuration
- Build-time environment variables
eas.json
- Build profile configuration
- Submit profile setup
- Environment secrets management
- Platform-specific build settings
Dynamic Configuration
- Environment-specific configs (dev, staging, prod)
- Feature flags integration
- App variants (white-label apps)
Development Workflow
Fast Refresh & Hot Reloading
- Understanding fast refresh behavior
- Troubleshooting fast refresh issues
- When to use full reload vs fast refresh
Debugging Tools
- React DevTools integration
- Remote debugging with Chrome DevTools
- Flipper for advanced debugging
- Network request inspection
- Performance profiling
Local Development
- Running on physical devices (QR code scanning)
- Running on simulators/emulators
- Offline development strategies
- Tunnel mode vs LAN mode
Deployment & Distribution
App Store Submission
- iOS: TestFlight, App Store Connect integration
- Android: Internal testing, Play Store submission
- EAS Submit command automation
- Store metadata management
Internal Distribution
- Ad-hoc iOS builds
- Android APK distribution
- Enterprise distribution
- TestFlight external testing
CI/CD Integration
- GitHub Actions with EAS Build
- GitLab CI integration
- Automated build triggers
- Automated OTA updates on merge
When to Use This Skill
Ask me when you need help with:
- Setting up Expo SDK 54+ development workflow
- Creating development builds with EAS Build
- Configuring app.json or eas.json
- Setting up over-the-air updates with EAS Update
- Troubleshooting Expo Go limitations
- Optimizing build times
- Managing app credentials and secrets
- Configuring deep linking and URL schemes
- Setting up CI/CD pipelines for Expo apps
- Deploying to App Store or Play Store
- Understanding Expo SDK 54 capabilities
- Migrating from Expo Go to dev client
- Handling native modules in Expo projects
- Implementing native tab navigation
- Setting up iOS Liquid Glass effects
- Configuring Android edge-to-edge display
- Migrating from expo-av to expo-video/expo-audio
- Using Expo Router v6 file-based routing
Essential Expo Commands
Project Setup
# Create new Expo project
npx create-expo-app@latest MyApp
# Navigate to project
cd MyApp
# Start development server
npx expo start
# Install Expo module
npx expo install expo-camera
# Check project health
npx expo-doctor
Development
# Start with cache cleared
npx expo start -c
# Start with specific mode
npx expo start --dev-client # Development build
npx expo start --go # Expo Go
# Run on specific platform
npx expo run:ios
npx expo run:android
# Prebuild native projects (bare workflow)
npx expo prebuild
EAS Build
# Login to EAS
eas login
# Configure EAS
eas build:configure
# Build for all platforms
eas build --platform all
# Build development version
eas build --profile development --platform ios
# Build for production
eas build --profile production --platform all
# Check build status
eas build:list
EAS Update
# Configure EAS Update
eas update:configure
# Publish update to default channel
eas update --branch production --message "Fix critical bug"
# Publish to specific channel
eas update --channel preview --message "QA testing"
# List published updates
eas update:list
# Rollback update
eas update:rollback
EAS Submit
# Submit to App Store
eas submit --platform ios
# Submit to Play Store
eas submit --platform android
# Submit specific build
eas submit --platform ios --id <build-id>
Pro Tips & Tricks
1. Development Build Optimization
Create a reusable development build once, then use EAS Update for daily changes:
// eas.json
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
}
}
}
}
Build once:
eas build --profile development --platform all
Update JavaScript daily:
eas update --branch development --message "Daily changes"
2. Environment-Based Configuration
Use app.config.js for dynamic configuration:
// app.config.js
export default ({ config }) => {
const isProduction = process.env.APP_ENV === 'production';
return {
...config,
name: isProduction ? 'MyApp' : 'MyApp Dev',
slug: 'myapp',
extra: {
apiUrl: isProduction
? 'https://api.myapp.com'
: 'https://dev-api.myapp.com',
analyticsKey: process.env.ANALYTICS_KEY,
},
updates: {
url: 'https://u.expo.dev/your-project-id'
}
};
};
3. Fast Credential Setup
Let EAS manage credentials automatically:
// eas.json
{
"build": {
"production": {
"ios": {
"credentialsSource": "remote"
},
"android": {
"credentialsSource": "remote"
}
}
}
}
4. Efficient Build Caching
Speed up builds by caching dependencies:
// eas.json
{
"build": {
"production": {
"cache": {
"key": "myapp-v1",
"paths": ["node_modules", "ios/Pods", "android/.gradle"]
}
}
}
}
5. Gradual OTA Rollout
Safely deploy updates to production:
# Start with 10% rollout
eas update --branch production --message "New feature" --rollout-percentage 10
# Monitor metrics, then increase
eas update:configure-rollout --branch production --percentage 50
# Full rollout
eas update:configure-rollout --branch production --percentage 100
6. Quick Testing on Physical Devices
For Expo Go (quick testing):
# Start dev server
npx expo start
# Scan QR code with:
# - iOS: Camera app
# - Android: Expo Go app
For dev client (full features):
# Install dev client once
eas build --profile development --platform ios
# Daily JavaScript updates via EAS Update
eas update --branch development
7. Troubleshooting Common Issues
"Unable to resolve module"
# Clear Metro cache
npx expo start -c
# Reinstall dependencies
rm -rf node_modules && npm install
"Build failed on EAS"
# Check build logs
eas build:list
eas build:view <build-id>
# Run prebuild locally to catch issues early
npx expo prebuild
"Update not appearing in app"
# Check update channel matches app's channel
eas channel:list
# Verify update was published successfully
eas update:list --branch production
# Force reload in app (shake device → reload)
8. Native Module Integration
When you need a native module not in Expo SDK:
# Install the module
npm install react-native-awesome-module
# Prebuild to generate native projects
npx expo prebuild
# Rebuild dev client with new module
eas build --profile development --platform all
# Continue using EAS Update for JS changes
eas update --branch development
9. Native Tab Navigation (SDK 54+)
Enable true native tab bars with Expo Router v6:
// app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router';
import { Platform } from 'react-native';
export default function TabLayout() {
return (
<Tabs
screenOptions={{
// Enable native tabs (iOS has translucent effect by default)
tabBarStyle: Platform.select({
ios: { position: 'absolute' }, // For Liquid Glass
default: {},
}),
}}
>
<Tabs.Screen
name="index"
options={{ title: 'Home', tabBarIcon: ({ color }) => <HomeIcon color={color} /> }}
/>
<Tabs.Screen
name="profile"
options={{ title: 'Profile', tabBarIcon: ({ color }) => <ProfileIcon color={color} /> }}
/>
</Tabs>
);
}
10. iOS Liquid Glass (SDK 54+ / iOS 26+)
Create beautiful translucent effects:
// components/GlassCard.tsx
import { View, StyleSheet, Platform } from 'react-native';
import { BlurView } from 'expo-blur';
export function GlassCard({ children }) {
if (Platform.OS === 'ios' && parseInt(Platform.Version, 10) >= 26) {
return (
<BlurView
style={styles.card}
intensity={60}
tint="systemMaterial" // Liquid Glass tint
>
{children}
</BlurView>
);
}
return <View style={[styles.card, styles.fallback]}>{children}</View>;
}
const styles = StyleSheet.create({
card: {
borderRadius: 16,
overflow: 'hidden',
},
fallback: {
backgroundColor: 'rgba(255, 255, 255, 0.8)',
},
});
11. Android Edge-to-Edge (SDK 54+)
Handle immersive display properly:
// app/_layout.tsx
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { View, StyleSheet, Platform } from 'react-native';
export default function RootLayout() {
const insets = useSafeAreaInsets();
return (
<View
style={[
styles.container,
{
// Account for edge-to-edge on Android 15+
paddingTop: insets.top,
paddingBottom: insets.bottom,
},
]}
>
<Slot />
</View>
);
}
// app.json - enable edge-to-edge
{
"expo": {
"android": {
"edgeToEdge": true // SDK 54 default
}
}
}
12. expo-video (Replacing expo-av)
Modern video playback:
// components/VideoPlayer.tsx
import { useVideoPlayer, VideoView } from 'expo-video';
import { useEvent } from 'expo';
import { StyleSheet, View } from 'react-native';
export function VideoPlayer({ source }: { source: string }) {
const player = useVideoPlayer(source, (player) => {
player.loop = true;
player.play();
});
useEvent(player, 'statusChange', ({ status }) => {
console.log('Player status:', status);
});
return (
<View style={styles.container}>
<VideoView
style={styles.video}
player={player}
allowsFullscreen
allowsPictureInPicture
/>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
video: { width: '100%', aspectRatio: 16 / 9 },
});
13. expo-audio (Replacing expo-av)
Modern audio handling:
// hooks/useAudio.ts
import { useAudioPlayer, useAudioPlayerStatus } from 'expo-audio';
export function useAudio(source: string) {
const player = useAudioPlayer(source);
const status = useAudioPlayerStatus(player);
return {
play: () => player.play(),
pause: () => player.pause(),
seek: (position: number) => player.seekTo(position),
isPlaying: status.playing,
position: status.currentTime,
duration: status.duration,
};
}
14. expo-image v2 with useImage
Imperative image loading:
import { useImage, Image } from 'expo-image';
export function PreloadedImage({ uri }: { uri: string }) {
const image = useImage(uri, {
onError: (error) => console.error('Failed to load image:', error),
});
if (!image) {
return <ActivityIndicator />;
}
return (
<Image
source={image}
style={{ width: image.width, height: image.height }}
contentFit="cover"
/>
);
}
Integration with SpecWeave
Increment Planning
- Document Expo setup steps in
spec.md - Include EAS Build/Update configuration in
plan.md - Track build and deployment tasks in
tasks.md
Testing Strategy
- Use dev builds for feature development
- Preview builds for QA testing
- Production builds for stakeholder demos
Living Documentation
- Document build profiles in
.specweave/docs/internal/operations/ - Track deployment procedures in runbooks
- Maintain credential management procedures
Cost Optimization
- Use EAS Update instead of rebuilding for JS-only changes
- Cache dependencies to reduce build times
- Monitor EAS usage in increment reports