Skip to content

Choosing a Module

s edited this page Aug 1, 2026 · 4 revisions

Choosing a Module

The CLI labels are Native Module, Native JNI Module, and JSI Module. In practical terms, they are a Kotlin/Java module, a Kotlin/Java bridge to C/C++, and an experimental synchronous C++ module.

Decision table

Question Choose Reason
Do you need Android services, permissions, content resolvers, or other Android APIs? Native Kotlin/Java is the supported user-owned Android layer.
Do you already have C or C++ code? JNI, unless a synchronous result is essential JNI provides a Promise-based API and generated conversion/registration.
Can the operation wait on files, networking, locks, devices, or unpredictable work? Native or JNI Do not synchronously block the JavaScript thread.
Must JavaScript receive the result before it can continue? Consider JSI JSI returns directly, but only for short operations and a qualified host.
Has JSI executed under the exact target PluginHost, linker namespace, and enforcing SELinux policy? JSI may be viable Generation and compilation alone do not establish device support.

Native: Kotlin or Java

Choose Native for Android APIs, Kotlin/Java libraries, or a conventional React Native native-module API. Returned values become JavaScript Promises. A Unit/void export is fire-and-forget.

A Promise does not make blocking implementation code inherently safe. Manage long work appropriately inside your Kotlin/Java implementation.

Typical uses:

  • Android storage, permissions, content resolvers, and services;
  • existing Kotlin/Java libraries;
  • ordinary plugin features that do not require C/C++.

Continue with Kotlin and Java Modules.

JNI: C or C++ behind Kotlin/Java

Choose JNI when implementation belongs in C/C++ and JavaScript can await the result. You write ordinary top-level C++ exports. The generator owns Kotlin, JNI conversion/registration, native loading, CMake, and TypeScript declarations.

Typical uses:

  • an existing C/C++ library;
  • parsing, compression, image processing, or batched computation;
  • file work with a Promise-based JavaScript API.

This backend does not provide a user-owned Kotlin glue layer for arbitrary Android APIs. If a feature needs extensive Android API work and C++, use a Kotlin/Java module or design an explicit supported boundary.

Continue with JNI Modules.

JSI: synchronous C++

Choose JSI only when all of these are true:

  1. JavaScript genuinely needs a synchronous return value.
  2. The operation is short, deterministic, and safe on the JavaScript thread.
  3. The target PluginHost provides a compatible React Native/JSI runtime.
  4. Its linker namespace and SELinux policy permit execution of the extracted plugin library.

Do not use JSI for files, networks, waits, locks, large parsing work, compression, or long computation. A blocked JavaScript thread freezes plugin logic and UI work.

The current official Supernote architecture describes Java/TurboModule access followed by Java-to-C/C++, and does not promise direct JS/TS-to-C/C++ calls. The generator can create a JSI package, but that is experimental generator support, not proof of host support. See JSI Modules and Compatibility.

Quick decision

Need Android APIs or prefer Kotlin/Java?
  -> Native

Need C/C++ and an asynchronous call is acceptable, or the work may block?
  -> JNI

Need a short synchronous C++ call, and exact target-host execution is proven?
  -> JSI (experimental)

The generator cannot convert a module between types. If uncertain, start with Native or JNI.

Clone this wiki locally