Subchapter 15.2
references/create-expo-module.mdMarkdown10 KBView on GitHub
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.
Use a local module when the native code only belongs to one Expo app.
package.json:expo.autolinking.nativeModulesDir, or falls back to modules/Use a standalone module when the module should be reusable across apps, live in a monorepo package, or be published to npm.
package.jsonexample app unless --no-example is passedWhen 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.
Use an explicit slug or path.
npx create-expo-module@latest key-value-store --local --platform apple android --features Function AsyncFunctionIf 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 AsyncFunctionImportant quirk:
my-module--name changes the native module class name, not the directory namenpx create-expo-module@latest expo-key-value-store --platform apple android --features Function AsyncFunctionThese 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-version only affect standalone modules because local modules do not have a standalone package manifest.--with-readme, --with-changelog, --no-example, and --package-manager are standalone-only concerns.--barrel only affects local modules.--name changes the native module class name. It does not rename the local module directory.Valid values are:
appleandroidwebBehavior to remember:
--platform is omitted in non-interactive modeapp.json:expo.platforms when available, mapping ios to appleIf you do not want web support, omit web during scaffolding instead of removing it later.
Feature examples are generated starter snippets, not capability restrictions. They are small working examples of common Expo Modules API patterns.
Available values:
ConstantFunctionAsyncFunctionEventViewViewEventSharedObjectImportant behaviors:
--features or --full-example is passed--full-example is equivalent to --features allViewEvent automatically includes ViewUse View only when the module actually renders UI. For native-only modules, do not scaffold the view files unless you plan to use them.
index.ts barrel by default--barrel only if you want a root barrel fileexample apppackage.json; they rely on the host appIf --barrel is not used, the CLI’s follow-up instructions point to direct imports from the module’s src/ files.
--package-manager is only relevant for standalone modulesexample app is created only when examples are enabled; --no-example skips it--with-readme and --with-changelog opt into those filesThe generated standalone scripts include build, clean, test, prepare, open:ios, and open:android.
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-supportExplicit usage:
npx create-expo-module@latest add-platform-support --platform androidYou can also pass the module path:
npx create-expo-module@latest add-platform-support ./packages/expo-key-value-store --platform webImportant behaviors:
apple, android, and web--platform is requiredexpo-module.config.jsonandroid/ or ios/ directoriesadd-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:
If no features are detected or provided, the command creates a minimal scaffold for the new platform.
EXPO_BETA: use the next template versionEXPO_DEBUG: enable debug logsEXPO_NO_TELEMETRY: disable telemetryEXPO_NONINTERACTIVE: force non-interactive modeCI: same as EXPO_NONINTERACTIVE, used in CI environments