new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo & React Native · all subjects

config-plugins

207 notes in this subject, read out of this brain and free to use. This is page 3 of 4.

Check community config plugins

If a package requires a config plugin but doesn't supply one, check the community plugins repository at https://github.com/expo/config-plugins to see if one already exists.

Use npx expo install to add plugins

Some packages can automatically add required Expo config plugins by running `npx expo install` with all packages in the package.json dependencies.

Debug TV config plugin

To see debug information during prebuild, set debug environment variables before running prebuild. Use export DEBUG=expo:* to see all Expo CLI and config plugin debug information, or export DEBUG=expo:react-native-tvos:config-tv to see only debug information for the TV plugin.

Apple TV config plugin modifications

The config plugin modifies ios/Podfile to target tvOS instead of iOS, modifies the Xcode project to target tvOS instead of iOS, and modifies the splash screen (SplashScreen.storyboard) to work on tvOS.

Android TV config plugin modifications

The config plugin modifies AndroidManifest.xml to remove the default phone portrait orientation and add the required intent for TV apps. It also modifies MainApplication.kt to remove unsupported Flipper invocations.

Install TV config plugin

Install the TV config plugin using: npx expo install @react-native-tvos/config-tv -- --dev (npm), yarn expo install @react-native-tvos/config-tv -- --dev (yarn), pnpm expo install @react-native-tvos/config-tv -- --dev (pnpm), or bun expo install @react-native-tvos/config-tv -- --dev (bun). The plugin modifies the project for TV when the environment variable EXPO_TV is set to 1 or the plugin parameter isTV is set to true.

Verify TV config plugin in app.json

Verify that the TV config plugin appears in app.json with: { "plugins": ["@react-native-tvos/config-tv"] }.

iOS permission configuration via config plugin properties

Many iOS permission messages are directly configurable using config plugin properties associated with the library that adds them. For example, with expo-media-library, you can configure photo permission messages using photosPermission and savePhotosPermission properties in the plugin configuration.

iOS permission message via config plugin example

Example of configuring iOS permission messages using expo-media-library config plugin: ```json { "plugins": [ [ "expo-media-library", { "photosPermission": "Allow $(PRODUCT_NAME) to access your photos.", "savePhotosPermission": "Allow $(PRODUCT_NAME) to save photos." } ] ] } ```

Disable precompiled modules on iOS via config plugin

Set the ios.usePrecompiledModules property of the expo-build-properties config plugin to false to build every Expo Module from source. This applies to both local builds and EAS Build, and takes effect the next time you run npx expo prebuild. Example configuration in app.json: {"expo": {"plugins": [["expo-build-properties", {"ios": {"usePrecompiledModules": false}}]]}}

expo-brownfield config plugin default settings

The expo-brownfield config plugin automatically adds an entry to the plugins array in app.json with default configuration, which is sufficient for most projects. The plugin entry is {"expo": {"plugins": ["expo-brownfield"]}}. The defaults are derived from the app config—for example, target names are based on the app's scheme or slug.

expo-brownfield custom configuration options

Custom expo-brownfield configuration can be passed with options to customize target names, bundle identifiers, and publishing configuration. For iOS, the options are: targetName (string) and bundleIdentifier (string). For Android, the options are: libraryName (string), group (string), package (string), and version (string). Example: {"expo": {"plugins": [["expo-brownfield", {"ios": {"targetName": "MyBrownfield", "bundleIdentifier": "com.example.mybrownfield"}, "android": {"libraryName": "mybrownfield", "group": "com.example", "package": "com.example.mybrownfield", "version": "1.0.0"}}]]}}

LogRocket config plugin setup in app.json

Add LogRocket config plugin to app.json. The expo-build-properties plugin must be configured with Android minSdkVersion 25, and the @logrocket/react-native plugin must be included. Example: {"plugins": [["expo-build-properties", {"android": {"minSdkVersion": 25}}], "@logrocket/react-native"]}

@clerk/expo config plugin setup

Add @clerk/expo and expo-secure-store to the plugins array in your app config. If you used npx expo install, Expo automatically adds them. Example: {"expo": {"plugins": ["expo-secure-store", "@clerk/expo"]}}

@clerk/expo plugin options and behavior

The @clerk/expo config plugin adds the Apple Sign In entitlement (disable with appleSignIn: false if your app doesn't use it), registers the Android intent filter for hosted authentication callback, and applies Android packaging fixes required by clerk-android SDK. Hosted authentication derives its default callback from android.package and ios.bundleIdentifier in your app config.

Universal 'apple' platform in expo-module.config.json

The expo-module.config.json file should use the 'apple' platform instead of 'ios' to provide seamless support for multiple Apple platforms. This tells autolinking that the module may support any Apple platform, with the actual target support determined by the podspec. The 'apple' key replaces 'ios' in the configuration, e.g., changing 'platforms': ['ios'] to 'platforms': ['apple'] and 'ios': {...} to 'apple': {...}.

Podspec platforms declaration for multi-platform support

The module's podspec must declare support for all target platforms using the s.platforms attribute instead of s.platform. The format should specify each platform with its minimum version, for example: s.platforms = { :ios => '13.4', :tvos => '13.4', :osx => '10.15' }. Running 'pod install' is required after making podspec changes.

Example Kotlin module template

package my.module.package import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class MyModule : Module() { override fun definition() = ModuleDefinition { // Definition components go here } }

expo-module.config.json required for Expo Autolinking

To integrate Expo Modules API into an existing React Native library, you must create an expo-module.config.json file at the root of your project with an empty object {} inside it. This file is required for Expo Autolinking to recognize your library as an Expo module and automatically link your native code.

Add expo-modules-core native dependency to build.gradle and podspec

Add expo-modules-core as a dependency in your build.gradle file using 'implementation project(':expo-modules-core')' and in your podspec file using 's.dependency 'ExpoModulesCore''.

Package.json dependencies for Expo module library

In your library's package.json, add 'expo' as a peer dependency (using version range '*'), and add 'expo-modules-core' as a dev dependency only. Mark the 'expo' peer dependency as optional using peerDependenciesMeta.

Create native module with Kotlin and Swift

Create a Kotlin class extending Module with a definition() method returning ModuleDefinition, and a Swift class extending Module with a definition() method returning ModuleDefinition. The Kotlin package should be in your module package (for example, my.module.package), and Swift requires importing ExpoModulesCore.

Register modules in expo-module.config.json

Register your native module classes in expo-module.config.json under the ios.modules array (using the class name like 'MyModule') and android.modules array (using the full qualified class name like 'my.module.package.MyModule'). Expo Autolinking will automatically link these classes as native modules.

Link native modules on Android and iOS

On Android, the native module class is linked automatically before building as part of the Gradle build task. On iOS, you must run 'pod install' to link the new class.

Access native module from JavaScript using requireNativeModule

Native module classes are accessible from JavaScript code using the requireNativeModule function from the expo-modules-core package. Create a separate TypeScript file that exports the native module using 'import { requireNativeModule } from 'expo-modules-core'; export default requireNativeModule('MyModule');'.

Example Swift module template

import ExpoModulesCore public class MyModule: Module { public func definition() -> ModuleDefinition { // Definition components go here } }

Example expo-module.config.json with modules registered

{ "ios": { "modules": ["MyModule"] }, "android": { "modules": ["my.module.package.MyModule"] } }

Example MyModule.ts wrapper for JavaScript

import { requireNativeModule } from 'expo-modules-core'; export default requireNativeModule('MyModule');

Use cases for integrating Expo Modules API into existing library

You may want to integrate Expo Modules API into an existing React Native library to incrementally rewrite your library or to take advantage of Android lifecycle listeners and iOS AppDelegate subscribers for automatic library setup.

Enable inline modules in app.json

To enable inline modules functionality in Expo CLI and Expo Modules Autolinking, add an empty object to expo.experiments.inlineModules in app.json: { "expo": { "experiments": { "inlineModules": {} } } }

Configure watched directories for inline modules

Use expo.experiments.inlineModules.watchedDirectories to specify which directories inline modules can be created in. Example: { "expo": { "experiments": { "inlineModules": { "watchedDirectories": ["app", "src"] } } } } Files inside nested directories will also be used.

Inline modules watched directories requirements

A directory in watchedDirectories must meet these criteria: (1) It needs to be inside a TypeScript/JavaScript project with an ancestor package.json. (2) It cannot be the whole project directory ("./") nor an ancestor of it (../ ). (3) It cannot be a subdirectory of another directory in watchedDirectories. (4) It cannot contain special characters like space, parentheses, or dollar sign.

Inline modules watchedDirectories with nested paths

If watchedDirectories is set to ["app"], inline module files in nested paths like app/nested/directory/SomeModule.kt will be discovered and the module can be used in your app.

Configure Xcode targets for inline modules on iOS

Use expo.experiments.inlineModules.xcodeProjectTargets to specify which Xcode targets inline module files are added to on iOS. When omitted, inline modules are added to your app's main target only. Example: { "expo": { "experiments": { "inlineModules": { "xcodeProjectTargets": ["MyApp", "MyAppWidgets"] } } } } Each entry should be the name of a target as it appears in the Xcode project and ios/Podfile target blocks. Use the target name only—do not include abstract target names.

Rebuild after inline modules config changes

You need to run `npx expo prebuild` after changing the app config for inline modules configuration changes to take effect.

Inline module file naming convention

The inline module file name must match the native module name (which needs to be unique in your whole app). If you have a SimpleModule.kt file, the class name inside must be SimpleModule and it must match the filename. The Name() declaration in the module definition can be omitted since it matches the filename.

Inline module Kotlin naming example

Example of a Kotlin inline module with proper naming: // SimpleModule.kt class SimpleModule: Module() { public func definition() -> ModuleDefinition { // Name("SimpleModule") can be omitted } } The class name must match the filename.

expo-module.config.json file purpose

Expo modules are configured in expo-module.config.json. This file is capable of configuring autolinking and module registration.

expo-module.config.json platforms property

The platforms property is an array of supported platforms. Acceptable values are: android, apple (or the more granular ios, macos, tvos), web, and devtools (devtools is used for creating dev tools plugins).

expo-module.config.json apple platform config

The apple property configures options specific to Apple platforms. It contains: modules (names of Swift native modules classes to put in the generated modules provider file) and appDelegateSubscribers (names of Swift classes that hook into ExpoAppDelegate to receive AppDelegate lifecycle events).

expo-module.config.json android platform config

The android property configures options specific to the Android platform. It contains: modules (full names including package and class name of Kotlin native modules classes to put in the generated package provider file).

Add expo-notifications plugin to app config

Add 'expo-notifications' to the plugins array in your app.json configuration file to enable push notifications in your Expo app.

Set app icon and splash screen with expo-splash-screen config plugin

The app icon can be set to a specific image path in the app configuration. The splash screen is configured using the expo-splash-screen config plugin, which allows specifying an image, background color, and positioning. These settings require a development server restart to take effect.

Android 11+ requires manifest configuration for URL schemes

For Android 11 (API level 30) and above, you must specify the intents your app will handle in the AndroidManifest.xml file. This can be accomplished by creating a config plugin.

Config plugin example for Android mailto and tel intents

Example config plugin that enables linking to email and phone apps by defining intents in AndroidManifest.xml: import { withAndroidManifest, ConfigPlugin } from 'expo/config-plugins'; const withAndroidQueries: ConfigPlugin = config => { return withAndroidManifest(config, config => { config.modResults.manifest.queries = [ { intent: [ { action: [{ $: { 'android:name': 'android.intent.action.SENDTO' } }], data: [{ $: { 'android:scheme': 'mailto' } }], }, { action: [{ $: { 'android:name': 'android.intent.action.DIAL' } }], }, ], }, ]; return config; }); }; module.exports = withAndroidQueries;

Config plugins customize native projects in CNG

Config plugins let you customize native Android and iOS projects generated with `npx expo prebuild` in Continuous Native Generation (CNG) projects. They can add properties to native config files, copy assets to native projects, or apply advanced configurations such as adding an app extension target.

Config plugins as synchronous functions with modifiable ExpoConfig

Plugins are synchronous functions that accept an `ExpoConfig` and return a modified `ExpoConfig`. By convention, plugin functions are prefixed with the word `with`, such as `withMyApiKey`.

Mods are async functions that modify native project files during code generation

Mods are async functions that modify files in native projects, such as source code or configuration files (plist, xml). Unlike the rest of the app config which serializes after reading, the `mods` object doesn't serialize, allowing you to perform actions during code generation.

Plugins invoked during config reading, mods only during prebuild syncing

`plugins` are invoked whenever the `getConfig` method from `expo/config` reads the configuration. In contrast, `mods` are invoked only during the "syncing" phase of `npx expo prebuild`.

Create expo module with create-expo-module command

Initialize a new Expo module project using `npx create-expo-module <module-name>`. This sets up scaffolding for Android, iOS, and TypeScript and includes an example project to test the module within an app.

withAndroidManifest helper modifies AndroidManifest.xml

The `withAndroidManifest` mod from `expo/config-plugins` allows you to read and modify the AndroidManifest.xml file. Use `AndroidConfig.Manifest` helpers like `addMetaDataItemToMainApplication()` to add metadata to the main application.

withInfoPlist helper modifies Info.plist

The `withInfoPlist` mod from `expo/config-plugins` allows you to modify Info.plist values by setting properties on the `modResults` object and returning the config.

Read AndroidManifest.xml metadata using PackageManager

On Android, access metadata information from AndroidManifest.xml using the `packageManager` class. Call `getApplicationInfo()` with the `PackageManager.GET_META_DATA` flag to retrieve application info, then access metadata via `applicationInfo?.metaData?.getString(key)`.

Read Info.plist values using Bundle.main.object

On iOS, read Info.plist property values using `Bundle.main.object(forInfoDictionaryKey: "key-name")` and cast to the desired type, such as `as? String`.

Plugin configuration file structure: app.plugin.js entry point

Create an app.plugin.js file at the project root as the plugin's entry point. It should export the plugin module: `module.exports = require('./plugin/build');`. Create a plugin/src/index.ts with the ConfigPlugin implementation, and a plugin/tsconfig.json extending 'expo-module-scripts/tsconfig.plugin'.

Reference config plugin in app.json with optional parameters

Add a config plugin to an app by including it in the `plugins` array in app.json. Plugins can accept configuration options: `"plugins": [["../app.plugin.js", { "apiKey": "cus••••••pi" }]]`.

Complete config plugin example: inject API key to Android and iOS

Example plugin combining withInfoPlist and withAndroidManifest to inject an API key: ```ts import { withInfoPlist, withAndroidManifest, AndroidConfig, ConfigPlugin, } from 'expo/config-plugins'; const withMyApiKey: ConfigPlugin<{ apiKey: string }> = (config, { apiKey }) => { config = withInfoPlist(config, config => { config.modResults['MY_CUSTOM_API_KEY'] = apiKey; return config; }); config = withAndroidManifest(config, config => { const mainApplication = AndroidConfig.Manifest.getMainApplicationOrThrow(config.modResults); AndroidConfig.Manifest.addMetaDataItemToMainApplication( mainApplication, 'MY_CUSTOM_API_KEY', apiKey ); return config; }); return config; }; export default withMyApiKey; ```

Run TypeScript compiler for plugin with npm run build

In the root of a module project, run `npm run build` to start the TypeScript compiler in watch mode. This compiles the plugin from plugin/src to plugin/build.

Test config plugin with npx expo prebuild --clean

Inside the example directory, run `npx expo prebuild --clean` to execute the plugin and update native files. This allows verification that the plugin correctly injects values into AndroidManifest.xml and Info.plist.

Kotlin ExpoNativeConfigurationModule example reading metadata

Example Kotlin module that reads MY_CUSTOM_API_KEY from AndroidManifest.xml metadata: ```kotlin package expo.modules.nativeconfiguration import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import android.content.pm.PackageManager class ExpoNativeConfigurationModule() : Module() { override fun definition() = ModuleDefinition { Name("ExpoNativeConfiguration") Function("getApiKey") { val applicationInfo = appContext?.reactContext?.packageManager?.getApplicationInfo(appContext?.reactContext?.packageName.toString(), PackageManager.GET_META_DATA) return@Function applicationInfo?.metaData?.getString("MY_CUSTOM_API_KEY") } } } ```

Give your agent this brain