9.8 KiB
create-expo-module
Use create-expo-module to scaffold new Expo modules and create-expo-module add-platform-support to extend existing Expo modules.
Prefer create-expo-module over manually creating module files and directories. In most cases, the right move is to generate the scaffold first and then build on top of it.
Choose the Module Type First
Local module
Use a local module when the native code only belongs to one Expo app.
- lives inside the app
- uses the app's dependencies and tooling
- does not create an example app
- respects
package.json:expo.autolinking.nativeModulesDir, or falls back tomodules/
Standalone module
Use a standalone module when the module should be reusable across apps, live in a monorepo package, or be published to npm.
- has its own
package.json - installs its own dependencies
- builds TypeScript during scaffolding
- usually creates an
exampleapp unless--no-exampleis passed - may initialize a Git repo if not already inside one
When creating a standalone module, default to keeping the example app. Only skip it when the user explicitly asks for --no-example or clearly does not want the example project.
Recommended Commands
Local module
Use an explicit slug or path.
npx create-expo-module@latest key-value-store --local --platform apple android --features Function AsyncFunction
If you need deterministic non-interactive output, pass the slug or path explicitly and then pass the rest of the options:
EXPO_NONINTERACTIVE=1 npx create-expo-module@latest key-value-store \
--local \
--name KeyValueStore \
--package expo.modules.keyvaluestore \
--platform apple android \
--features Function AsyncFunction
Important quirk:
- in non-interactive local scaffolding, omitting the positional slug causes the CLI to fall back to
my-module --namechanges the native module class name, not the directory name
Standalone module
npx create-expo-module@latest expo-key-value-store --platform apple android --features Function AsyncFunction
Creation Options
These are the module creation options exposed by the CLI:
| Option | Applies to | Notes |
|---|---|---|
[path] |
local, standalone | Positional slug or target path. Use this explicitly for stable local scaffolding in non-interactive mode. |
--local |
local | Create a local module inside the current Expo project. |
--platform <platforms...> |
local, standalone | Valid values: apple, android, web. |
--features <features...> |
local, standalone | Pick generated feature examples. Use all to include everything. |
--full-example |
local, standalone | Equivalent to --features all. |
--barrel |
local | Generate a local index.ts barrel. Ignored for standalone modules. |
--source <source_dir> |
local, standalone | Use a local expo-module-template directory instead of downloading from npm. |
--name <name> |
local, standalone | Native module name, for example KeyValueStore. |
--description <description> |
standalone | Package description. |
--package <package> |
local, standalone | Android package name, for example expo.modules.keyvaluestore. |
--author-name <name> |
standalone | Package author name. |
--author-email <email> |
standalone | Package author email. |
--author-url <url> |
standalone | Package author profile URL. |
--repo <url> |
standalone | Package repository URL. |
--license <license> |
standalone | Package license identifier. |
--module-version <version> |
standalone | Initial package version. |
--package-manager <manager> |
standalone | One of npm, pnpm, yarn, bun. |
--with-readme |
standalone | Keep README.md in the generated package. |
--with-changelog |
standalone | Keep CHANGELOG.md in the generated package. |
--no-example |
standalone | Skip creating the example app. |
Notes:
--description, author flags,--repo,--license, and--module-versiononly affect standalone modules because local modules do not have a standalone package manifest.--with-readme,--with-changelog,--no-example, and--package-managerare standalone-only concerns.--barrelonly affects local modules.--namechanges the native module class name. It does not rename the local module directory.
Platforms
Valid values are:
appleandroidweb
Behavior to remember:
- standalone modules default to all platforms when
--platformis omitted in non-interactive mode - local modules also default to all platforms in non-interactive mode
- interactive local scaffolding preselects platforms from
app.json:expo.platformswhen available, mappingiostoapple - invalid platform values are ignored with a warning; if all provided values are invalid, the CLI falls back to all platforms
If you do not want web support, omit web during scaffolding instead of removing it later.
Feature Examples
Feature examples are generated starter snippets, not capability restrictions. They are small working examples of common Expo Modules API patterns.
Available values:
ConstantFunctionAsyncFunctionEventViewViewEventSharedObject
Important behaviors:
- no features selected means a minimal module
- in interactive mode, feature examples start unselected
- in non-interactive mode, no features are included unless
--featuresor--full-exampleis passed --full-exampleis equivalent to--features allViewEventautomatically includesView
Use View only when the module actually renders UI. For native-only modules, do not scaffold the view files unless you plan to use them.
Local Module Quirks
- local modules do not generate an
index.tsbarrel by default - use
--barrelonly if you want a root barrel file - local modules skip dependency installation and do not create an
exampleapp - local modules do not have a local
package.json; they rely on the host app
If --barrel is not used, the CLI's follow-up instructions point to direct imports from the module's src/ files.
Standalone Module Quirks
--package-manageris only relevant for standalone modules- if omitted, the CLI detects the package manager from the user agent or available package managers
- the scaffold builds TypeScript after installing dependencies
- the
exampleapp is created only when examples are enabled;--no-exampleskips it --with-readmeand--with-changelogopt into those files
The generated standalone scripts include build, clean, test, prepare, open:ios, and open:android.
add-platform-support
Use this subcommand when an existing Expo module needs another supported platform.
Interactive usage from the module root:
npx create-expo-module@latest add-platform-support
Explicit usage:
npx create-expo-module@latest add-platform-support --platform android
You can also pass the module path:
npx create-expo-module@latest add-platform-support ./packages/expo-key-value-store --platform web
Important behaviors:
- supported values are
apple,android, andweb - in non-interactive mode,
--platformis required - the command only adds platforms that are not already present in
expo-module.config.json - it refuses to overwrite existing
android/orios/directories - for native modules, it only works with modules that use the Expo Modules API DSL
- older module formats are not supported
Feature detection
add-platform-support tries to detect the existing module's feature examples from the native module definition. This is best effort.
Use --features to override the detected feature examples when:
- the module is unusual
- the module uses generated code
- the definition is spread across multiple files
- the generated files do not match the existing module's shape
If no features are detected or provided, the command creates a minimal scaffold for the new platform.
Environment Variables
EXPO_BETA: use the next template versionEXPO_DEBUG: enable debug logsEXPO_NO_TELEMETRY: disable telemetryEXPO_NONINTERACTIVE: force non-interactive modeCI: same asEXPO_NONINTERACTIVE, used in CI environments