This is for simple single-public-method modules. If you need more than that, use the "CLI Generated" method below.
- Make a new TypeScript file in this format:
/* @turbomodule ModuleName.myMethod(): string
#import <Whatever/Whatever.h>
// add any imports you need here
// aside from <Foundation/Foundation.h> and <AppSpec/AppSpec.h>
// which are automatically imported for you
- (NSString *)myMethod {
return @"Something here";
}
*/
import ModuleName from "./NativeModuleName"
export function myMethod(): string {
return ModuleName.myMethod()
}- Add the file to
package.jsonin thegenerateTurboModules.filesarray.
{
...
"generateTurboModules": {
"files": [
"app/utils/myMethod.ts"
],
"destinationPath": "macos/build/generated/colocated"
}
}- Run
npm run podto generate the Objective-C++ files and run codegen and link everything up in Xcode. The generated files can be debugged in Xcode -- find them in theColocatedgroup.
(Note: if you need to, run COLO_LOCO_CLEAN=1 npm run pod to clean the generated files and start fresh. Then run npm run pod again.)
- Use the new method anywhere in your app like this:
import { myMethod } from "./utils/myMethod"
const result = myMethod()
console.log({ result })Done!
- Run
./bin/turbomodule add IRMyThing - It'll generate files in
./app/native/IRMyThing/*... you can move them anywhere in./app/or leave them there. - Run
npm run podto generate the Objective-C++ header files and run codegen and link everything up in Xcode. - Use the new method anywhere in your app like this:
import IRMyThing from "./native/IRMyThing/NativeIRMyThing"
const result = IRMyThing.myMethod()
console.log({ result })(You can also run ./bin/turbomodule remove IRMyThing to remove the module if you haven't moved it from the ./app/native/IRMyThing/* folder.)
- Create a new
NativeIRMyThing.tsfile anywhere in your./app/folder structure. Make it look likeNativeIRKeyboard.tsbut with your own methods. - Create a new Objective-C++ implementation file anywhere in your
./app/folder structure. You can just copy theIRKeyboard.mmfile and rename it to something likeIRMyThing.mm. - Customize with your own logic.
- Run
npm run podto generate the Objective-C++ header files and run codegen and link everything up in Xcode. - Use the new method anywhere in your app like this:
import IRMyThing from "./native/IRMyThing/NativeIRMyThing"
const result = IRMyThing.myMethod()
console.log({ result })(Untested, from memory)
- Create a new Objective-C header/implementation file in the
./app/native/folder. You can just copy theIRFontList.mm/hfiles and rename them to something likeIRMyThing.mm/h. - Make them look like
IRFontList.mm/hbut with your own logic. - Link both files in Xcode:
- In Xcode, select
Reactotronin the project navigator (left sidebar, first icon). - Right-click on it
- Select
Add Files to "Reactotron" - Select the
IRMyThing.mmfile and clickAdd - Choose
Reference files in placeand make sure the target is selected - Click
Finish - Repeat for the
IRMyThing.hfile
- In Xcode, select
- Make a TypeScript file in the
./specs/folder. You can just copy theNativeIRFontList.tsfile and rename it toNativeIRMyThing.ts. - Edit it to look like your own module.
- Run codegen with:
npx react-native codegen. It'll create abuild/generated/iosfolder (yes,ios). - Now access your new module in your app with:
import NativeIRMyThing from "specs/NativeIRMyThing" - And use it (async) like this:
NativeIRMyThing.getMyThing().then((myResponse) => { console.log(myResponse) }) - Done!
Windows supports the Manual approach (equivalent to macOS) with the same unified workflow, but currently requires explicit file creation.
- ✅ Manual TurboModule creation with automatic detection
- ✅ Fabric Component support
- ✅ Unified linking command (
npm run windows-link) - ✅ Same developer workflow as macOS Manual approach
- ❌ Embedded TurboModules (Objective-C in TypeScript comments)
- ❌ CLI Generated (
./bin/turbomodule addequivalent) - ❌ Header auto-generation (Windows requires explicit
.hfiles)
This approach mirrors the macOS Manual method but with Windows-specific files.
-
Create your TypeScript spec anywhere in your
./app/folder structure. Copy an existingNativeIRSomething.tsfile and customize it. -
Create Windows implementation files:
app/native/IRMyThing/ ├── NativeIRMyThing.ts # TypeScript spec (shared between platforms) ├── IRMyThing.mm # macOS implementation ├── IRMyThing.windows.h # Windows header (explicit) └── IRMyThing.windows.cpp # Windows implementation -
Write your Windows header (
IRMyThing.windows.h):#pragma once #include "NativeModules.h" namespace winrt::reactotron::implementation { REACT_MODULE(IRMyThing) struct IRMyThing { IRMyThing() noexcept = default; REACT_SYNC_METHOD(myMethod) std::string myMethod() noexcept; }; }
-
Write your Windows implementation (
IRMyThing.windows.cpp):#include "pch.h" #include "IRMyThing.h" namespace winrt::reactotron::implementation { std::string IRMyThing::myMethod() noexcept { return "Hello from Windows!"; } }
-
Run the Windows linking command:
npm run windows-link
This automatically:
- Detects your
.windows.{h,cpp}files - Generates consolidated headers for the build system
- Runs Windows codegen
- Links everything automatically
- Detects your
-
Use in your app (same as macOS):
import IRMyThing from "./native/IRMyThing/NativeIRMyThing" const result = IRMyThing.myMethod() console.log({ result }) // "Hello from Windows!"
The Windows system automatically detects and handles both:
- 🔧 TurboModules: Use
REACT_MODULEattributes → auto-registered - 🎨 Fabric Components: Use
ComponentViewinheritance → auto-registered
# macOS
npm run pod # Link native modules
npm run pod-clean # Clean & regenerate
# Windows
npm run windows-link # Link native modules
npm run windows-link-clean # Clean & regenerateThe TypeScript spec files are shared between platforms - only the native implementations differ!