ScaleBun
Skip to article

Quick start

react-nativeDeveloper

Enable OTA in init(), let the SDK check for updates automatically, and drive the update UI with the useOtaUpdate hook — download progress, mandatory updates, and restart-to-apply.

Updated

OTA is part of the SDK you already installed — there is no extra package. You turn it on in init(), and from then on the SDK can pull new JS bundles for your app.

1. Enable OTA in init()#

App.tsxTypeScript
import ScaleBun from '@scalebun/react-native';
ScaleBun.init({  clientKey: 'skb_live_ck_…',  apiUrl: 'https://api.scalebun.com/api/v1',  ota: {    enabled: true,           // OTA is off until you opt in    checkOnForeground: true, // check for a new bundle each time the app foregrounds    channelOverride: 'production', // which channel this build follows (optional)    mandatoryBlocksUi: true, // a required update blocks the UI until applied  },});
OptionDefaultWhat it does
enabledfalseMaster switch — OTA does nothing until this is true
checkOnForegroundtrueAutomatically check for an update whenever the app returns to the foreground
channelOverrideFollow a specific channel (e.g. production, beta). Falls back to the app's default channel
mandatoryBlocksUifalseWhen a release is marked mandatory, block the UI until it's applied

With checkOnForeground: true, that's already a working setup: publish a bundle and it reaches this app on its next foreground + restart. The rest of this page is about controlling and surfacing updates in your UI.

2. Drive updates with useOtaUpdate#

useOtaUpdate is a React hook that exposes the update state and a sync() action — ideal for a "check for updates" button, a download bar, or a mandatory-update gate.

UpdateBanner.tsxTSX
import { useOtaUpdate } from '@scalebun/react-native';import DeviceInfo from 'react-native-device-info';
export function UpdateBanner() {  const {    sync,                    // () => Promise<SyncResult>    restart,                 // () => void — apply a staged update now    isSyncing,               // download/verify in progress    downloadProgress,        // 0..1    isRestartRequired,       // a bundle is staged, waiting for restart    mandatoryUpdatePending,  // a required update is waiting    syncResult,              // last result  } = useOtaUpdate({    apiUrl: 'https://api.scalebun.com/api/v1',    clientKey: 'skb_live_ck_…',    appVersion: DeviceInfo.getVersion(),    channelName: 'production',    autoRestart: false, // let the user choose when to apply  });
  if (mandatoryUpdatePending) {    return <BlockingUpdate progress={downloadProgress} />;  }
  if (isRestartRequired) {    return <Banner text="Update ready" action="Restart" onPress={restart} />;  }
  return (    <Button      title={isSyncing ? `Downloading ${Math.round(downloadProgress * 100)}%` : 'Check for updates'}      disabled={isSyncing}      onPress={sync}    />  );}

What the hook returns#

FieldTypeMeaning
sync()() => Promise<SyncResult>Check, download, verify and stage in one call
restart()() => voidApply a staged bundle immediately
isSyncingbooleanA sync is in flight
downloadProgressnumber01 during download
isRestartRequiredbooleanA bundle is staged and waiting for the next restart
mandatoryUpdatePendingbooleanA required update is waiting
activeBundleOtaBundlePayload | nullThe bundle currently running
syncResultSyncResult | nullThe outcome of the last sync
lastEventOtaEvent | nullThe most recent OTA event

SyncResult.status#

TypeScript
type SyncResult = {  status: 'UP_TO_DATE' | 'UPDATE_INSTALLED' | 'ROLLED_BACK' | 'ERROR';  bundle?: OtaBundlePayload;  error?: string;};
  • UP_TO_DATE — nothing newer for this channel/version.

  • UPDATE_INSTALLED — a bundle was downloaded and staged (applies on restart, or now if autoRestart).

  • ROLLED_BACK — the boot guard reverted a bad bundle.

  • ERROR — see error.

3. When updates apply#

A staged bundle activates on the next app restart — never mid-session. You have three ways to control the moment:

  • Do nothing — it applies the next time the OS restarts your app.

  • Prompt — show isRestartRequired and call restart() on the user's tap.

  • Mandatory — mark the release mandatory (dashboard/CLI); with mandatoryBlocksUi the SDK blocks until it's applied.

4. Listen to OTA events (optional)#

For analytics or custom UI, subscribe to the event stream instead of polling:

TypeScript
import { otaEventEmitter } from '@scalebun/react-native';
const off = otaEventEmitter.on('DOWNLOAD_PROGRESS', (e) => {  console.log('progress', e);});// later: off();

Next#

Quick start · OTA updates · React Native SDK · ScaleBun