Native Boundary
The native boundary is every change that affects android/, ios/, the app binary, signing, permissions, or native runtime compatibility.
flowchart LR
config["app config"] --> prebuild["expo prebuild"]
deps["native dependencies"] --> prebuild
plugins["config plugins"] --> prebuild
modules["Expo modules"] --> prebuild
prebuild --> android["android/"]
prebuild --> ios["ios/"]
android --> build["native build"]
ios --> build
build --> stores["stores and devices"]
Durable Native Changes
| Need | Use |
|---|---|
| App name, package, bundle ID, version, icons, scheme | App config |
Android permissions or iOS Info.plist values | App config or package config plugin |
| Library-specific native setup | Existing config plugin |
| Repeated generated-native edits | Custom config plugin |
| Custom Swift/Kotlin API | Expo Modules API |
| Fully hand-managed native project | Commit and own android/ and ios/ deliberately |
CNG Rule
In a CNG project, android/ and ios/ are generated outputs unless the project explicitly decides otherwise. A manual native edit that cannot survive npx expo prebuild --clean is not durable.
Use this command to inspect generated output without dependency installs:
npx expo prebuild --clean --no-install
Rebuild Triggers
Rebuild the development or release binary after changing:
- Native dependencies.
- Expo SDK version.
- App config affecting native projects.
- Config plugins.
- Android permissions or iOS usage descriptions.
- Custom native modules.
- App extensions, widgets, background modes, URL schemes, or associated domains.
Gotcha: A JavaScript reload cannot test a native dependency that is not inside the installed binary. If the app needs new native code, install a new development build.