-
Notifications
You must be signed in to change notification settings - Fork 0
Getting Started
This page walks through adding the first native module to a Supernote plugin.
It assumes that the existing plugin already builds and runs. Creating, packaging, installing, and debugging the plugin itself remain part of the official Supernote plugin workflow.
The generator creates a local package and connects it to the parent plugin. Depending on the module type and package manager, it may change:
local_modules/<package-name>/
package.json
package-lock.json or yarn.lock
android/settings.gradle or android/settings.gradle.kts
There is no Add dry run.
Before generating a module, use one of these approaches:
- Commit the current plugin state.
- Stash unrelated work.
- Save a patch or backup of the affected files.
You do not need to commit unrelated work solely to use the generator, but you should have a way to distinguish your existing changes from the generator's changes.
Python 3.9 or newer is required.
On Linux or macOS:
python3 -m pip install --upgrade supernote-module-generatorOn Windows, one common form is:
py -m pip install --upgrade supernote-module-generatorIf your system uses a different Python command, replace python3 or py with that command.
Confirm that the executable is available:
supernote-module --versionIf the command is not found, see Troubleshooting.
The Wiki follows the current default branch and may describe changes newer than the installed release. For the exact behavior of your installed version, use:
supernote-module --help
supernote-module help addRun the generator from the root of the existing plugin, not from android/, src/, or another subdirectory.
The current directory must contain:
PluginConfig.json
package.json
android/
android/settings.gradle
android/settings.gradle.kts is also supported.
The generator does not search parent directories. A quick check on Linux, macOS, Git Bash, or WSL is:
pwd
ls PluginConfig.json package.json androidIn PowerShell:
Get-Location
Get-Item PluginConfig.json, package.json, androidUse this practical rule:
- Choose Native Module for Kotlin, Java, Android APIs, or Kotlin and Java libraries.
- Choose Native JNI Module for C or C++ behind a normal Promise-based JavaScript API.
- Choose JSI Module only for a short synchronous C++ API that has been tested in the target PluginHost.
When unsure between JNI and JSI, choose JNI.
See Home for the fuller comparison.
Doctor checks the current plugin and the development tools required by a module type. It does not change the plugin.
supernote-module doctor --type native
supernote-module doctor --type jni
supernote-module doctor --type jsiRunning without --type checks every module type:
supernote-module doctorThat is useful for setting up a complete machine, but it can report missing C or C++ tools even when you only plan to create a Native Module.
Doctor checks:
- The Supernote plugin root.
- Node.js and the detected npm or Yarn command.
- Java 17 or newer.
- An Android SDK identified by
ANDROID_HOMEorANDROID_SDK_ROOTwith platform 35. - The plugin's Gradle wrapper.
- For JNI and JSI, CMake 3.22.1 or newer and a suitable Android NDK.
- For JSI, an advisory runtime-policy boundary that cannot be proven locally.
If Android Studio can build the plugin but Doctor cannot find the SDK, the current terminal may not have the SDK environment variable.
Examples using the usual SDK locations are shown below. Replace the path when your SDK is elsewhere.
Linux:
export ANDROID_HOME="$HOME/Android/Sdk"macOS:
export ANDROID_HOME="$HOME/Library/Android/sdk"PowerShell:
$env:ANDROID_HOME = "$env:LOCALAPPDATA\Android\Sdk"Set the variable in your shell startup configuration when it should persist between terminals. See Troubleshooting before installing a second SDK.
For the normal human workflow, run:
supernote-moduleThe main menu contains:
Add module
Update module
Validate module
Remove module
Doctor
Help
Exit
In a capable terminal:
- Use the up and down arrow keys to move.
- Press Enter to select.
- Press Esc to return to the previous question or leave the menu.
- Press Ctrl+C to interrupt the operation.
In --plain mode, choose numbered options and use :back or :cancel.
Choose Add module, then choose the module type.
The generator asks for:
| Question | Example | Meaning |
|---|---|---|
| Package name | local-math |
Folder below local_modules/, dependency name, and import string |
| Description | Leave empty | Optional package description |
| JavaScript name | Math |
Object imported and called from JavaScript or TypeScript |
| Android namespace | com.example.math |
Kotlin or Java namespace and generated Android paths |
| Package version | 0.1.0 |
Version stored in the local package |
| Install now | Yes | Runs npm or Yarn after adding the local dependency |
Use a lowercase npm package name such as local-math or @my-plugin/local-math. Do not use spaces or uppercase letters.
The JavaScript name must begin with a letter and contain only letters and numbers. The Android namespace uses dot-separated Java identifiers.
The package name, JavaScript name, and Android namespace must be unique in the plugin. Update cannot rename them later.
Add creates the generated package, adds the local file: dependency to the parent package.json, and adds the integration required by the selected module type.
The implementation directory is:
| Module type | User-owned implementation |
|---|---|
| Native Module | local_modules/<package>/android/src/main/java/<namespace-path>/ |
| Native JNI Module | local_modules/<package>/android/src/main/cpp/ |
| JSI Module | local_modules/<package>/android/src/main/cpp/ |
Other generated package, bridge, registration, Gradle, CMake, loader, and declaration files may be replaced by Update.
If you choose not to install immediately, Add still creates the module and edits the parent package.json. --skip-install skips the npm or Yarn command and lockfile refresh; it does not make Add read-only.
After Add completes, inspect what changed:
git status --short
git diffYou should see the new module below local_modules/ and the expected parent integration changes.
The success output includes the module path and the next action. Open the generated package's README.md and the implementation directory listed above.
Continue with the page for the selected module:
Each page explains the supported function signatures and which files are safe to edit.
After changing an exported function, run:
supernote-module validate local-math --buildWithout --build, validation checks the generated structure, parent integration, dependency link, and exports. With --build, it also runs the applicable Android build through the existing plugin project.
For complete Gradle, compiler, or linker output:
supernote-module validate local-math --build --verboseA successful JSI build still does not prove that PluginHost can load and execute the library.
Every generated package has one default export.
For Native and JNI modules:
import Math from 'local-math';
const total = await Math.add(20, 22);For JSI modules:
import Math from 'local-math';
const total = Math.add(20, 22);Do not use await with JSI.
After this point, build, package, install, and debug the plugin using the normal Supernote plugin workflow.
The menu is not required. A direct command can still prompt for missing values when run in a terminal:
supernote-module add local-mathA command with documented defaults can be shorter:
supernote-module add local-math --type native --yesDirect commands are useful for ordinary terminal use as well as scripts. See Using the CLI for every command, option, confirmation rule, output mode, and exit code.