Lucent, Expo Modules, Nitro and Turbo Native Modules
What each one has you write, how it reaches native code, what it can do today, and when to pick it.
Expo Modules, Nitro Modules, Turbo Native Modules and Lucent all let JavaScript call native code synchronously over JSI. They differ in the languages you write, how the interface is declared, and how much of the platform you reach today.
| Lucent | Expo Modules | Nitro Modules | Turbo Native Modules |
|---|---|---|---|
| You write | |||
A TypeScript subsetmodules in *.lucent.ts and components in *.lucent.tsx, compiled to C++20 | Swift + Kotlin | C++, or Swift + KotlinSwift and Kotlin each cover one platform | Obj-C++ + Java/Kotlin, or C++Swift needs Objective-C++ glue |
| Interface defined by | |||
| The implementationits exported functions, types and classes | A Swift/Kotlin DSLthe module definition | A TypeScript spec*.nitro.ts; Nitrogen (optional) generates the native interfaces | A TS or Flow specCodegen generates the native interfaces |
| Codebases per module | |||
| 1 | 2 | 1 or 21 in C++; plus the spec | 2, or 1 in C++C++ still needs a small platform registration layer; plus the spec |
| Call path | |||
| JSI → C++one pure C++ TurboModule | JSIthrough Expo's module layer | JSI → C++Hybrid Objects on jsi::NativeState; Swift and Kotlin through generated bridges | JSIC++ modules directly, others through the platform interop layer |
| Platform SDKs | |||
Mosttyped from your Xcode and Android SDK, Swift-only and Kotlin-only APIs included through generated Swift and Kotlin; lucent sdk coverage lists what can't be bound yet. See SDK types | Full | Full | Full |
| Views | |||
| ExperimentalUIKit and Android views, and SwiftUI and Jetpack Compose written as JSX, behind an internal switch. See the announcement | YesView in the module definition | YesNitro Views; React Native 0.78+, New Architecture | YesFabric Native Components, a separate API |
| Bare React Native / Expo | |||
| BothReact Native 0.88, Expo SDK 58 | Bothbare apps install the expo package | BothReact Native 0.75+ | Both |
| Maturity | |||
| Experimentalsee the roadmap | Productionthe Expo SDK is built on it | Productionused by widely adopted published libraries | Productionpart of React Native core |
Native code of any of these kinds needs a development build: it doesn't run in Expo Go. How a module becomes native code shows what Lucent generates.
Performance
Section titled “Performance”Lucent calls go through JSI into C++, like Nitro Modules and C++ Turbo Native Modules. We publish no speed comparison between these tools. lucent bench measures your own module against the same code run as JavaScript.
When to pick each
Section titled “When to pick each”- Expo Modules: your team already writes Swift and Kotlin, or you need views and full platform SDK access today.
- Nitro Modules: you want the most performance, write C++, Swift or Kotlin, and like declaring the interface in TypeScript first.
- Turbo Native Modules: you are writing a library that should depend only on React Native core.
- Lucent: you want native code without adding Swift, Kotlin or C++ to the codebase. You can do without views and an npm release for now.
Sources
Section titled “Sources”The other tools were last checked on 2026-09-23, and Lucent's rows updated on 2026-10-01. Corrections are welcome.