# Expo Modules API

## Expo Modules API: Overview

An overview of the APIs and utilities provided by Expo to develop native modules.

## What is the Expo Modules API
The Expo Modules API allows you to write Swift and Kotlin to add new capabilities to your app with native modules and views. The API is designed to take advantage of modern language features, to be as consistent as possible on both platforms, to require minimal boilerplate, and provide comparable performance characteristics to React Native's Turbo Modules API. Expo Modules all support the New Architecture and are automatically backwards compatible with existing React Native apps using the old architecture.
We believe that using the Expo Modules API makes building and maintaining nearly all kinds of React Native modules about as easy as it can be, and we think that the Expo Modules API is the best choice for the vast majority of developers building native modules for their apps.
### Common questions
Note: Do I need to know the Expo Modules API to build an Expo / React Native app?
---
Most of the time, Expo and React Native developers don't need to write any native code &mdash; libraries are already available for a wide range of use cases, from camera to video to maps to haptics and much more.
But sometimes, nothing does exactly what you need. Maybe you want to integrate an analytics service that your company mandates but that doesn't yet have a React Native library yet, so you need to build a module around their SDK. Or maybe you want to access a system feature that your app requires, but isn't commonly used, so nobody maintains a library for it.
---
Note: When should I use Turbo Modules and when should I use the Expo Modules API?
---
To summarize and paraphrase the [recommendation from the React Native team](https://github.com/react-native-community/discussions-and-proposals/blob/main/proposals/0759-react-native-frameworks.md#what-do-we-recommend-to-react-native-library-developers):
- If you intend to use C++ in your native module, use Turbo Modules since it provides easier access to lower-level mechanisms.
- If you are looking for a better developer experience and you are willing to depend on the `expo` package in your module, then use the Expo Modules API.
---
Note: Where can I find open source Expo Modules to learn from?
---
The [Expo SDK](https://github.com/expo/expo/tree/main/packages) is a great place to look if you want to learn how we have implemented our libraries. Another great resource is open source apps, such as [Bluesky](https://github.com/bluesky-social/social-app/tree/main/modules).
The following libraries are some of our favorites from the community:
- [`react-native-widget-extension`](https://github.com/bndkt/react-native-widget-extension)
- [`burnt`](https://github.com/nandorojo/burnt)
- [`expo-video-metadata`](https://github.com/hirbod/expo-video-metadata)
- [`swiftui-react-native`](https://github.com/andrew-levy/swiftui-react-native)
- [`react-native-ios-context-menu`](https://github.com/dominicstop/react-native-ios-context-menu)
- [`react-native-mlkit`](https://github.com/infinitered/react-native-mlkit)
- [`react-native-passkeys`](https://github.com/peterferguson/react-native-passkeys)
- [`expo-drag-drop-content-view`](https://github.com/AlirezaHadjar/expo-drag-drop-content-view)
---
Note: What impact does using the Expo Modules API have on my app size?
---
Adding the Expo Modules API to your app has a negligible impact on your app size, it may increase the size by a few hundred kilobytes. [Learn more in this blog post](https://blog.expo.dev/embracing-expo-modules-in-your-react-native-projects-cd8ed4cbec3).
---
Note: What impact does using the Expo Modules API have on my app's performance?
---
The Expo Modules API has similar performance characteristics to React Native's Turbo Modules API. Both APIs leverage React Native's JavaScript Interface (JSI), rather than the legacy approach of using a JSON message queue ("bridge") ([learn more about JSI](https://reactnative.dev/docs/the-new-architecture/landing-page#fast-javascriptnative-interfacing)).
Neither Expo Modules nor Turbo Modules are designed to be as fast as technically possible, but rather they are fast where it matters. For example, the Expo Modules API could leverage code generation and the new native Swift / C++ interop to reduce the overhead of individual method calls. However, this imposes some developer experience challenges and overhead, and we have not yet encountered any use cases where such an optimization would provide any meaningful real-world performance improvements. In reality, the time spent executing the body of a native method is often orders of magnitude greater than the overhead of the method invocation. Both Expo Modules and Turbo Modules can easily execute hundreds of thousands of native method calls per second, which is well over what you are likely to find in any app, and the overhead of the method calls is unlikely to be the bottleneck.
If you encounter any performance bottlenecks with the Expo Modules API, [file an issue](https://github.com/expo/expo/issues/new/choose) and we'd be happy to discuss it with you.
---
Note: Does the Expo Modules API support platforms other than Android, iOS, and web?
---
The Expo Modules API has experimental support for macOS and tvOS. See [Additional platform support](/modules/additional-platform-support/) tutorial for more information.
---
Note: How can I use the Expo Modules API to make a third-party SDK available to my Expo app?
---
Learn more about this in the [Integrate an existing library](/modules/existing-library/) tutorial.
---
## Next steps


## Expo Modules API: Get started

Learn about getting started with Expo modules API.

**There are two ways to get started with the Expo Modules API:** you can either initialize a new module from scratch or add the Expo Modules API to an existing module. This guide will walk you through creating a new module from scratch, and the [Integrating in an existing library](/modules/existing-library) covers the latter.
The two recommended flows to create a new module with Expo Modules API:
- [Add a new module to an existing Expo application](#add-a-new-module-to-an-existing-application), and use it to test and develop your module.
- [Create a new module in isolation with a generated example project](#create-a-new-module-with-an-example-project) if you want to reuse it in multiple projects or publish it to npm.
Both of these flows are covered in the next sections.
## Add a new module to an existing application
Step 1: 
### Create the local Expo module
Navigate to your project directory (the one that contains the **package.json** file) and run the following command. This is the recommended way to create a local Expo module.
```sh
$ npx create-expo-module@latest --local
```
You can provide a meaningful module name in the CLI prompt. For the rest of the prompts, you can also accept the default suggestions.
Once you've run the command, you will see a new directory created in your project called **modules**. The directory structure should look like this:
```
âââ modules/
    âââ my-module/
        âââ android/
        â   âââ 
        âââ ios/
        â   âââ 
        âââ src/
        â   âââ 
        âââ expo-module.config.json
        âââ index.ts
```
Then, if your project doesn't have native projects generated (**android** and **ios** directories), run the following command, otherwise skip this command:
```sh
$ npx expo prebuild --clean
```
> **Note**: If you have a pre-existing **ios** directory in your project's root which was created using `npx expo prebuild`, you must reinstall the pods:
>
> 
> ```sh
$ npx pod-install
```
Step 2: 
### Use the local module
Import the local module in your application, for example in **App.js** or **App.tsx** or **app/(tabs)/index.tsx**:
```tsx app/(tabs)/index.tsx
import MyModule from '@/modules/my-module';
export default function HomeScreen() {
  return (
    <View style={styles.container}>
      <Text>{MyModule.hello()}</Text>
    </View>
  );
}
```
Start the development server in your terminal so that when you edit the native module and build the app in the next step, the changes will be reflected in the app:
```sh
$ npx expo start
```
Congratulations! You have created a local Expo module. You can now start working on it.
> **info** **Tip**: You can also use absolute import paths [by applying these configuration changes](https://expo.fyi/absolute-path-expo-modules.md).
Step 3: 
### Edit the module
To develop and test your module locally, let's use Android Studio and Xcode for Android and iOS.
#### Android
1. Open the **android** directory (that is generated by `npx expo prebuild` in step 1) from your project in Android Studio. It may take a while for Gradle to finish syncing the native directory project.
2. Once the project is synced, open **modules/my-module/android/src/main/java/expo/modules/mymodule/MyModule.kt** file.
3. Change `hello` function to return a different string, such as "Hello world! ðð¤" and save the file.
4. Build the app by clicking **Run 'app'** button from top menu bar and you will see the changes on the screen.
You have to repeat the build step anytime you make a change to the native code to the changes.
#### iOS
1. Open the **ios** directory (that is generated by `npx expo prebuild` in step 1) from your project in Xcode by running `xed ios` command.
2. Under **Pods** > **Development Pods** > **MyModule**, open **MyModule.swift** file.
3. Change `hello` function to return a different string, such as "Hello world! ðð" and save the file.
4. Build your app by clicking **Run** button from top menu bar or press <kbd>â Cmd</kbd> + <kbd>R</kbd>, you will see the changes on the screen.
You have to repeat the build step anytime you make a change to the native code to the changes.
> **info** **Tip**: Use `npx pod-install` to reinstall the pods if you add new native files to the module or when you modify **expo-module.config.json**.
> **Note**: There are also other flows for working on an Expo module in parallel with your application. For example, you can use a monorepo or publish to npm, as described in the [How to use a standalone Expo module](/modules/use-standalone-expo-module-in-your-project) guide.
## Create a new module with an example project
Step 1: 
### Create the Expo module
To create a new Expo module from scratch, run the `create-expo-module` script as shown below.
The script will ask you a few questions and then generate the native Expo module along with the example app for Android and iOS that uses your new module.
```sh
`$ npx create-expo-module@latest my-module`
```
Step 2: 
### Open the module and start the development server
Navigate to the module directory and then open the Android and/or iOS example project by running the following commands:
```sh
`$ cd my-module`
`$ npm run open:android`
`$ npm run open:ios`
```
Go to **example** directory and start the development server in your terminal so that when you edit the native module and build the app in the next step, the changes will be reflected in the app:
```sh
$ cd example
$ npx expo start
```
> **Note:** If you're using Windows, you can open the example project by opening the **android** directory in Android Studio, but you cannot open the iOS project files.
Step 3: 
### Edit the module
#### Android
1. Open **my-module/android/src/main/java/expo/modules/mymodule/MyModule.kt** file.
2. Change `hello` function to return a different string, such as "Hello world! ðð¤" and save the file.
3. Build the app by clicking **Run 'app'** button from top menu bar and you will see the changes on the screen.
You have to repeat the build step anytime you make a change to the native code to the changes.
#### iOS
1. Under **Pods** > **Development Pods** > **MyModule**, open **MyModule.swift** file.
2. Change `hello` function to return a different string, such as "Hello world! ðð" and save the file.
3. Build your app by clicking **Run** button from top menu bar or press <kbd>â Cmd</kbd> + <kbd>R</kbd>, you will see the changes on the screen.
You have to repeat the build step anytime you make a change to the native code to the changes.
> **info** **Tip**: Use `npx pod-install` to reinstall the pods if you add new native files to the module or when you modify **expo-module.config.json**.
## Next steps
Now that you have learned how to initialize a module and make simple changes to it, you can continue to a tutorial or dive right into the API reference.