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

NeedUse
App name, package, bundle ID, version, icons, schemeApp config
Android permissions or iOS Info.plist valuesApp config or package config plugin
Library-specific native setupExisting config plugin
Repeated generated-native editsCustom config plugin
Custom Swift/Kotlin APIExpo Modules API
Fully hand-managed native projectCommit 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.