# Integrate the Genuin SDK with React Native apps

Add Genuin carousels, standard walls, full-screen feeds, single sign-on, deep links, and push notifications to a React Native app with genuin-react-native 3.0.3.

The `genuin-react-native` package wraps the native Genuin SDKs. On Android it pins `com.begenuin:core` and `com.begenuin:ui` 2.1.5; on iOS it pins the `GenuinCore` and `GenuinUI` 2.1.5 pods. It exports four components (`Carousel`, `StandardWall`, `Feed`, and `HomeFeed`) and functions for single sign-on, link-out interception, and push notifications. Initialization, deep-link entitlements, and Firebase setup stay in your Android and iOS projects.

This page covers what the package adds and what you configure natively. For the behaviour underneath (embed layouts, user and contextual parameters, callbacks), see [Integrate the Genuin Android SDK](https://begenuin.com/developers/developer-resources/sdk/how-to-integrate-and-power-your-brand-community-in-android-apps) and [Integrate the Genuin iOS SDK](https://begenuin.com/developers/developer-resources/sdk/developer/genuin-sdk/native-compatibility/ios/how-to-integrate-and-power-your-brand-community-in-ios-apps).

## Requirements

| | Minimum |
| --- | --- |
| React Native | Any version is accepted as a peer dependency; the package is built and tested against 0.81.5. It ships a TurboModule spec for the New Architecture and a legacy module for apps with newArchEnabled=false. |
| Android | minSdk 24, compileSdk and targetSdk 36, Kotlin 2.1.20 (read from rootProject.ext.kotlinVersion), Java 17, and a Material Components theme |
| iOS | Deployment target 15.1 (React Native 0.81's minimum; the Genuin pods declare 13.0), CocoaPods with dynamic frameworks, and an Objective-C bridging header when AppDelegate is Swift |
| Push notifications | A Firebase project and @react-native-firebase/messaging |
| Credentials | An API key and one or more embed IDs from Brand Control Center |

The API key comes from **Build** > **Publish Brand Community** > **SDK Integration** in Brand Control Center. That screen has a React Native tab and a switch between the **Live Environment** and **QA Environment** keys. Embed IDs come from [Generate an embed code in Brand Control Center](https://begenuin.com/developers/browse-by-products/onsite/how-do-brands-generate-embed-codes-from-brand-control-center).

## Step 1: Install the package

```bash title="Terminal"
npm install genuin-react-native   # or: yarn add genuin-react-native
cd ios && pod install
```

Autolinking registers `GenuinSDKPluginPackage` on Android and the `genuin-react-native` pod on iOS. The pod requires `GenuinCore` and `GenuinUI` at exactly 2.1.5, and the Android module requires `com.begenuin:core` and `com.begenuin:ui` 2.1.5, so you don't declare the native SDKs yourself.

## Step 2: Configure the Android project

1. Set the minimum SDK in `android/app/build.gradle`:

```groovy title="android/app/build.gradle"
android {
    defaultConfig {
        minSdk = 24
    }
}
```

2. Check your repositories. The package adds ByteDance's Pangle repository (the Pangle SDK is a dependency of `com.begenuin:core`) to every project at configuration time, and `core` also needs two libraries from JitPack. If your `settings.gradle` uses `RepositoriesMode.FAIL_ON_PROJECT_REPOS`, declare both there instead:

```groovy title="android/settings.gradle"
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" }
        maven { url "https://artifact.bytedance.com/repository/pangle" }
    }
}
```

3. Update `android/app/src/main/AndroidManifest.xml`. The SDK's manifests declare `android:allowBackup="false"`, so your app must match or the manifest merge fails. Add the `tools` namespace, the `INTERNET` permission, and the attributes below:

```xml title="AndroidManifest.xml"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        android:name=".MainApplication"
        android:allowBackup="false"
        android:theme="@style/AppTheme"
        tools:remove="android:taskAffinity">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTask"
            android:windowSoftInputMode="adjustPan"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
```

4. Use a Material Components theme in `android/app/src/main/res/values/styles.xml`. The SDK's own themes extend `Theme.MaterialComponents.DayNight.NoActionBar.Bridge`, and its views are Material Components that read theme attributes from your activity. A non-Material `AppTheme` crashes when the first Genuin view inflates.

```xml title="styles.xml"
<resources>
    <style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
</resources>
```

5. Add ProGuard rules for minified release builds. The `core` and `ui` AARs ship consumer rules that keep their own public classes and Retrofit, so a release build runs without any app-side rule. The package README asks for the block below as well; add it to `android/app/proguard-rules.pro` if your shrunk build misbehaves:

```proguard title="proguard-rules.pro"
-keep class com.bumptech.glide.** { *; }
-keep class com.begenuin.core.data.model.** { <fields>; }
-keepattributes Signature, InnerClasses, EnclosingMethod, *Annotation*
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
-keepclassmembers,allowshrinking,allowobfuscation interface * { @retrofit2.http.* <methods>; }
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>
-keep public class * implements java.lang.reflect.Type
-dontwarn javax.annotation.**
-dontwarn retrofit2.KotlinExtensions
-dontwarn com.google.android.play.core.**
```

6. To replace the loading animation (Optional), add a Lottie file named exactly `loader_mix.json` to `android/app/src/main/res/raw/`. A resource with that name overrides the SDK's.

## Step 3: Initialize the SDK on Android

Initialize in `MainActivity.onCreate`, before React renders the first Genuin component, and hand incoming deep links to the SDK:

```kotlin title="android/app/src/main/java/.../MainActivity.kt"
import android.content.Intent
import android.os.Bundle
import com.facebook.react.ReactActivity
import com.genuinsdk.GenuinSDKPluginModule

class MainActivity : ReactActivity() {
  override fun getMainComponentName(): String = "YourApp"

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    GenuinSDKPluginModule.initSDK(application, "<<YOUR_API_KEY>>")   // isQAEnv = true for a QA key
    if (intent?.data != null) GenuinSDKPluginModule.handleDeepLink(this, intent)
  }

  override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    if (intent.data != null) GenuinSDKPluginModule.handleDeepLink(this, intent)
  }
}
```

`initSDK(application, apiKey, isQAEnv = false, fontFamily = "", gamAppId = "")` calls the native `GenuinSDK.initSDK` with `GenuinEnv.QA` when `isQAEnv` is `true`. Keys aren't shared between environments. Keep the key out of source control by injecting it through a `BuildConfig` field or a secrets plugin.

For deep links to open your app, the manifest also needs an intent filter for your white-labelled domain, plus a Digital Asset Links file on that domain:

```xml title="AndroidManifest.xml"
<activity android:name=".MainActivity" ...>
    <intent-filter android:autoVerify="true">
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />
        <data android:host="{{YOUR_DOMAIN}}" android:scheme="https" />
    </intent-filter>
</activity>
```

Genuin serves `assetlinks.json` on your white-labelled domain once you send your package name and signing fingerprints; [Handle Genuin deep links in your app](https://begenuin.com/developers/developer-resources/sdk/handle-genuin-deep-links-in-your-app) covers the request. For push notifications, add the Google Services plugin to `android/build.gradle` and your `google-services.json` to `android/app/`:

```groovy title="android/build.gradle"
buildscript {
    dependencies {
        classpath("com.google.gms:google-services:4.4.2")
    }
}
```

## Step 4: Configure the iOS project

1. In `ios/Podfile`, build with dynamic frameworks, keep `RNReanimated` static, and set the deployment target on every pod:

```ruby title="Podfile"
ENV['USE_FRAMEWORKS'] = 'dynamic'
platform :ios, min_ios_version_supported
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym

target 'YourApp' do
  config = use_native_modules!
  use_react_native!(:path => config[:reactNativePath], :app_path => "#{Pod::Config.instance.installation_root}/..")

  pre_install do |installer|
    installer.pod_targets.each do |pod|
      if pod.name.eql?('RNReanimated')
        def pod.build_type; Pod::BuildType.static_library; end
      end
    end
  end

  post_install do |installer|
    react_native_post_install(installer, config[:reactNativePath], :mac_catalyst_enabled => false)
    installer.pods_project.targets.each do |target|
      target.build_configurations.each do |config|
        config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.1'
        config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
      end
    end
  end
end
```

2. If your `AppDelegate` is Swift, add an Objective-C wrapper, because the pod's `GenuinSDKPlugin.h` is Objective-C++. Create `GenuinModuleObjCWrapper.h`:

```objc title="GenuinModuleObjCWrapper.h"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface GenuinModuleObjCWrapper : NSObject
+ (void)initSDK:(NSString *_Nullable)apiKey isQAEnv:(BOOL)isQAEnv loaderName:(NSString *_Nullable)loaderName showNavigationBar:(BOOL *_Nullable)showNavigationBar;
+ (BOOL)willHandleDeepLinkWithUrl:(NSURL *_Nonnull)url;
+ (BOOL)handleDeepLink:(NSURL *_Nullable)dlURL controller:(UIViewController *_Nullable)controller;
+ (void)handleForegroundNotification:(NSDictionary *)notificationData;
+ (UINavigationController *_Nullable)getGenuinNavigationController:(UIViewController *)viewController;
@end
NS_ASSUME_NONNULL_END
```

3. Create `GenuinModuleObjCWrapper.mm`, which forwards each call to `GenuinSDKPlugin`:

```objc title="GenuinModuleObjCWrapper.mm"
#import "GenuinModuleObjCWrapper.h"
#import "GenuinSDKPlugin.h"
@implementation GenuinModuleObjCWrapper
+ (void)initSDK:(NSString *)apiKey isQAEnv:(BOOL)isQAEnv loaderName:(NSString *)loaderName showNavigationBar:(BOOL *)showNavigationBar {
  [GenuinSDKPlugin initSDK:apiKey isQAEnv:isQAEnv loaderName:loaderName showNavigationBar:showNavigationBar];
}
+ (BOOL)willHandleDeepLinkWithUrl:(NSURL *)url { return [GenuinSDKPlugin willHandleDeepLinkWithUrl:url]; }
+ (BOOL)handleDeepLink:(NSURL *)dlURL controller:(UIViewController *)controller {
  return [GenuinSDKPlugin handleDeepLink:dlURL controller:controller];
}
+ (void)handleForegroundNotification:(NSDictionary *)notificationData {
  [GenuinSDKPlugin handleForegroundNotification:notificationData];
}
+ (UINavigationController *)getGenuinNavigationController:(UIViewController *)viewController {
  return [GenuinSDKPlugin getGenuinNavigationController:viewController];
}
@end
```

4. Import the wrapper in your bridging header, `YourApp-Bridging-Header.h`:

```objc title="YourApp-Bridging-Header.h"
#import "GenuinModuleObjCWrapper.h"
```

## Step 5: Initialize the SDK on iOS

Initialize in `didFinishLaunchingWithOptions`, then wrap React Native's root view controller in the Genuin navigation controller. The SDK pushes its own screens (full-screen feed, comments, profile) onto that stack.

```swift title="ios/YourApp/AppDelegate.swift"
import UIKit
import React
import React_RCTAppDelegate
import Firebase

@main
class AppDelegate: RCTAppDelegate, UNUserNotificationCenterDelegate {
  override func application(_ application: UIApplication,
                            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil) -> Bool {
    self.moduleName = "YourApp"
    if FirebaseApp.app() == nil { FirebaseApp.configure() }
    UNUserNotificationCenter.current().delegate = self
    UIApplication.shared.registerForRemoteNotifications()
    GenuinModuleObjCWrapper.initSDK("<<YOUR_API_KEY>>", isQAEnv: false,
                                    loaderName: "{{LOTTIE_LOADER_NAME}}", showNavigationBar: nil)
    addNavVC()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

  func addNavVC() {
    DispatchQueue.main.async {
      guard let rootVC = self.window.rootViewController else { return }
      self.window.rootViewController = nil
      let navVC = GenuinModuleObjCWrapper.getGenuinNavigationController(rootVC)
      navVC?.setNavigationBarHidden(true, animated: true)
      self.window.rootViewController = navVC
      self.window.makeKeyAndVisible()
    }
  }
}
```

`loaderName` is the name of a Lottie file in your main bundle that replaces the SDK's loading animation; pass `nil` to keep the default. `isQAEnv: true` points the SDK at the QA environment and needs a QA key.

Deep links on iOS arrive as universal links. Let the SDK claim the ones it recognizes:

```swift title="Universal links"
override func application(_ application: UIApplication, continue userActivity: NSUserActivity,
                          restorationHandler: @escaping ([any UIUserActivityRestoring]?) -> Void) -> Bool {
  if let url = userActivity.webpageURL,
     GenuinModuleObjCWrapper.willHandleDeepLink(with: url),
     GenuinModuleObjCWrapper.handleDeepLink(url, controller: window.rootViewController) {
    return true
  }
  return false
}
```

Add the Associated Domains entitlement with `applinks:{{YOUR_DOMAIN}}`. Genuin serves the `apple-app-site-association` file on that domain once you send your Team ID and bundle ID; [Handle Genuin deep links in your app](https://begenuin.com/developers/developer-resources/sdk/handle-genuin-deep-links-in-your-app) covers the request.

For push notifications, forward the APNs token to Firebase, register the FCM token with the SDK, and pass tapped notifications to it. The package doesn't export the push functions to JavaScript on iOS, so this happens in `AppDelegate`. Set `Messaging.messaging().delegate = self` and the notification center delegate in `didFinishLaunchingWithOptions`:

```swift title="Push notifications"
import FirebaseMessaging
import GenuinCore

override func application(_ application: UIApplication,
                          didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
  Messaging.messaging().apnsToken = deviceToken
}

extension AppDelegate: MessagingDelegate {
  func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
    if let fcmToken { GenuinSDK.shared.registerFCMToken(token: fcmToken) }
  }

  func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification,
                              withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    completionHandler([.list, .banner, .badge, .sound])
  }

  func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse,
                              withCompletionHandler completionHandler: @escaping () -> Void) {
    GenuinModuleObjCWrapper.handleForegroundNotification(["data": response.notification.request.content.userInfo])
    completionHandler()
  }
}
```

`handleForegroundNotification` checks whether the payload is Genuin's and, if so, opens the matching screen on the top view controller. Other notifications are ignored, so your own handling is unaffected.

## Step 6: Render an embed

Each component renders one embed configured in Brand Control Center. Give every component an explicit size through `style`; a component without a height renders nothing.

```tsx title="CarouselScreen.tsx"
import React, { useRef } from 'react';
import { Carousel, type PlayPauseRef } from 'genuin-react-native';

export default function CarouselScreen() {
  const carouselRef = useRef<PlayPauseRef>(null);
  return (
    <Carousel
      ref={carouselRef}
      style={{ height: 400, width: '100%' }}
      embedId="{{EMBED_ID}}"
      uniqueId="home-carousel"
      ssoToken="{{SSO_TOKEN}}"
      isShowProfileEnabled={false}
      isDirectDeepLinkEnabled={false}
    />
  );
}
```

| Component | Renders | Platforms |
| --- | --- | --- |
| Carousel | A horizontal carousel or grid, depending on the embed's layout | Android, iOS |
| StandardWall | A standard wall that takes over its container | Android, iOS |
| Feed | A full-screen vertical feed | Android, iOS |
| HomeFeed | The brand's home feed, with no embed ID | Android only |

`StandardWall` and `Feed` are normally given `{ height: '100%', width: '100%' }`. Render `HomeFeed` only when `Platform.OS === 'android'`; on iOS the native view isn't registered and the component throws.

### Props

All four components accept `style`. `Carousel`, `StandardWall`, and `Feed` accept the embed props below; `HomeFeed` takes none.

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| embedId | string | Yes | — | The embed to load, from Brand Control Center |
| uniqueId | string | No | — | Set a different value for each instance when the same embed appears more than once, on one screen or across screens |
| ssoToken | string | No | — | Signs the viewer in before the embed loads. See Step 7. |
| params | object | No | — | name, email, mobile, nickname, profile_image to pre-fill the viewer's profile. On Android it's applied only together with ssoToken. |
| contextualParams | object | No | — | page_context and geo to rank the feed toward the screen and the viewer. See Deliver contextual feeds. |
| interactionDeepLink | string | No | — | A URL to open instead of the SDK's own flow when the viewer interacts in the full-screen view. Android only. |
| isDirectDeepLinkEnabled | boolean | No | false | Opens the specific video in your white-labelled app on interaction; interactionDeepLink is then ignored. Needs the deep-link setup from Steps 3 and 5. |
| isDirectDeepLinkWithLoginEnabled | boolean | No | false | Like isDirectDeepLinkEnabled, after the viewer signs in. Android only. |
| isShowProfileEnabled | boolean | No | false | Shows the signed-in viewer's profile picture in the full-screen view, with account settings and sign-out |
| interTileSpacing | number (dp) | No | 8 | Gap between carousel tiles. Carousel only. |
| carouselInsetTop, carouselInsetLeft, carouselInsetBottom, carouselInsetRight | number (dp) | No | 8, 16, 0, 16 | Space between the carousel and its container. Carousel only. |
| tileCornerRadius | number (dp) | No | 8 | Rounding of each tile. Carousel only. |
| isVerticalScrollDirection | boolean | No | false | Declared in the typings but has no effect in 3.0.3 |

Numbers are in dp on Android (the package converts them to pixels) and in points on iOS.

### Pause and resume playback

Videos autoplay. On Android, the `ref` gives you `pause()` and `resume()`, which forward to the native view; call them when your screen loses and regains focus:

```tsx title="Pause and resume"
import React from 'react';
import { useFocusEffect } from '@react-navigation/native';

useFocusEffect(
  React.useCallback(() => {
    carouselRef.current?.resume();
    return () => carouselRef.current?.pause();
  }, [])
);
```

On iOS the components ignore the ref, and playback follows the native view's own lifecycle.

## Step 7: Sign users in with single sign-on

Viewers can browse without an account. To let them post, comment, or follow, your server issues an SSO token for the user and you pass it to the SDK. Either set `ssoToken` on a component, or sign in once for every view:

```ts title="Sign in"
import { ssoLogin, ssoLogout } from 'genuin-react-native';

// After your app authenticates the user
ssoLogin('{{SSO_TOKEN}}', { name: 'John Doe', email: 'john.doe@example.com' });

// When the user signs out of your app
ssoLogout();
```

The second argument is optional and takes the same keys as `params`; the SDK uses them the first time the account is created. How tokens are issued and validated is explained in [Choose how members sign in to the Genuin SDK](https://begenuin.com/developers/developer-resources/sdk/user-authentication-mechanisms-in-genuin-sdk).

### Let the SDK ask your app to sign in

When a signed-out viewer taps an action that needs an account, the SDK can return to your app instead of showing its own login. Register once at startup, and listen for the two events the package emits:

```ts title="Sign-in request"
import { DeviceEventEmitter, NativeEventEmitter, Platform } from 'react-native';
import { GenuinSDKPlugin, registerCallback, registerLinkOutCallback, ssoLogin } from 'genuin-react-native';

registerCallback();                              // 'NavigateToScreen' with 'Login' when sign-in is needed
registerLinkOutCallback(['shop.example.com']);   // 'LinkOutRedirection' with the URL for these domains

const emitter = Platform.OS === 'ios' ? new NativeEventEmitter(GenuinSDKPlugin) : DeviceEventEmitter;
emitter.addListener('NavigateToScreen', (screen: string) => {
  if (screen === 'Login') {
    // Run your sign-in flow, then: ssoLogin('{{SSO_TOKEN}}')
  }
});
emitter.addListener('LinkOutRedirection', (url: string) => {
  // Route the product URL inside your app
});
```

On Android, the SDK first brings your launcher activity back to the front and then emits the event. Without `registerCallback`, the SDK shows its own sign-in screens. `registerLinkOutCallback` takes the domains your app handles; link-outs to any other domain open in the browser.

## Step 8: Handle push notifications

Genuin sends notifications for replies, mentions, and community activity through Firebase Cloud Messaging (FCM). Genuin also needs your Firebase project's credentials to send anything; [Set up push notifications in the Genuin SDK](https://begenuin.com/developers/get-started/developers/genuin-sdk/creation-n-editing-tools/how-do-push-notifications-work-with-the-genuin-sdk) covers that step, the payload, and every notification type.

1. Create the Firebase project, add `google-services.json` (Android) and `GoogleService-Info.plist` (iOS), and install `@react-native-firebase/app` and `@react-native-firebase/messaging`.
2. On Android, mount this controller once, after your first screen renders. On iOS, the `AppDelegate` code in [Step 5](#step-5-initialize-the-sdk-on-ios) handles tokens and taps:

```tsx title="NotificationController.tsx"
import { useEffect } from 'react';
import { PermissionsAndroid, Platform } from 'react-native';
import messaging, { type FirebaseMessagingTypes } from '@react-native-firebase/messaging';
import { GenuinSDKPlugin } from 'genuin-react-native';

const open = (m: FirebaseMessagingTypes.RemoteMessage | null) => {
  if (m && GenuinSDKPlugin.willHandleBackgroundNotifications(m)) GenuinSDKPlugin.handleBackgroundNotifications(m);
};

export default function NotificationController() {
  useEffect(() => {
    if (Platform.OS !== 'android') return; // iOS: AppDelegate, Step 5
    PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
    messaging().getToken().then((token) => GenuinSDKPlugin.registerFCMToken(token));
    const offRefresh = messaging().onTokenRefresh((token) => GenuinSDKPlugin.registerFCMToken(token));
    const offMessage = messaging().onMessage(async (m) => {
      const payload = { data: m.data, body: m.notification?.body ?? '', title: m.notification?.title, icon: 'drawable/ic_notification' };
      if (GenuinSDKPlugin.willHandleForegroundNotifications(payload)) GenuinSDKPlugin.handleForegroundNotifications(payload);
    });
    const offOpened = messaging().onNotificationOpenedApp(open);
    messaging().getInitialNotification().then(open);
    return () => { offRefresh(); offMessage(); offOpened(); };
  }, []);
  return null;
}
```

The foreground payload must carry `data` and `body`. `icon` names the small notification icon in your Android resources as `folder/name`; the SDK falls back to a system icon when it's missing. `registerFCMToken` needs a running activity, which is why the controller mounts after the first screen. `willHandleForegroundNotifications` and `willHandleBackgroundNotifications` return `false` for notifications that aren't Genuin's, so your own notifications are unaffected.

## Limitations

- **Pinned native SDKs**: the package fixes the Android and iOS SDKs at 2.1.5. To use another version you need a fork.
- **Explicit size required**: every component needs a height and width in `style`; `wrap_content`-style sizing renders nothing.
- **iOS ignores some props and the ref**: `interactionDeepLink` and `isDirectDeepLinkWithLoginEnabled` aren't forwarded, `StandardWall` ignores `params` and `contextualParams`, and `pause()` and `resume()` have no effect.
- **`HomeFeed`** **is Android only**: rendering it on iOS throws, because no native view is registered.
- **Push helpers are Android only**: `registerFCMToken` and the four notification functions aren't exported to JavaScript on iOS; iOS taps go through `AppDelegate`.
- **No web target**: the package resolves native views at import time, so it can't run in a web bundle.
- **Material theme required**: Android needs a `Theme.MaterialComponents` parent on the app theme.
- **Deep links need a white-labelled domain**: `handleDeepLink` only resolves links on a domain configured in Brand Control Center.

## See also

- [Integrate the Genuin Android SDK](https://begenuin.com/developers/developer-resources/sdk/how-to-integrate-and-power-your-brand-community-in-android-apps)
- [Integrate the Genuin iOS SDK](https://begenuin.com/developers/developer-resources/sdk/developer/genuin-sdk/native-compatibility/ios/how-to-integrate-and-power-your-brand-community-in-ios-apps)
- [Integrate the Genuin SDK with Flutter apps](https://begenuin.com/developers/developer-resources/sdk/how-do-you-integrate-the-genuin-flutter-sdk-into-your-application)
- [Add IAB Standard Size Experiences to a React Native app](https://begenuin.com/developers/developer-resources/sdk/integrate-ads-with-react-native-sdk)
- [How Auto Login works](https://begenuin.com/developers/developer-resources/sdk/genuin-auto-login)
