npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@octopus-community/react-native

v1.13.3

Published

React Native module for the Octopus Community SDK

Readme

Octopus Community SDK for React Native

npm package Android SDK iOS SDK

React Native module for the Octopus Community Android and Swift SDKs.

Official documentation: Octopus Developer Guide — for concepts, SSO setup, and native SDK details.

Features

Installation

npm install @octopus-community/react-native

iOS setup

Make sure to use_frameworks in your Podfile.

# Podfile
linkage = :static # or :dynamic
if linkage != nil
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
  use_frameworks! :linkage => linkage.to_sym
end

Due to a bug in Xcode 15, you might need to set ENABLE_USER_SCRIPT_SANDBOXING to YES and then to NO in order to compile (see this issue).

Compatibility table

| React Native version(s) | Android | iOS | Old arch | New arch | Octopus native SDK | | ----------------------- | ------------- | ----- | -------- | ------------- | --------------------------- | | v0.81.x (tested 0.81.4) | 7.0+ (API 24) | 15.1+ | ✅ | Interop layer | Android 1.13.4 · iOS 1.13.2 |

  • Older React Native versions (e.g. v0.78+) may work but are untested
  • New architecture is supported via the React Native interoperability layer
  • The minimum iOS version and the minimum Xcode version are the ones required by React Native itself, so they move with the React Native version you use
  • Other requirements:
    • Android: Kotlin 2.x
    • iOS: Xcode 16.1+

Versioning

This package's MAJOR.MINOR tracks the wrapped native Octopus SDKs, so the two numbers can be read together: package 1.13.x wraps native 1.13.x. The patch levels are independent — package 1.13.0 wrapping Android 1.13.3 and iOS 1.13.2 is normal, and the table above names the exact pins. That also means the two native pins agree on MAJOR.MINOR but not necessarily on PATCH: when one platform ships a fix the other does not need, only that platform's pin moves.

One consequence to plan for: because the minor tracks the natives, a breaking TypeScript change can arrive in a minor — each one gets a section with a before/after in MIGRATING.md, and the release it shipped in is listed in CHANGELOG.md.

Expo

Configure use_frameworks (static or dynamic) with expo-build-properties:

[
  "expo-build-properties",
  {
    "ios": {
      "useFrameworks": "static"
    }
  }
]

Usage

Initialization

Initialize the SDK with your API key with initialize.

Choose whether your app or Octopus handles user authentication:

Octopus-handled authentication

import { initialize } from '@octopus-community/react-native';

await initialize({
  apiKey: 'YOUR_OCTOPUS_API_KEY',
  connectionMode: { type: 'octopus' }
});

Single Sign-On (SSO)

For SSO mode:

  • your app manages user authentication and certain profile fields; you specify which profile fields your app will handle directly
  • you must provide a token provider that returns a valid JWT for the connected user. The JWT must be signed on your backend using the secret key provided by Octopus — never embed the secret in the app. See Generate a signed JWT for SSO
  • handle the connectUser rejection. The promise rejects when the platform refuses the connection — banned user, JWT the backend won't accept, no network. Ignoring it leaves the user anonymous while your app believes it connected them, which the user experiences as a login screen that "does nothing": they sign in, come back to the community, and are still asked for an account. See error handling below.
  • in React components, use the useUserTokenProvider hook to supply the token:
import {
  initialize,
  addEditUserListener,
  addLoginRequiredListener,
  connectUser,
  disconnectUser,
  isConnectUserError,
  useUserTokenProvider,
  closeUI,
} from '@octopus-community/react-native';

// Initialize with SSO mode and custom theme
await initialize({
  apiKey: 'YOUR_OCTOPUS_API_KEY',
  connectionMode: {
    type: 'sso',
    appManagedFields: ['username', 'profilePicture', 'biography']
  },
  theme: {
    colors: {
      primary: '#FF6B35', // Your brand's primary color
      primaryLowContrast: '#FF8C69', // Lighter variation
      primaryHighContrast: '#CC4A1A', // Darker variation
      onPrimary: '#FFFFFF', // Text color on primary background
    },
    logo: {
      image: Image.resolveAssetSource(require('./assets/images/logo.png')), // Your custom logo
    },
  }
});

// Listen for when authentication is required
const loginRequiredSubscription = addLoginRequiredListener(() => {
  // Navigate to your app's login screen
  console.log('User needs to log in');
  closeUI();
});

// Listen for when users want to edit their profile
const editUserSubscription = addEditUserListener(({ fieldToEdit }) => {
  // Navigate to your app's profile editing screen
  // for the specific field (username, profilePicture, etc.)
  console.log(`User wants to edit: ${fieldToEdit}`);
  closeUI();
});

// Set up token provider (in a React component)
useUserTokenProvider(async () => {
  const token = await refreshUserToken();
  return token;
});

// Connect a user after they log in.
// The token provider above must already be registered: the promise resolves only once the
// platform has authenticated the user, and rejects when it refuses.
try {
  await connectUser({
    userId: 'unique-user-id',
    profile: {
      username: 'john_doe',
      profilePicture: 'https://example.com/avatar.jpg',
      biography: 'Software developer',
    },
  });
} catch (error) {
  if (isConnectUserError(error) && error.code === 'USER_BANNED') {
    // `message` is the reason the platform itself returned — display it as-is.
    showBlockingMessage(error.message);
  } else {
    // The user is still anonymous. Say so, instead of returning them to the login screen.
    showRetryableError();
  }
}

// Disconnect the user when they log out
await disconnectUser();

// Cleanup listeners when appropriate (eg. in return of a useEffect)
loginRequiredSubscription.remove();
editUserSubscription.remove();

Handling a refused connection

connectUser rejects with an error whose code says why. The full list — and which platform reports each one — is in ConnectUserErrorCode; the ones worth an explicit branch:

| code | What happened | What to do | |---|---|---| | USER_BANNED | The user is banned from the community. | Show error.message — it is the reason the platform returned. Do not retry. | | MISSING_TOKEN | Your token provider returned nothing usable. An empty string counts as no token — throw instead of returning ''. | Fix the provider; re-authenticate the user in your app. | | INVALID_TOKEN | The JWT was rejected (bad signature or algorithm). | Check the backend signing key and algorithm against Generate a signed JWT for SSO. | | TOKEN_REQUEST_TIMEOUT | Nobody answered the token request within 60 s. | Register useUserTokenProvider / addUserTokenRequestListener before calling connectUser — a request emitted while nothing is listening is dropped — and make sure the provider always returns or throws. | | NO_NETWORK | No connection was available. | Retry later; tell the user the community is unavailable. | | SERVER_ERROR | The platform answered with an error it does not classify further — this covers transient outages and permanent problems such as a malformed request. | Read error.message before deciding: retry the transient ones, report the rest. |

Three limits worth knowing:

  • On iOS, a token request that fails does not always reject. When nothing is connected yet, the native SDK falls back to an anonymous connection and reports success, so a provider that times out or throws can leave you with a resolved promise and an unauthenticated user. Treat a resolved connectUser as "the SDK is usable" rather than "my user is authenticated", and make answering every token request the thing you rely on.
  • The rejection covers the connection attempt only. The platform calls your token provider again later (for instance when it refreshes the user's rights). A failure at that point has no promise left to reject, and this version has no event for it — the user simply stops being authenticated.
  • Codes are not symmetric across platforms, because the native SDKs classify failures differently. Branch on the codes you handle and keep a default branch; never assume a given platform emits a specific one.

Show the UI

You can show the Octopus Community in two ways:

  • Fullscreen — Call openUI() to open the native Octopus home screen (modal-style). Use closeUI() to dismiss it.
  • Embedded — Render the OctopusUIView component inside your React tree for an in-screen embed. Pass displayMode="embed" or displayMode="fullscreen" and optional theme/options. See the API reference and the example app for usage.

Theming

Match the SDK UI to your brand — colors (single set or light/dark pairs), font family and text styles, logo, and the top app bar — all through initialize():

import { Image } from 'react-native';

await initialize({
  apiKey: 'YOUR_OCTOPUS_API_KEY',
  connectionMode: { type: 'octopus' },
  theme: {
    colors: {
      primary: '#FF6B35',
      primaryLowContrast: '#FF8C69',
      primaryHighContrast: '#CC4A1A',
      onPrimary: '#FFFFFF',
    },
    logo: {
      image: Image.resolveAssetSource(require('./assets/images/logo.png')),
    },
  },
});

All theme properties are optional; anything you omit keeps the default Octopus appearance. A theme is read at initialization, so changing it means calling initialize() again.

See the theming guide for dual-mode colors, custom fonts (including fontFamily and how to register it with the host app), every text style, the top app bar options, and the platform-behaviour notes.

API docs

For details about the Typescript API, head to the API docs.

Example app

The example app demonstrates the full SDK surface. From the root, run yarn example start then yarn example ios or yarn example android. It opens on a Config screen (API key, auth mode — SSO or Octopus — user id, theme, then Start; Start stays disabled until a key resolves) and then shows four tabs:

| Tab | Purpose | |-----|---------| | Home | Read-only dashboard: SDK status, API key source, server, connection state, unseen count, community access | | Scenarios | Searchable index of capabilities; each opens a page with single-tap QA presets, its result panel, and that capability's controls (theming, batch group sync, custom events, push token) | | Settings | Connect/disconnect, display mode (fullscreen vs embed), URL interception, profile taps, locale override, Back to Config, Debug console | | Community | Open the Octopus UI (fullscreen or embedded) with the current theme and options |

See example/README.md for environment variables (API key, SSO user/token) and run instructions. The example is the best reference for implementing SSO, theming, reactive events, and URL interception in your app.

Troubleshooting

Any error that might be intercepted by the React Native module will be rejected in the methods you call. If it cannot be intercepted, you may see the underlying SDK's logs in your native logs.

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

Use of this SDK is governed by the Octopus Community Mobile SDK License Agreement.