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 4 of 4.

Swift ExpoNativeConfigurationModule example reading from Info.plist

Example Swift module that reads MY_CUSTOM_API_KEY from Info.plist: ```swift import ExpoModulesCore public class ExpoNativeConfigurationModule: Module { public func definition() -> ModuleDefinition { Name("ExpoNativeConfiguration") Function("getApiKey") { return Bundle.main.object(forInfoDictionaryKey: "MY_CUSTOM_API_KEY") as? String } } } ```

expo-module-scripts simplifies plugin development

The npm package `expo-module-scripts` simplifies plugin development by providing a recommended default configuration for TypeScript and Jest. Although optional, it is recommended for plugin development.

ConfigPlugin TypeScript type with parameters

Define a config plugin with parameters using the generic type: `const withMyApiKey: ConfigPlugin<{ apiKey: string }> = (config, { apiKey }) => { ... }`. The second parameter receives the options object passed from app.json.

Gradle file writes must check language type and handle both assignment forms

In withAppBuildGradle, withProjectBuildGradle, or withSettingsGradle, a write to config.modResults.contents must be guarded by a check that config.modResults.language === 'groovy'. Also ensure a gradle regex matches both assignment forms when both exist in gradle files.

Idempotency requirement for config plugins

Running prebuild twice must converge to the same file state. This is the most critical property for config plugins because mistakes do not fail CI but silently corrupt an app developer's native files like Info.plist, AndroidManifest.xml, Podfile, or .pbxproj, often only on the second prebuild run.

withDangerousMod must not duplicate typed base mods

Do not create a new or expanded withDangerousMod that hand-edits files already owned by introspective base mods. These files include: AndroidManifest.xml, strings.xml, colors.xml, night colors, styles.xml, gradle.properties, Info.plist, .entitlements file, Expo.plist, and Podfile.properties.json. Use the matching typed mod instead.

Text appending to native files must use mergeContents or guard against duplication

A mod that appends or inserts text into a native file such as Podfile, app or project build.gradle, settings.gradle, AppDelegate, MainActivity, or MainApplication must either go through mergeContents (producing a @generated begin <tag> block) or short-circuit when its content is already present. Plain concatenation causes the classic double-prebuild duplication bug.

withXcodeProject modifications must check for existing items

Inside withXcodeProject, calls to addBuildPhase, addPbxGroup, addToPbxBuildFileSection, or addFramework must include a preceding lookup to verify the existing phase, group, or file is not already present.

mergeContents tags must be scoped to the owning package

A mergeContents tag value must be scoped to the owning package. Two packages sharing an unscoped tag will overwrite each other's @generated block. Example of correct scoping: expo-localization-supported-locales and expo-build-properties. Bare tag names like 'fonts' or 'locales' represent the same mistake as the unscoped xml-fonts-init tag.

Renaming existing mergeContents tags breaks idempotency

Renaming an existing tag string in mergeContents will cause the old @generated block in already prebuilt projects to never be replaced, resulting in duplicate content.

Anchor regexes must handle missing patterns

A new or changed anchor regex, or a .replace() against native template text, must have surrounding code with a path for when the anchor is not present: use try/catch, an includes precheck, or a WarningAggregator fallback.

Plugin props must be validated before native file injection

A plugin prop or app-config value interpolated into a native file (an Android resource or file name, an XML attribute, a gradle string literal, a plist key or value, or a Podfile line) must be asserted for type and format first to prevent injection vulnerabilities and corrupted projects.

New native modules require matching expo-module.config.json declarations

A new Expo Module subclass (Swift under ios/ or apple/, or Kotlin/Java under android/src/) must have a corresponding entry in the package's expo-module.config.json. The apple.modules array must include the Swift class name and android.modules must include the Kotlin class name. Without these declarations, autolinking never registers the module and the API is missing at runtime.

podName in spm.config.json must have matching podspec file

A new or renamed podName in an spm.config.json product must have a corresponding <podName>.podspec file at the package root, ios/, or apple/ directory.

Podspec and spm.config.json declarations must stay in sync

Changes to podspec source_files, exclude_files, s.dependency, s.platforms, or added/renamed/moved iOS source directories in a package with an spm.config.json must be paired with updates to the corresponding target's path, pattern, exclude, dependencies, or platforms in spm.config.json. The two build systems run in parallel and drift silently if not kept in sync.

spm.config.json keys must be declared in schema and types

An spm.config.json key must be declared in both tools/src/prebuilds/schemas/spm.config.schema.json and tools/src/prebuilds/SPMConfig.types.ts.

withDangerousMod is appropriate for file creation, copying, and deletion

A withDangerousMod is the intended approach for writing res/xml or res/font files, copying font or splash assets, and generating widget or extension sources. Do not ask for these to become typed base mods.

WarningAggregator functions are the correct contract for unsupported project shapes

Using WarningAggregator.addWarningAndroid, addWarningIOS, or addWarningForPlatform to warn and skip unsupported project shapes is the intended contract. This applies when a mod returns config unchanged for projects it cannot support, such as non-groovy build.gradle, non-Swift AppDelegate, or a file already present in a PBXGroup.

Do not flag mod ordering between different named mods

Do not assert that one named mod should run before or after a different named mod, or that withPlugins entries should be reordered to sequence different mod types. Raise ordering issues only when both actions share the same mod name or when the fix is to move work into withFinalizedMod.

Non-idempotency findings must describe the second prebuild changes

Before reporting a non-idempotency finding in config plugins, describe in the rationale what changes on the second prebuild run. Keep evidence to the single mod or write line that causes it, never a pasted excerpt of generated native files.

Overriding default Android strings.xml values

Android modules can define default string values in strings.xml that users can override in their own projects. ## Default module strings.xml The module provides default values: ```xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="expo_custom_value" translatable="false"></string> </resources> ``` ## User override in project strings.xml Users override defaults by creating a string with the same name property in their local project file at `./android/app/src/main/res/values/strings.xml`: ```xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="expo_custom_value" translatable="false">I Love Expo</string> </resources> ``` This overrides the default empty value defined in the module with the user's custom value.

Config plugin serialization requirement

Config plugins must be synchronous. Their return value must be serializable, except for any `mods` that are added.

Inline modules

Inline modules are native modules and views (Kotlin and Swift) created directly inside an Expo project's app directory without requiring a separate package or create-expo-module scaffolding. Kotlin and Swift files are written alongside app code, and Expo discovers them automatically and includes them in the build.

expo-secure-store config plugin for NSFaceIDUsageDescription

expo-secure-store added a config plugin to automatically set NSFaceIDUsageDescription on iOS.

expo-sharing config plugin for receiving shared data

expo-sharing includes a config plugin for receiving data from other apps.

expo-camera barcode scanner can be disabled

expo-camera allows disabling barcode scanner functionality via config plugin.

expo-font config plugin for font linking

expo-font added config plugin to allow fonts to be linked at build time.

Give your agent this brain