All skills
expo avatar

/expo-module

@5c8f62e official
by expoexpo/skills2.6k stars
156

Framework (OSS). Guide for creating and writing Expo native modules and views using the Expo Modules API (Swift, Kotlin, TypeScript). Covers module definition DSL, native views, shared objects, config plugins, lifecycle hooks, autolinking, and type system. Use when building or modifying native modules for Expo. Not for migrating an existing Swift module from the definition DSL to the Expo Modules API 2.0 macros; use expo-migrate-module (from the expo-experiments plugin) for that.

Use this Skill: https://skilld.dev/gh/expo/skills/expo-module

This session only. Nothing lands on disk.

referenceslifecycle.md

≈941 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Lifecycle Hooks Reference

Module Lifecycle (in module definition)

OnCreate {
  // Module initialized - preferred over class initializers
}

OnDestroy {
  // Module deallocated - clean up resources
}

OnAppContextDestroys {
  // App context is being deallocated
}

iOS App Lifecycle (in module definition)

OnAppEntersForeground { /* UIApplication.willEnterForegroundNotification */ }
OnAppEntersBackground { /* UIApplication.didEnterBackgroundNotification */ }
OnAppBecomesActive { /* UIApplication.didBecomeActiveNotification */ }

Android Activity Lifecycle (in module definition)

OnActivityEntersForeground { /* Activity resumed */ }
OnActivityEntersBackground { /* Activity paused */ }
OnActivityDestroys { /* Activity destroyed */ }
OnNewIntent { intent -> /* Deep link received */ }
OnActivityResult { activity, result -> /* startActivityForResult callback */ }
OnUserLeavesActivity { /* User-initiated background transition */ }
RegisterActivityContracts { /* Modern activity result contracts */ }

iOS AppDelegate Subscribers

For hooking into AppDelegate events without editing AppDelegate directly. Requires app's AppDelegate to extend ExpoAppDelegate.

import ExpoModulesCore

public class MyAppDelegateSubscriber: ExpoAppDelegateSubscriber {
  public func applicationDidBecomeActive(_ application: UIApplication) {}
  public func applicationWillResignActive(_ application: UIApplication) {}
  public func applicationDidEnterBackground(_ application: UIApplication) {}
  public func applicationWillEnterForeground(_ application: UIApplication) {}
  public func applicationWillTerminate(_ application: UIApplication) {}

  public func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    return false  // Return true if handled
  }
}

Register in expo-module.config.json:

{
  "apple": {
    "appDelegateSubscribers": ["MyAppDelegateSubscriber"]
  }
}

Result aggregation:

  • didFinishLaunchingWithOptions: Returns true if any subscriber returns true
  • didReceiveRemoteNotification: Priority: failed > newData > noData

Android Lifecycle Listeners

For hooking into Activity/Application lifecycle outside module definitions. Useful for handling deep links, intents, and app-level initialization.

ReactActivityLifecycleListener

Supported callbacks: onCreate, onResume, onPause, onDestroy, onNewIntent, onBackPressed.

Note: onStart and onStop are not supported — the implementation hooks into ReactActivityDelegate which lacks these methods.

class MyPackage : Package {
  override fun createReactActivityLifecycleListeners(
    activityContext: Context
  ): List<ReactActivityLifecycleListener> {
    return listOf(MyActivityListener())
  }
}

class MyActivityListener : ReactActivityLifecycleListener {
  override fun onCreate(activity: Activity, savedInstanceState: Bundle?) { }
  override fun onResume(activity: Activity) { }
  override fun onPause(activity: Activity) { }
  override fun onDestroy(activity: Activity) { }
  override fun onNewIntent(intent: Intent?): Boolean { return false }
  override fun onBackPressed(): Boolean { return false }
}

ApplicationLifecycleListener

Supported callbacks: onCreate, onConfigurationChanged.

class MyPackage : Package {
  override fun createApplicationLifecycleListeners(
    context: Context
  ): List<ApplicationLifecycleListener> {
    return listOf(MyAppListener())
  }
}

class MyAppListener : ApplicationLifecycleListener {
  override fun onCreate(application: Application) {
    // App-level initialization
  }
}

Source: SKILL.md on GitHub

No alerts17d4 checks · Risk SAFE
  • Gen Agent Trust Hub17d

    The skill provides developer documentation and reference guides for creating and writing Expo native modules and views. All code examples and scripts align with legitimate development practices, and no security risks were identified.

  • Socket17d

    No alerts

  • Snyk17d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 5c8f62e. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 days ago.

Activeupdated 2 months ago
version
1.0.0
  • TypeScript
  • expo
  • native-modules
  • swift
  • kotlin
  • react-native
  • ios
  • android
  • config-plugins

README badge

README badge for expo/skills/expo-module

Guides you through creating and modifying Expo native modules in Swift (iOS) and Kotlin (Android), with TypeScript bindings. Use this skill when building native modules, native views, config plugins, or wrapping platform SDKs for React Native consumption.

Generated from the current SKILL.md.

What is the difference between a local module and a standalone module?
Local modules are for a single app and live in expo.autolinking.nativeModulesDir or modules/ folder, using the host app's tooling. Standalone modules have their own package metadata, scripts, and example app, and are intended for reuse, monorepos, or publishing.
Should I manually create native files or use create-expo-module?
Use create-expo-module to scaffold. It sets up the expected layout, expo-module.config.json, podspec/Gradle files, TypeScript bindings, and the example app flow. Manually creating files is error-prone and not recommended.
How do I add a new platform to an existing Expo module?
Use create-expo-module add-platform-support instead of manually copying native directories. This ensures correct file placement and configuration.
What platforms does this skill cover?
Swift (iOS), Kotlin (Android), and TypeScript. The skill provides DSL patterns for all three to create modules, native views, and shared objects.
Do I need to manually edit expo-module.config.json?
The scaffold generates it automatically, but you may need to edit it to register native modules and configure platform-specific settings like fully-qualified class names for Android.

Generated from the current SKILL.md. These answers refresh after source changes.