Ordinary-claude-skills native-modules
Expert in React Native native modules, bridging JavaScript and native code, writing custom native modules, using Turbo Modules, Fabric, JSI, autolinking, module configuration, iOS Swift/Objective-C modules, Android Kotlin/Java modules. Activates for native module, native code, bridge, turbo module, JSI, fabric, autolinking, custom native module, ios module, android module, swift, kotlin, objective-c, java native code.
git clone https://github.com/Microck/ordinary-claude-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/Microck/ordinary-claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills_categorized/defi/native-modules" ~/.claude/skills/microck-ordinary-claude-skills-native-modules-10056d && rm -rf "$T"
skills_categorized/defi/native-modules/SKILL.mdNative Modules Expert
Specialized in React Native native module integration, including custom native module development, third-party native library integration, and troubleshooting native code issues.
What I Know
Native Module Fundamentals
What Are Native Modules?
- Bridge between JavaScript and native platform code
- Access platform-specific APIs (Bluetooth, NFC, etc.)
- Performance-critical operations
- Integration with existing native SDKs
Modern Architecture
- Old Architecture: Bridge-based (React Native < 0.68)
- New Architecture (React Native 0.68+):
- JSI (JavaScript Interface): Direct JS ↔ Native communication
- Turbo Modules: Lazy-loaded native modules
- Fabric: New rendering engine
Using Third-Party Native Modules
Installation with Autolinking
# Install module npm install react-native-camera # iOS: Install pods (autolinking handles most configuration) cd ios && pod install && cd .. # Rebuild the app npm run ios npm run android
Manual Linking (Legacy)
# React Native < 0.60 (rarely needed now) react-native link react-native-camera
Expo Integration
# For Expo managed workflow, use config plugins npx expo install react-native-camera # Add plugin to app.json { "expo": { "plugins": [ [ "react-native-camera", { "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera" } ] ] } } # Rebuild dev client eas build --profile development --platform all
Creating Custom Native Modules
iOS Native Module (Swift)
// RCTCalendarModule.swift import Foundation @objc(CalendarModule) class CalendarModule: NSObject { @objc static func requiresMainQueueSetup() -> Bool { return false } @objc func createEvent(_ name: String, location: String, date: NSNumber) { // Native implementation print("Creating event: \(name) at \(location)") } @objc func getEvents(_ callback: @escaping RCTResponseSenderBlock) { let events = ["Event 1", "Event 2", "Event 3"] callback([NSNull(), events]) } @objc func findEvents(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: @escaping RCTPromiseRejectBlock) { // Async with Promise DispatchQueue.global().async { let events = self.fetchEventsFromNativeAPI() resolve(events) } } }
// RCTCalendarModule.m (Bridge file) #import <React/RCTBridgeModule.h> @interface RCT_EXTERN_MODULE(CalendarModule, NSObject) RCT_EXTERN_METHOD(createEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)date) RCT_EXTERN_METHOD(getEvents:(RCTResponseSenderBlock)callback) RCT_EXTERN_METHOD(findEvents:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @end
Android Native Module (Kotlin)
// CalendarModule.kt package com.myapp import com.facebook.react.bridge.* class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { override fun getName(): String { return "CalendarModule" } @ReactMethod fun createEvent(name: String, location: String, date: Double) { // Native implementation println("Creating event: $name at $location") } @ReactMethod fun getEvents(callback: Callback) { val events = WritableNativeArray().apply { pushString("Event 1") pushString("Event 2") pushString("Event 3") } callback.invoke(null, events) } @ReactMethod fun findEvents(promise: Promise) { try { val events = fetchEventsFromNativeAPI() promise.resolve(events) } catch (e: Exception) { promise.reject("ERROR", e.message, e) } } }
// CalendarPackage.kt package com.myapp import com.facebook.react.ReactPackage import com.facebook.react.bridge.NativeModule import com.facebook.react.bridge.ReactApplicationContext import com.facebook.react.uimanager.ViewManager class CalendarPackage : ReactPackage { override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> { return listOf(CalendarModule(reactContext)) } override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> { return emptyList() } }
JavaScript Usage
// CalendarModule.js import { NativeModules } from 'react-native'; const { CalendarModule } = NativeModules; export default { createEvent: (name, location, date) => { CalendarModule.createEvent(name, location, date); }, getEvents: (callback) => { CalendarModule.getEvents((error, events) => { if (error) { console.error(error); } else { callback(events); } }); }, findEvents: async () => { try { const events = await CalendarModule.findEvents(); return events; } catch (error) { console.error(error); throw error; } } }; // Usage in components import CalendarModule from './CalendarModule'; function MyComponent() { const handleCreateEvent = () => { CalendarModule.createEvent('Meeting', 'Office', Date.now()); }; const handleGetEvents = async () => { const events = await CalendarModule.findEvents(); console.log('Events:', events); }; return ( <View> <Button title="Create Event" onPress={handleCreateEvent} /> <Button title="Get Events" onPress={handleGetEvents} /> </View> ); }
Turbo Modules (New Architecture)
Creating a Turbo Module
// NativeCalendarModule.ts (Codegen spec) import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { createEvent(name: string, location: string, date: number): void; findEvents(): Promise<string[]>; } export default TurboModuleRegistry.getEnforcing<Spec>('CalendarModule');
Benefits of Turbo Modules
- Lazy loading: Loaded only when used
- Type safety with TypeScript
- Faster initialization
- Better performance via JSI
Native UI Components
Custom Native View (iOS - Swift)
// RCTCustomViewManager.swift import UIKit @objc(CustomViewManager) class CustomViewManager: RCTViewManager { override static func requiresMainQueueSetup() -> Bool { return true } override func view() -> UIView! { return CustomView() } @objc func setColor(_ view: CustomView, color: NSNumber) { view.backgroundColor = RCTConvert.uiColor(color) } } class CustomView: UIView { override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = .blue } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
Custom Native View (Android - Kotlin)
// CustomViewManager.kt class CustomViewManager : SimpleViewManager<View>() { override fun getName(): String { return "CustomView" } override fun createViewInstance(reactContext: ThemedReactContext): View { return View(reactContext).apply { setBackgroundColor(Color.BLUE) } } @ReactProp(name = "color") fun setColor(view: View, color: Int) { view.setBackgroundColor(color) } }
JavaScript Usage
import { requireNativeComponent } from 'react-native'; const CustomView = requireNativeComponent('CustomView'); function MyComponent() { return ( <CustomView style={{ width: 200, height: 200 }} color="red" /> ); }
Common Native Module Issues
Module Not Found
# iOS: Clear build and reinstall pods cd ios && rm -rf build Pods && pod install && cd .. npm run ios # Android: Clean and rebuild cd android && ./gradlew clean && cd .. npm run android # Clear Metro cache npx react-native start --reset-cache
Autolinking Not Working
# Verify module in package.json npm list react-native-camera # Re-run pod install cd ios && pod install && cd .. # Check react-native.config.js for custom linking config
Native Crashes
# iOS: Check Xcode console for crash logs # Look for: # - Unrecognized selector sent to instance # - Null pointer exceptions # - Memory issues # Android: Check logcat adb logcat *:E # Look for: # - Java exceptions # - JNI errors # - Null pointer exceptions
When to Use This Skill
Ask me when you need help with:
- Integrating third-party native modules
- Creating custom native modules
- Troubleshooting native module installation
- Writing iOS native code (Swift/Objective-C)
- Writing Android native code (Kotlin/Java)
- Debugging native crashes
- Understanding Turbo Modules and JSI
- Migrating to New Architecture
- Creating custom native UI components
- Handling platform-specific APIs
- Resolving autolinking issues
Essential Commands
Module Development
# Create module template npx create-react-native-module my-module # Build iOS module cd ios && xcodebuild # Build Android module cd android && ./gradlew assembleRelease # Test module locally npm link cd ../MyApp && npm link my-module
Debugging Native Code
# iOS: Run with Xcode debugger open ios/MyApp.xcworkspace # Android: Run with Android Studio debugger # Open android/ folder in Android Studio # Print native logs # iOS tail -f ~/Library/Logs/DiagnosticReports/*.crash # Android adb logcat | grep "CalendarModule"
Pro Tips & Tricks
1. Type-Safe Native Modules with Codegen
Use Codegen (New Architecture) for type safety:
// NativeMyModule.ts import type { TurboModule } from 'react-native'; import { TurboModuleRegistry } from 'react-native'; export interface Spec extends TurboModule { getString(key: string): Promise<string>; setString(key: string, value: string): void; } export default TurboModuleRegistry.getEnforcing<Spec>('MyModule');
2. Event Emitters for Native → JS Communication
// iOS - Emit events to JavaScript import Foundation @objc(DeviceOrientationModule) class DeviceOrientationModule: RCTEventEmitter { override func supportedEvents() -> [String]! { return ["OrientationChanged"] } @objc override static func requiresMainQueueSetup() -> Bool { return true } @objc func startObserving() { NotificationCenter.default.addObserver( self, selector: #selector(orientationChanged), name: UIDevice.orientationDidChangeNotification, object: nil ) } @objc func stopObserving() { NotificationCenter.default.removeObserver(self) } @objc func orientationChanged() { let orientation = UIDevice.current.orientation sendEvent(withName: "OrientationChanged", body: ["orientation": orientation.rawValue]) } }
// JavaScript - Listen to native events import { NativeEventEmitter, NativeModules } from 'react-native'; const { DeviceOrientationModule } = NativeModules; const eventEmitter = new NativeEventEmitter(DeviceOrientationModule); function MyComponent() { useEffect(() => { const subscription = eventEmitter.addListener('OrientationChanged', (data) => { console.log('Orientation:', data.orientation); }); return () => subscription.remove(); }, []); return <View />; }
3. Native Module with Callbacks
// Android - Pass callbacks @ReactMethod fun processData(data: String, successCallback: Callback, errorCallback: Callback) { try { val result = heavyProcessing(data) successCallback.invoke(result) } catch (e: Exception) { errorCallback.invoke(e.message) } }
// JavaScript CalendarModule.processData( 'input data', (result) => console.log('Success:', result), (error) => console.error('Error:', error) );
4. Synchronous Native Methods (Use Sparingly)
// iOS - Synchronous method (blocks JS thread!) @objc func getDeviceId() -> String { return UIDevice.current.identifierForVendor?.uuidString ?? "unknown" }
// JavaScript - Synchronous call const deviceId = CalendarModule.getDeviceId(); console.log(deviceId); // Returns immediately
Warning: Synchronous methods block the JS thread. Use only for very fast operations (<5ms).
Integration with SpecWeave
Native Module Planning
- Document native dependencies in
spec.md - Include native module setup in
plan.md - Add native code compilation to
tasks.md
Testing Strategy
- Unit test native code separately
- Integration test JS ↔ Native bridge
- Test on both iOS and Android
- Document platform-specific behaviors
Documentation
- Maintain native module API documentation
- Document platform-specific quirks
- Keep runbooks for common native issues