Using Nitro in your app
While most libraries are built with Nitro and shipped over npm, you can also easily build a library with Nitro in your app - that's the "brownfield" way of doing things.
Installing Nitro
First, you need to install the Nitro Modules core package from npm:
- npm
 - yarn
 - pnpm
 - bun
 
npm i react-native-nitro-modules
cd ios && pod install
yarn add react-native-nitro-modules
cd ios && pod install
pnpm add react-native-nitro-modules
cd ios && pod install
bun i react-native-nitro-modules
cd ios && pod install
Creating a Hybrid Object
After installing Nitro, you can start creating your Hybrid Objects - either with Nitrogen, or manually:
- With Nitrogen ✨
 - Manually
 
Nitrogen will ✨ automagically ✨ generate native specifications for each Hybrid Object based on a given TypeScript definition.
1. Installing Nitrogen
First, install Nitrogen:
- npm
 - yarn
 - pnpm
 - bun
 
npm i nitro-codegen --save-dev
yarn add nitro-codegen -D
pnpm add nitro-codegen -D
bun i nitro-codegen -d
Nitrogen is currently named nitro-codegen instead of nitrogen on npm.
Then, create your nitro.json configuration in your app's root directory:
{
  "$schema": "https://nitro.margelo.com/nitro.schema.json",
  "cxxNamespace": ["example"],
  "ios": {
    "iosModuleName": "NitroExample"
  },
  "android": {
    "androidNamespace": ["example"],
    "androidCxxLibName": "NitroExample"
  },
  "autolinking": {}
}
Note: Replace Example with your app's name.
2. Creating Nitro specs
Now it's time to create your first spec. Let's create Math.nitro.ts:
interface Math extends HybridObject<{ ios: 'swift', android: 'kotlin' }> {
  readonly pi: number
  add(a: number, b: number): number
}
And now let's run Nitrogen:
npx nitro-codegen
Nitrogen is currently named nitro-codegen instead of nitrogen on npm.
This will generate the native Swift and Kotlin protocol "HybridMathSpec", as well as some helper classes for autolinking and bridging to C++.
3. Adding the generated sources to your project
You now need to add the generated sources to your project - either by creating a sub-package that you will use in your app (e.g. in a monorepo), or by just manually adding the source files:
- Manually
 - Via a subpackage
 
iOS
On iOS, you just need to drag and drop the nitrogen/generated/ios and nitrogen/generated/shared folders into your Xcode project. That's it.
Android
For Android, you need to add everything in nitrogen/generated/android and nitrogen/generated/shared to your build.gradle (Java/Kotlin source) and CMake (C++ sources) project.
Java/Kotlin sources (build.gradle)
Add the Java/Kotlin sources to your Gradle project by including the generated autolinking gradle file. Simply add this to the top of your app/build.gradle:
apply from: '../nitrogen/generated/android/NitroExample+autolinking.gradle'
C++ sources (CMakeLists.txt)
Add the C++ sources to your CMake project by including the generated autolinking CMake file. If you do not have a CMake setup yet, make sure to configure CMake through externalNativeBuild in build.gradle. Simply add this to your CMakeLists.txt:
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroImage+autolinking.cmake)
iOS
On iOS, you need to create a local Podspec ($$iosModuleName$$.podspec). In this local pod you need to include the autolinking code that has been generated by Nitrogen:
load 'nitrogen/generated/ios/NitroExample+autolinking.rb'
add_nitrogen_files(s)
And then just add this local Pod to your Podfile:
pod '$$iosModuleName$$', :path => '../'
Android
On Android, you need to create a local Android library (build.gradle). This library also needs to set up a CMake build (via externalNativeBuild). See the template for an example.
Inside the local Android library's build.gradle, add the autogenerated Java/Kotlin sources:
apply from: '../nitrogen/generated/android/NitroExample+autolinking.gradle'
Inside the local Android library's CMakeLists.txt, add the autogenerated C++ sources:
include(${CMAKE_SOURCE_DIR}/../nitrogen/generated/android/NitroImage+autolinking.cmake)
And lastly, add this local Android library to your app's build.gradle using dependencies:
// ...
dependencies {
  // ...
  implementation project(':your-local-library')
}
You might also need to include the local library in your app's settings.gradle:
include ':your-local-library'
4. Implement Hybrid Object Specs
After adding the generated sources to your project, you can start implementing the spec in a class:
- Swift
 - Kotlin
 
class HybridMath : HybridMathSpec {
  public var pi: Double {
    return Double.pi
  }
  public func add(a: Double, b: Double) throws -> Double {
    return a + b
  }
}
class HybridMath : HybridMathSpec() {
  override var pi: Double
    get() = Double.PI
  override fun add(a: Double, b: Double): Double {
    return a + b
  }
}
5. Registering the Hybrid Objects
Nitro needs to be able to initialize an instance of your Hybrid Object - so we need to tell it how to do that.
In your nitro.json, register HybridMath in the "autolinking" section:
- Swift/Kotlin
 - C++
 
{
  ...
  "autolinking": {
    "Math": {
      "swift": "HybridMath",
      "kotlin": "HybridMath"
    }
  }
}
- Make sure 
HybridMathis default-constructible. That is, it has a public initializer that takes no arguments. - Make sure the Java/Kotlin class 
HybridMathis inside the package/namespacecom.margelo.nitro.$$androidNamespace$$(as configured innitro.json). - Make sure the Java/Kotlin class 
HybridMathis annotated with@DoNotStripto avoid it from being compiled out in production builds. 
{
  ...
  "autolinking": {
    "Math": {
      "cpp": "HybridMath"
    }
  }
}
- Make sure 
HybridMathis default-constructible. That is, it has a public constructor that takes no arguments. - Make sure the 
HybridMathclass is defined in a header namedHybridMath.hpp- this is what Nitro will import. - Also make sure 
HybridMathis either in the global namespace, or inmargelo::nitro::<cxxNamespace>(configured innitro.json). 
For more information, see the Nitrogen documentation.
Manually creating Hybrid Objects is quite easy, but since Nitro is a C++ library, you need to use C++. You can bridge the implementations of those methods to Swift/Objective-C/Java/Kotlin/Rust yourself, but Nitrogen usually does all of that ✨ automagically ✨.
Simply create your C++ classes and inherit from HybridObject:
class HybridMath: public HybridObject {
public:
  HybridMath(): HybridObject(NAME) { }
public:
  double add(double a, double b);
protected:
  void loadHybridMethods() override;
private:
  static constexpr auto NAME = "Math";
};
double HybridMath::add(double a, double b) {
  return a + b;
}
void HybridMath::loadHybridMethods() {
  // register base methods (toString, ...)
  HybridObject::loadHybridMethods();
  // register custom methods (add)
  registerHybrids(this, [](Prototype& proto) {
    proto.registerHybridMethod(
      "add",
      &HybridMath::add
    );
  });
}
Then, register the Hybrid Object constructor somewhere on app startup - e.g. in AppDelegate's application:didFinishLaunchingWithOptions:, or in your cpp-adapter's JNI on load:
HybridObjectRegistry::registerHybridObjectConstructor(
  "Math",
  []() -> std::shared_ptr<HybridObject> {
    return std::make_shared<HybridMath>();
  }
);
Using your Hybrid Objects
And finally, to initialize HybridMath from JS you just need to call createHybridObject:
export const MathModule = NitroModules.createHybridObject<Math>("Math")
const result = MathModule.add(5, 7)
If this call failed, you might have forgotten to register your Hybrid Object's constructor in the HybridObjectRegistry.