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/: Benchmark objects and View fixtures.
  • packages/template/: The RN library template.

Run Nitro Example​

1. Set up your development environment​

You need:

  • Bun
  • Xcode with Swift 6.4 or higher for iOS builds
  • Android Studio

2. Clone the repo​

Clone margelo/nitro and navigate into the nitro folder. Target v1 for Nitro V1 contributions.

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​

For iOS, set up React Native's SwiftPM dependencies from the repository root:

bun example spm

The example and benchmark apps use React Native 0.88 and SwiftPM. The remaining Podfiles and podspecs provide discovery metadata for React Native CLI; CocoaPods is not needed to build these apps.

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.xcodeproj 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 regenerates the Nitrogen bindings for every test fixture with the local Nitrogen build.

Reproduce an issue​

Add a reproduction to the repository with your issue report. Portable runtime regressions belong in tests/standalone/; React Native integration and View regressions belong in tests/react-native/apps/example/. To submit a reproduction:

  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 standalone or 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, reproduce changes to your Xcode project or SwiftPM dependencies in tests/react-native/apps/example/ and check whether it still builds. 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​

Add HybridObject specs to tests/standalone/nitro-test/specs/TestObject.nitro.ts. Use the separate nitro-test-external package for cross-library types. View specs belong in tests/react-native/packages/react-native-nitro-test/src/specs/. After changing a spec, 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​

Add portable runtime assertions to tests/standalone/test-runner/js/. Run bun test:ios or bun test:android from the repository root. These suites run through Swift Testing and JUnit, including sanitizer configurations in CI.

For React Native integration or View regressions, add an assertion to the Harness files in tests/react-native/apps/example/__tests__/. Run bun test:react-native:ios or bun test:react-native:android. Harness keeps nine View tests and three integration checks; portable cases run standalone.

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.

To run the Nitro docs, follow these steps:

1. Install dependencies​

Clone Nitro and install dependencies from its repository root:

git clone 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.