SDK Usage Guide
Automatic Updates
The simplest approach. Updates are checked and installed automatically:
import { initNorrix } from '@norrix/client-sdk';
initNorrix({
updateUrl: 'https://norrix.net',
checkForUpdatesOnLaunch: true,
installUpdatesAutomatically: true,
});With this configuration:
- App launches and checks for updates
- If compatible update available, it’s downloaded
- Update is installed silently
- Update activates on next app restart
With Restart Prompt
Prompt users to restart after an update:
initNorrix({
updateUrl: 'https://norrix.net',
checkForUpdatesOnLaunch: true,
installUpdatesAutomatically: true,
promptToRestartAfterInstall: true, // Shows restart dialog
});Manual Update Control
For full control over the update flow:
import { initNorrix } from '@norrix/client-sdk';
// Initialize without auto-install
const norrix = initNorrix({
updateUrl: 'https://norrix.net',
});
// Check for updates manually
async function checkAndApplyUpdate() {
const update = await norrix.checkForUpdates();
if (!update.updateAvailable) {
console.log('App is up to date');
return;
}
if (update.requiresStoreUpdate) {
// Native changes detected - direct user to app store
showStoreUpdatePrompt(update.compatibilityReason);
return;
}
// Show update prompt to user
const shouldUpdate = await showUpdateDialog({
version: update.version,
releaseNotes: update.releaseNotes,
});
if (!shouldUpdate) {
return; // User declined
}
// Download the update
const success = await norrix.downloadUpdate(update);
if (success) {
// Apply the update
norrix.applyUpdate();
}
}Status Monitoring
Track update progress with callbacks:
import { initNorrix, SyncStatus } from '@norrix/client-sdk';
initNorrix({
updateUrl: 'https://norrix.net',
checkForUpdatesOnLaunch: true,
installUpdatesAutomatically: true,
statusCallback: (status, data) => {
switch (status) {
case SyncStatus.CHECKING_FOR_UPDATE:
showSpinner('Checking for updates...');
break;
case SyncStatus.DOWNLOADING_PACKAGE:
showSpinner('Downloading update...');
break;
case SyncStatus.INSTALLING_UPDATE:
showSpinner('Installing update...');
break;
case SyncStatus.UPDATE_INSTALLED:
hideSpinner();
showToast(`Update ${data?.version} ready!`);
break;
case SyncStatus.UP_TO_DATE:
hideSpinner();
break;
case SyncStatus.ERROR:
hideSpinner();
showError(data?.message);
break;
}
},
downloadProgressCallback: (progress) => {
updateProgressBar(progress);
},
});What Can Be Updated
✅ OTA-Compatible Changes
These changes can be pushed via OTA:
- JavaScript/TypeScript code: Business logic, API calls, utilities
- CSS/SCSS styles: Colors, layouts, animations
- Assets: Images, fonts, icons (in
/srcor/app) - Non-native npm packages: Pure JS/TS packages
❌ Requires Store Build
These changes require a new store binary:
- NativeScript platform versions:
@nativescript/ios,@nativescript/android - Native plugin updates: Plugins with native code
- App_Resources changes: Icons, splash screens, Info.plist
- Custom native code: NativeSource files
Reset OTA Updates
To reset all OTA updates and return to the original store binary:
const norrix = initNorrix({
updateUrl: 'https://norrix.net',
});
// Clear all OTA updates
norrix.resetAllOTAs();This:
- Clears stored OTA fingerprint and version
- Removes downloaded OTA packages
- Prompts user to restart
- App restarts with original store binary
Use Cases
- Debugging OTA issues on a single device
- Reverting a problematic update for testing
- Developer testing
To roll back all users to an older codebase, publish a new OTA update with a bumped build number instead. See Rolling Back an OTA Update.
Automatic Crash Recovery
The SDK includes built-in crash recovery. If an OTA update causes the app to crash on launch, Norrix automatically rolls back to the original store binary on the next launch attempt. No code is required — this protection is active as soon as the SDK is initialized.
After a crash recovery, the SDK reports the incident to your OTA analytics, including the version and build number of the OTA that caused the crash. You can view this data in Dashboard → OTA Analytics.
Crash recovery only triggers for launch crashes (before SDK initialization completes). Runtime crashes during normal app use do not trigger a rollback — those are application bugs, not OTA delivery failures.
For a detailed explanation of how crash recovery works, see OTA Crash Recovery.
Fingerprint Access
Get the current native binary fingerprint:
const norrix = initNorrix({
updateUrl: 'https://norrix.net',
});
const hash = norrix.getCurrentFingerprintHash();
console.log('Binary fingerprint:', hash);This returns the fingerprint hash embedded in the native binary:
- iOS:
NorrixFingerprintHashinInfo.plist - Android:
norrixFingerprintHashinBuildConfig
The value is baked in at build time and cannot be modified by OTA updates, making it the single source of truth for native compatibility checks.
Force Close App
Utility to close the app (useful for manual restart handling):
norrix.closeAppNow();This calls:
- iOS:
exit(0) - Android:
java.lang.System.exit(0)
Use with caution. Only call after user confirmation.
HMR Compatibility
When Hot Module Replacement (HMR) is enabled during development, the SDK skips OTA checks to avoid conflicts:
statusCallback: (status) => {
if (status === SyncStatus.SKIPPING_BECAUSE_HMR_ENABLED) {
console.log('OTA skipped - HMR is active');
}
};This is automatic. No configuration needed.
Error Handling
Handle update errors gracefully:
initNorrix({
updateUrl: 'https://norrix.net',
checkForUpdatesOnLaunch: true,
installUpdatesAutomatically: true,
statusCallback: (status, data) => {
if (status === SyncStatus.ERROR) {
// Log error for debugging
console.error('OTA Error:', data?.message);
// Optionally notify error tracking
Sentry.captureException(new Error(data?.message));
// App continues normally - OTA is non-blocking
}
},
});OTA errors are non-fatal. The app continues with its current version.