Quick Start With Supabase

This guide walks you through setting up hot-updater with Supabase in a React Native project. You'll configure the environment, install required packages, and initialize Supabase for seamless updates.

Prerequisites

Before you begin, make sure the following are ready:

  • Node.js: Version 20 or later is recommended.
  • Supabase CLI: Install it via npx supabase.
  • Supabase Account: Sign up at Supabase if you don’t have one.

Step 1: Install Required Packages

Run the following command to install dependencies:

npm
pnpm
yarn
npm install hot-updater --save-dev

Step 2: Configure Supabase

Run the initialization script to start the interactive setup process. Use the following command with your preferred package manager:

npm
pnpm
yarn
npx hot-updater init
Interactive Setup Steps
  1. Select a Build Plugin: Choose a build plugin for your project (e.g., Metro for React Native).
  2. Select a Provider: Select Supabase as the provider for handling updates.

During the setup, you will be prompted to:

  1. Create or Select a Supabase Organization: Choose an existing organization or create a new one.
  2. Create or Select a Project: Choose an existing project or create a new one within your organization.
  3. Configure Storage: Select an existing storage bucket or create a new public bucket to store updates.
  4. Database Migration: create a new one to store updates.
  5. Deploy Edge Function: Deploy a Supabase Edge Function called update-server.

Once the setup is complete, a .env file will be generated containing the following keys:

HOT_UPDATER_SUPABASE_ANON_KEY=your-anon-key HOT_UPDATER_SUPABASE_BUCKET_NAME=your-bucket-name HOT_UPDATER_SUPABASE_URL=https://your-project-id.supabase.co
WARNING

The .env file should remain secure, as it contains sensitive keys required for the hot-updater to function.

Step 3: Generated Configurations

During the initialization process, the following file is automatically generated:

  • hot-updater.config.ts: This file contains the configuration settings for integrating Supabase with your project.
hot-updater.config.ts
import { metro } from "@hot-updater/metro";
import { supabaseDatabase, supabaseStorage } from "@hot-updater/supabase";
import { defineConfig } from "hot-updater";
import "dotenv/config";

export default defineConfig({
  build: metro(),
  storage: supabaseStorage({
    supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
    supabaseAnonKey: process.env.HOT_UPDATER_SUPABASE_ANON_KEY!,
    bucketName: process.env.HOT_UPDATER_SUPABASE_BUCKET_NAME!,
  }),
  database: supabaseDatabase({
    supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
    supabaseAnonKey: process.env.HOT_UPDATER_SUPABASE_ANON_KEY!,
  }),
});

Step 4: Add HotUpdater to Your Project

The HotUpdater component wraps your application, enabling seamless delivery of updates and fallback UI during updates. Follow these steps to integrate it into your App.tsx:

App.tsx
import { HotUpdater } from "@hot-updater/react-native";

function App() {
  return (
    <View>
      <Text>Hello World</Text>
    </View>
  );
}

export default HotUpdater.wrap({ 
  source: "https://<project-id>.supabase.co/functions/v1/update-server",
  requestHeaders: {
    // if you want to use the request headers, you can add them here
  },
  fallbackComponent: ({ progress = 0 }) => (
    <Modal transparent visible={true}>
      <View
        style={{
          flex: 1,
          padding: 20,
          borderRadius: 10,
          justifyContent: "center",
          alignItems: "center",
          backgroundColor: "rgba(0, 0, 0, 0.5)",
        }}
      >
        <Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
          Updating...
        </Text>
        <Text style={{ color: "white", fontSize: 20, fontWeight: "bold" }}>
          {Math.round(progress * 100)}%
        </Text>
      </View>
    </Modal>
  ),
})(App);

Step 5: Add Babel Plugin to Your Project

In this step, you will configure Babel to set the bundle ID at build time. This is necessary for integrating the hot-updater plugin into your project.

Add the following to your babel.config.js file:

babel.config.js
module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: [
    'hot-updater/babel-plugin', 
  ],
};

Step 6: Add Native Code

To complete the integration of hot-updater, you'll need to add native code modifications for both Android and iOS platforms. This step ensures the hot-updater can interact with your app's underlying framework to apply updates seamlessly.

Android

Kotlin
Java
android/app/src/main/java/com/<your-app-name>/MainActivity.kt
package com.hotupdaterexample

import android.app.Application
import android.util.Log
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.soloader.OpenSourceMergedSoMapping
import com.facebook.soloader.SoLoader
import com.hotupdater.HotUpdater 

class MainApplication :
    Application(),
    ReactApplication {
    override val reactNativeHost: ReactNativeHost =
        object : DefaultReactNativeHost(this) {
            override fun getPackages(): List<ReactPackage> =
                PackageList(this).packages.apply {
                    // Packages that cannot be autolinked yet can be added manually here, for example:
                    // add(MyReactNativePackage())
                }

            override fun getJSMainModuleName(): String = "index"

            override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG

            override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
            override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED

            override fun getJSBundleFile(): String? {  
                return HotUpdater.getJSBundleFile(applicationContext)  
            }  
        }
    
    override val reactHost: ReactHost
              get() = getDefaultReactHost(applicationContext, reactNativeHost)

    override fun onCreate() {
        super.onCreate()
        SoLoader.init(this, OpenSourceMergedSoMapping)

        if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
            // If you opted-in for the New Architecture, we load the native entry point for this app.
            load()
        }
    }
}

iOS

ios/<your-app-name>/AppDelegate.mm
#import "AppDelegate.h"
#import <HotUpdater/HotUpdater.h> 
#import <React/RCTBundleURLProvider.h>

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  self.moduleName = @"HotUpdaterExample";
  // You can add your custom initial props in the dictionary below.
  // They will be passed down to the ViewController used by React Native.
  self.initialProps = @{};

  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  return [self bundleURL];
}

- (NSURL *)bundleURL
{
#if DEBUG 
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"]; 
#else 
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 
#endif 
  return [HotUpdater bundleURL]; 
}

@end

Verifying the Setup

  1. Check your Supabase dashboard for the newly created bucket and edge function.
  2. Test the HotUpdater integration in your React Native app.

You’re all set! 🎉 Start using hot-updater with Supabase for seamless updates in your React Native app.

This document simplifies the initialization process, making it easy for developers to get started with minimal friction.