Before changing code: inventory the old system
- List every iOS and Android application, deployment, deployment key, target binary version, and rollout policy.
- Find CodePush references in JavaScript,
AppDelegate,MainApplication, plist, manifest, CI, and release scripts. - Record which binary versions are still active in production.
- Export the last known-good release metadata and your current embedded bundle version.
- Decide how long old binaries will remain supported after the new binary launches.
1. Create the NitroPush release boundaries
Create a NitroPush project and separate test, stage, and production environments. Each environment gets its own deployment key. Keep production credentials separate from preview or internal-test builds.
2. Replace the client package
npm uninstall react-native-code-push
npm install @nitropush/react-native react-native-nitro-modulesRemove the CodePush higher-order component or old synchronization calls. NitroPush returns a client from a module-scope configure() call and passes that client to the sync() helper.
import { configure, sync, InstallMode } from '@nitropush/react-native';
const client = configure();
// After the first successful render:
await client.notifyAppReady();
// At your chosen update-check point:
await sync(client, { installMode: InstallMode.ON_NEXT_RESUME });3. Wire the native bundle resolver
Expo
Add the @nitropush/react-native config plugin with deploymentKeyEnvVar naming a private build variable (default NITROPUSH_DEPLOYMENT_KEY), run npx expo prebuild, and rebuild the development client or native application. Keep the actual key out of committed app.json and every EXPO_PUBLIC_* variable.
Bare React Native
Set NITROPUSH_DEPLOYMENT_KEY in Info.plist and AndroidManifest metadata. Configure release builds to resolve the active NitroPush bundle while preserving Metro for DEBUG builds. Follow the current Swift and Kotlin snippets in the installation documentation.
4. Establish the health-confirmation point
Call client.notifyAppReady() after the application’s first known-good render. This replaces assumptions based only on download success: a newly activated bundle stays pending until the application proves it reached a healthy state.
5. Decide on bundle signing before production
Signing is easiest to establish before the first NitroPush-enabled store release because the public verification key is part of the trusted native configuration. Generate an ECDSA P-256 keypair, register the public key, keep the private PEM out of source control, and sign every production upload.
6. Replace the release pipeline
nitropush release upload \
--project <project-id> \
--environment prod \
--runtime-version 1.2.3 \
--label 1.2.4 \
--bundle-path ./distThe CLI auto-detects Expo export metadata or CodePush-style Hermes/JavaScript bundles. Add --signing-key <temporary-pem-path> when signing is enabled. Use explicit project, environment, native app version, release label, and bundle path values in CI.
7. Test failure—not only success
- Install a release build containing its embedded bundle.
- Publish a harmless staging OTA update and confirm download and activation.
- Confirm
notifyAppReady()marks it healthy. - Publish a controlled test bundle that does not confirm health.
- Verify the next launch restores the previous known-good bundle.
- Verify signature rejection with an invalid signing key in an isolated test environment.
- Verify debug builds continue to load Metro.
8. Roll out the new native binary
Release the NitroPush-enabled binary through the stores and monitor adoption. Do not retire migration messaging or old-version support until enough active users have moved to the new binary. The first NitroPush OTA should target only the exact native version you validated.
CodePush-to-NitroPush concept mapping
| CodePush concept | NitroPush equivalent |
|---|---|
| App | Project |
| Deployment | Environment |
| Deployment key | Environment deployment key |
| Target binary version | App version |
| Release label | Release label |
| Rollout | Release rollout percentage |
codePush.sync() | sync(client, options) |