# @end #
platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
target 'yolo27' do
  use_expo_modules!
  # ...
  # podfile_properties['your_property']
end
```
Generally, you should only interact with the Podfile via Expo [Autolinking](/more/glossary-of-terms/#autolinking), this provides a programmatic interface with the project files.
### Custom base modifiers
The Expo CLI `npx expo prebuild` command uses [`@expo/prebuild-config`](https://github.com/expo/expo/tree/main/packages/%40expo/prebuild-config) to get the default base modifiers. These defaults only manage a subset of common files, if you want to manage custom files you can do that locally by adding new base modifiers.
For example, say you wanted to add support for managing the `ios/*/AppDelegate.h` file, you could do this by adding a `ios.appDelegateHeader` modifier.
> This example uses `tsx` for simple local TypeScript support, this isn't strictly necessary. [Learn more](/guides/typescript/#appconfigjs).
```ts withAppDelegateHeaderBaseMod.ts
import { ConfigPlugin, IOSConfig, Mod, withMod, BaseMods } from 'expo/config-plugins';
import fs from 'fs';
/**
 * A plugin which adds new base modifiers to the prebuild config.
 */
export function withAppDelegateHeaderBaseMod(config) {
  return BaseMods.withGeneratedBaseMods<'appDelegateHeader'>(config, {
    platform: 'ios',
    providers: {
      // Append a custom rule to supply AppDelegate header data to mods on `mods.ios.appDelegateHeader`
      appDelegateHeader: BaseMods.provider<IOSConfig.Paths.AppDelegateProjectFile>({
        // Get the local filepath that should be passed to the `read` method.
        getFilePath({ modRequest: { projectRoot } }) {
          const filePath = IOSConfig.Paths.getAppDelegateFilePath(projectRoot);
          // Replace the .m with a .h
          if (filePath.endsWith('.m')) {
            return filePath.substr(0, filePath.lastIndexOf('.')) + '.h';
          }
          // Possibly a Swift project...
          throw new Error(`Could not locate a valid AppDelegate.h at root: "${projectRoot}"`);
        },
        // Read the input file from the filesystem.
        async read(filePath) {
          return IOSConfig.Paths.getFileInfo(filePath);
        },
        // Write the resulting output to the filesystem.
        async write(filePath: string, { modResults: { contents } }) {
          await fs.promises.writeFile(filePath, contents);
        },
      }),
    },
  });
}
/**
 * (Utility) Provides the AppDelegate header file for modification.
 */
export const withAppDelegateHeader: ConfigPlugin<Mod<IOSConfig.Paths.AppDelegateProjectFile>> = (
  config,
  action
) => {
  return withMod(config, {
    platform: 'ios',
    mod: 'appDelegateHeader',
    action,
  });
};
// (Example) Log the contents of the modifier.
export const withSimpleAppDelegateHeaderMod = config => {
  return withAppDelegateHeader(config, config => {
    console.log('modify header:', config.modResults);
    return config;
  });
};
```
To use this new base mod, add it to the plugins array. The base mod **MUST** be added last after all other plugins that use the mod, this is because it must write the results to disk at the end of the process.
```js app.config.js
// Required for external files using TS
require('tsx/cjs');
import {
  withAppDelegateHeaderBaseMod,
  withSimpleAppDelegateHeaderMod,
} from './withAppDelegateHeaderBaseMod.ts';
export default ({ config }) => {
  if (!config.plugins) config.plugins = [];
  config.plugins.push(
    withSimpleAppDelegateHeaderMod,
    // Base mods MUST be last
    withAppDelegateHeaderBaseMod
  );
  return config;
};
```
For more info, see [the PR that adds support](https://github.com/expo/expo-cli/pull/3852) for this feature.
## expo install
When a node module is installed with the `npx expo install` command, if it includes a config plugin, it will be added to the project's app config automatically. This makes setup easier and helps prevent users from forgetting to add a plugin. However, this does come with a couple of caveats:
1. `npx expo install` only adds config plugins using the root **app.config.js** file automatically to the app manifest. This rule was added to prevent popular packages like `lodash` from being mistaken for a config plugin and breaking the prebuild.
2. There is currently no mechanism for detecting if a config plugin has mandatory props. Because of this, `expo install` will only add the plugin, and not attempt to add any extra props. For example, `expo-camera` has optional extra props, so `plugins: ['expo-camera']` is valid, but if it had mandatory props, then `expo-camera` would throw an error.
3. Plugins can only be automatically added when the user's project uses a static app config (**app.json** and **app.config.json**). If the user runs `expo install expo-camera` in a project with an **app.config.js**, they'll see a warning like:
```sh
Cannot automatically write to dynamic config at: app.config.js
Please add the following to your app config
{
  "plugins": [
    "expo-camera"
  ]
}
```


## Using patch-project

Learn about how to use patch-project to create generate, apply, and preserve native changes in your Expo project.

> **important** **Note**: `patch-project` is an alpha feature.
`patch-project` is an Expo config plugin and command-line interface (CLI) tool that generates and applies patches to preserve native changes after running `npx expo prebuild`. This tool is useful for native app developers who want to preserve customizations without needing to know how to write a config plugin, effectively generating an automatic solution that works with [Continuous Native Generation (CNG)](/workflow/continuous-native-generation/).
This guide explains how to use `patch-project`, when to use it, and its limitations.
## How patch-project works
`patch-project` uses an approach to generate and automatically apply patches, which is inspired by Git. Using this command line tool requires the following steps in your project:
### Installation
To get started, you need to install the tool in your project:
```sh
$ npx expo install patch-project
```
This command will automatically add the `patch-project` config plugin to your [app config](/workflow/configuration/):
```json app.json
{
  "expo": {
    "plugins": [
      "patch-project"
    ]
  }
}
```
### Generate patches from existing customizations
Let's assume you manually modified native directories (**android** and **ios**) in your project. To generate patches for these native directories, you can run the following command:
```sh
$ npx patch-project
```
> **info** **Note**: In scenarios where you want to generate patches for a specific platform, you can use the `--platform` option and run `npx patch-project --platform android` or `npx patch-project --platform ios`.
These patches, when generated, are saved in the **cng-patches** directory.
```
âââ ./
    âââ app.json  # with patch-project plugin
    âââ cng-patches/
    â   âââ android+eee880ad7b07965271d2323f7057a2b4.patch  # patch for android directory
    â   âââ ios+eee880ad7b07965271d2323f7057a2b4.patch  # patch for ios directory
    âââ package.json
    âââ ...  # other project files
```
Each file will be prefixed with a platform's name followed by a checksum value. For example:
```bash
ios+eee880ad7b07965271d2323f7057a2b4.patch
```
### Apply patches during prebuild
Once you have generated patches, they are automatically applied when subsequently running the `npx expo prebuild` command. The `patch-project` config plugin detects the existing patches and applies them to restore your customizations.
## When to use patch-project
You can use `patch-project` in the following scenarios:
- **Migrating existing React Native apps** that are complex because they contain extensive native customizations and re-creating these native customizations as config plugins would be time-consuming.
- **Preserving manual changes** made to **android** and/or **ios** directories while transitioning to adopt Continuous Native Generation (CNG) in your Expo project.
- **Quick prototyping** when you need to test native changes before writing config plugins.
- **Patches are applied automatically** when running the `npx expo prebuild` command subsequently. This is an advantage over tools like `patch-package` (commonly used for generating patches for npm libraries), which do not preserve and automatically apply patches during the prebuild process.
## Limitations and considerations
Patches may become invalid during Expo SDK version upgrades because:
- **Template and/or file structure changes**: The prebuild template evolves between SDK versions with new changes and file updates in native directories. This will affect the already generated diff in the **cng-patches** directory, which may no longer apply.
- **Plugin conflicts**: CNG patches can be dangerous and may break when other plugins modify the same files. For example, if you add a new plugin that updates **MainApplication.kt** and conflicts with your existing patches, the patches may no longer apply correctly. In such cases, you may need to regenerate patches.
- **iOS .pbxproj changes**: In iOS projects, applying patches to **.pbxproj** files can be fragile since this file contains UUIDs and running a command like `npx expo prebuild --clean` can change these IDs. For example, if you're adding a widget extension or making other project configuration changes, patch-based approaches may not work reliably. You can review the generated **cng-patches/ios-\*** and keep only the necessary patch. Having the patch as minimal as possible would reduce the risk of failures when applying patches.
It is recommended to regenerate patches after each SDK upgrade.