Skip to main content

Contributing

If you encounter issues with Nitro, want to fix a bug, or reproduce a bug in the example app, you'd need to clone the repo and get it running first.

Contribution flow and PR rules

This page covers environment setup and reproduction - how to run Nitro locally. For the contribution flow itself (what PRs we accept, the required test-per-fix rule, the nitrogen workflow, and the PR checklist), see CONTRIBUTING.md in the repo root. Read it before opening a PR.

The Nitro repository is a Bun monorepo:

  • packages/nitro-core/: Shared native runtime and JS/TS API.
  • packages/nitrogen/: The CLI that generates native bindings.
  • packages/react-native-nitro-modules/: RN entry point and native build integration.
  • tests/standalone/: Core runtime tests without React Native.
  • tests/react-native/apps/: Example and benchmark apps.
  • tests/react-native/packages/: Two fixture libraries for runtime and cross-library tests.
  • packages/template/: The RN library template.

Run Nitro Example​

1. Set up your development environment​

You need:

  • Bun
  • CocoaPods (installed via Bundler - see below)
  • Ruby 2.7.2 (matches CI)
  • Xcode 26.2 or higher
  • Android Studio

2. Clone the repo​

Clone margelo/nitro and navigate into the nitro folder. Target core-split until the reorganization lands on main.

3. Install dependencies​

Prepare core dependencies, install packages, and build the workspace:

bun bootstrap

All packages resolve from the local workspace. The only submodule is the Hermes engine used by standalone native tests.

3.1. (Optional) Install iOS dependencies​

If you want to work on the iOS codebase, you also need to install the Pods:

cd tests/react-native/apps/example
bundle install
bun pods

4. Run the app​

After installing all dependencies, you can run the React Native app in tests/react-native/apps/example/:

  1. Open tests/react-native/apps/example/ios/NitroExample.xcworkspace in Xcode
  2. Select your target (iPhone Simulator)
  3. Click Run

Edit shared implementations in packages/nitro-core. bun sync-core stages those sources into the RN package, and bun specs:all regenerates every test fixture with the local Nitrogen build.

Reproduce something in the Nitro Example app​

With most issue reports, it is required to reproduce the issue in the Nitro example app (tests/react-native/apps/example/). Whether it's a build error, a nitrogen error, or a runtime error, there needs to be a way to reproduce it here. Usually, you can reproduce issues like this:

  1. Fork the repository
  2. Change the code to reproduce the issue
  3. Create a PR to the nitro repository which demonstrates the issue
You don't need to ship a fix

A PR that only reproduces the bug - and makes CI go red - is a completely valid and very welcome contribution. If you can add a minimal failing test (compile error or runtime error caught by the Harness tests) and open a PR with just that, stop there. You don't have to attempt a fix. A clean, 100% deterministic repro pinned in CI is often more valuable than a guessed patch; the actual fix can be taken from there.

See You don't need to ship a fix in CONTRIBUTING.md for details and the test-writing rules (reuse existing types, keep it small, don't remove existing tests).

Reproduce a build error​

If you encounter a build error, compare your setup to the setup in tests/react-native/apps/example/. For example, if you have a different setting in your Podfile, try changing it here in Nitro tests/react-native/apps/example/ as well to see if it builds here. Submit a PR with the change required to make it fail, and see if the CI fails to build. That alone is enough - you don't need to also fix it.

Reproduce a nitrogen bug​

The Nitro tests/react-native/apps/example/ app uses a Nitro Module (tests/react-native/packages/react-native-nitro-test/) which acts as an example and contains a lot of test code, like src/specs/TestObject.nitro.ts (link). If you change something in TestObject.nitro.ts, make sure to run nitrogen from the repo root:

bun specs

Commit the generated files. If that change causes a compile error downstream (e.g. Swift refuses to build the generated code), that's a valid repro on its own - open the PR with the red CI and leave the fix to a maintainer if you don't have one.

When adding a reproduction, follow the rules in CONTRIBUTING.md: reuse existing types where possible, don't remove existing test cases, and keep the addition small. Dumping a full user spec into the test module is not the right approach - distill the bug to the minimal type or call that reproduces it.

Reproduce a runtime error​

Submit a PR with a failing assertion in one of the Harness test files in tests/react-native/apps/example/__tests__/. The iOS and Android Harness workflows run these tests in CI. A PR that reproduces the failure is enough; you don't have to include a fix.

Performance tests​

Performance CI is opt-in. A maintainer with write, maintain, or admin repository access can post @nitro-modules-bot please test performance on an open PR. The bot acknowledges it with 👍, updates the PR's Nitro Performance status, and posts the results or a failure link. Contributors without write access can ask a maintainer to run it, including for PRs from forks.

See Performance tests in CONTRIBUTING.md for repeat runs and measurement-only retries.

Run Nitro Docs​

The Nitro docs (nitro.margelo.com) live in the docs/ folder of margelo/nitro and are built with Docusaurus. Until the reorganization lands on main, target core-split.

To run the Nitro docs, follow these steps:

1. Install dependencies​

Clone Nitro's core-split branch and install dependencies from its repository root:

git clone --branch core-split https://github.com/margelo/nitro.git
cd nitro
bun install --frozen-lockfile --ignore-scripts

2. Run docs (dev)​

Run the docs development server from the Nitro repository root:

bun docs start

Before submitting docs changes, run bun docs typecheck and bun docs build from the same directory.

Linting​

We value code quality and consistent styling.

For JS/TS, we use ESLint and Prettier:

bun lint

For C++, we use clang-format:

bun lint-cpp

For Swift, we use swift format:

bun lint-swift

For Kotlin, we use ktlint:

bun lint-kotlin

Make sure to lint your files everytime before creating a PR. This is also enforced in the CI, but linting beforehand also applies auto-fixes.