From react-native-hifi
Guides building custom Expo dev clients for apps needing native modules, Apple features, third-party SDKs, or Expo Go limitations via EAS Build.
npx claudepluginhub bidah/react-native-hifi --plugin react-native-hifiThis skill uses the workspace's default tool permissions.
A custom development client is a debug build of your app that includes your specific native modules and configuration. It replaces Expo Go when you need native code that Expo Go does not bundle.
Build and distribute Expo development clients with EAS Build for iOS/Android testing of custom native code via TestFlight or local installs.
Builds and distributes Expo development clients using EAS Build locally or via TestFlight for testing custom native code on iOS/Android devices when Expo Go is insufficient.
Provides expertise for building React Native mobile apps with Expo, including Expo Router navigation, EAS Build and Submit, development builds, native module integration, and production deployment.
Share bugs, ideas, or general feedback.
A custom development client is a debug build of your app that includes your specific native modules and configuration. It replaces Expo Go when you need native code that Expo Go does not bundle.
Core principle: Use Expo Go for rapid prototyping. Switch to a dev client when you need custom native code, and use EAS Build to create and distribute it.
Use a dev client when your app requires:
| Feature | Expo Go | Dev Client |
|---|---|---|
| Native code | Pre-bundled only | Any native module |
| Setup time | Zero | Requires build step |
| OTA updates | Yes | Yes |
| Custom config plugins | No | Yes |
| App Store distribution | No | Yes (via TestFlight) |
| Custom app icon/splash | No | Yes |
| Background modes | Limited | Full control |
| Fast Refresh | Yes | Yes |
npx expo install expo-dev-client
This adds the development client UI (launcher, error overlay, dev menu) to your app.
# Install EAS CLI if needed
npm install -g eas-cli
# Initialize EAS in your project
eas build:configure
This creates eas.json:
{
"cli": {
"version": ">= 5.0.0"
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"ios": {
"simulator": true
}
},
"preview": {
"distribution": "internal"
},
"production": {}
}
}
# iOS Simulator build
eas build --platform ios --profile development
# iOS device build (requires Apple Developer account)
eas build --platform ios --profile development \
--local # Optional: build locally instead of EAS servers
# Android build
eas build --platform android --profile development
# Install on simulator/emulator (automatic after build)
eas build:run --platform ios
# Or start dev server pointing to the dev client
npx expo start --dev-client
For sharing dev builds with your team:
// eas.json
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal"
}
}
}
Register test devices:
# Register iOS devices (creates provisioning profile)
eas device:create
# Build for registered devices
eas build --platform ios --profile development
Team members install via the link provided after build completes.
For broader beta testing:
// eas.json
{
"build": {
"preview": {
"distribution": "internal",
"ios": {
"buildConfiguration": "Release"
}
}
},
"submit": {
"production": {
"ios": {
"appleId": "your@email.com",
"ascAppId": "1234567890"
}
}
}
}
# Build and submit to TestFlight
eas build --platform ios --profile preview
eas submit --platform ios
Build on your machine instead of EAS cloud servers:
# Requires Xcode / Android Studio installed
eas build --platform ios --profile development --local
# Output: .app (simulator) or .ipa (device)
Advantages of local builds:
Most Expo-compatible libraries use config plugins that automatically configure native code:
npx expo install expo-camera
// app.json
{
"expo": {
"plugins": [
[
"expo-camera",
{
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera"
}
]
]
}
}
Rebuild your dev client after adding plugins:
eas build --platform ios --profile development
# Create a new native module
npx create-expo-module my-native-module --local
This scaffolds:
modules/
my-native-module/
android/
src/main/java/.../MyNativeModule.kt
ios/
MyNativeModule.swift
src/
index.ts # TypeScript API
expo-module.config.json
1. npx expo start --dev-client
2. Open dev client app on device/simulator
3. Dev client connects to your local dev server
4. Fast Refresh works for JS/TS changes
5. Native code changes require rebuild
Shake device or press Cmd+D (iOS simulator) / Cmd+M (Android emulator):
Config plugins modify native project configuration at build time without ejecting:
// plugins/withCustomEntitlement.ts
import { ConfigPlugin, withEntitlementsPlist } from 'expo/config-plugins';
const withCustomEntitlement: ConfigPlugin = (config) => {
return withEntitlementsPlist(config, (mod) => {
mod.modResults['com.apple.developer.healthkit'] = true;
mod.modResults['com.apple.developer.healthkit.access'] = ['health-records'];
return mod;
});
};
export default withCustomEntitlement;
// app.json
{
"expo": {
"plugins": ["./plugins/withCustomEntitlement"]
}
}
| Mistake | Fix |
|---|---|
Running npx expo start without --dev-client | Must use --dev-client flag to connect to custom builds |
| Forgetting to rebuild after adding native module | Any native dependency change requires eas build |
| Using Expo Go config with dev client | Remove expo-go specific workarounds |
| Not registering iOS test devices | Run eas device:create before building for physical devices |
| Mixing development and production profiles | Keep eas.json profiles separate and clear |
| Building for simulator when targeting device | Set "simulator": false in the iOS build profile for devices |
| Task | Command |
|---|---|
| Install dev client | npx expo install expo-dev-client |
| Configure EAS | eas build:configure |
| Build for iOS simulator | eas build --platform ios --profile development |
| Build locally | eas build --platform ios --profile development --local |
| Start dev server | npx expo start --dev-client |
| Register device | eas device:create |
| Install build | eas build:run --platform ios |
| Submit to TestFlight | eas submit --platform ios |
| Create native module | npx create-expo-module my-module --local |