or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

android-config.mdandroid-plugins.mdcore-plugin-system.mdindex.mdios-config.mdios-plugins.mdmod-system.mdutilities.md
tile.json

ios-plugins.mddocs/

iOS Platform Plugins

High-level plugins for modifying iOS project files including Info.plist, entitlements, Xcode project configuration, and AppDelegate files. These plugins provide convenient interfaces for common iOS development tasks.

Info.plist Plugins

withInfoPlist

Modify the Info.plist file with structured property list manipulation.

function withInfoPlist(
  config: ExpoConfig,
  action: Mod<InfoPlist>
): ExpoConfig;

Usage:

config = withInfoPlist(config, (config) => {
  const infoPlist = config.modResults;
  
  // Set app display name
  infoPlist.CFBundleDisplayName = "My Custom App";
  
  // Add URL schemes
  infoPlist.CFBundleURLTypes = [
    {
      CFBundleURLName: "com.example.myapp",
      CFBundleURLSchemes: ["myapp", "mycustomscheme"]
    }
  ];
  
  return config;
});

createInfoPlistPlugin

Helper for creating Info.plist modification plugins.

function createInfoPlistPlugin(
  action: (expo: ExpoConfig, infoPlist: InfoPlist) => Promise<InfoPlist> | InfoPlist,
  name?: string
): ConfigPlugin;

createInfoPlistPluginWithPropertyGuard

Create an Info.plist plugin with property conflict detection.

function createInfoPlistPluginWithPropertyGuard(
  action: (expo: ExpoConfig, infoPlist: InfoPlist) => Promise<InfoPlist> | InfoPlist,
  settings: {
    infoPlistProperty: string;
    expoConfigProperty: string;
    expoPropertyGetter?: (config: ExpoConfig) => string;
  },
  name?: string
): ConfigPlugin;

Entitlements Plugins

withEntitlementsPlist

Modify the app's entitlements file for capabilities and permissions.

function withEntitlementsPlist(
  config: ExpoConfig,
  action: Mod<Plist>
): ExpoConfig;

Usage:

config = withEntitlementsPlist(config, (config) => {
  const entitlements = config.modResults;
  
  // Enable associated domains
  entitlements["com.apple.developer.associated-domains"] = [
    "applinks:example.com",
    "webcredentials:example.com"
  ];
  
  // Enable keychain access groups
  entitlements["keychain-access-groups"] = [
    "$(AppIdentifierPrefix)com.example.myapp"
  ];
  
  return config;
});

withExpoPlist

Modify the Expo.plist file for Expo Updates configuration.

function withExpoPlist(
  config: ExpoConfig,
  action: Mod<Plist>
): ExpoConfig;

Xcode Project Plugins

withXcodeProject

Modify the Xcode project file (.pbxproj) for build settings and configurations.

function withXcodeProject(
  config: ExpoConfig,
  action: Mod<XcodeProject>
): ExpoConfig;

Usage:

config = withXcodeProject(config, (config) => {
  const xcodeProject = config.modResults;
  
  // Add build setting
  const configurations = xcodeProject.pbxXCBuildConfigurationSection();
  Object.keys(configurations).forEach(key => {
    const configuration = configurations[key];
    if (configuration.buildSettings) {
      configuration.buildSettings.CUSTOM_FLAG = "YES";
      configuration.buildSettings.OTHER_LDFLAGS = [
        "$(inherited)",
        "-framework CustomFramework"
      ];
    }
  });
  
  return config;
});

Source Code Plugins

withAppDelegate

Modify the AppDelegate.m or AppDelegate.swift file.

function withAppDelegate(
  config: ExpoConfig,
  action: Mod<AppDelegateProjectFile>
): ExpoConfig;

Usage:

config = withAppDelegate(config, (config) => {
  const appDelegate = config.modResults;
  
  // Add import
  if (!appDelegate.contents.includes("#import <CustomSDK/CustomSDK.h>")) {
    appDelegate.contents = appDelegate.contents.replace(
      /#import "AppDelegate\.h"/,
      `#import "AppDelegate.h"
#import <CustomSDK/CustomSDK.h>`
    );
  }
  
  // Add initialization code
  const initCode = `  [CustomSDK initializeWithKey:@"your-key"];`;
  if (!appDelegate.contents.includes(initCode)) {
    appDelegate.contents = appDelegate.contents.replace(
      /- \(BOOL\)application:\(UIApplication \*\)application didFinishLaunchingWithOptions:\(NSDictionary \*\)launchOptions\s*{/,
      `- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
${initCode}`
    );
  }
  
  return config;
});

Podfile Plugins

withPodfileProperties

Modify Podfile properties for CocoaPods configuration.

function withPodfileProperties(
  config: ExpoConfig,
  action: Mod<Record<string, string>>
): ExpoConfig;

Usage:

config = withPodfileProperties(config, (config) => {
  const properties = config.modResults;
  
  // Set iOS deployment target
  properties["ios.deploymentTarget"] = "12.0";
  
  // Enable modular headers
  properties["ios.useModularHeaders"] = "true";
  
  return config;
});

withPodfile (Deprecated)

Legacy Podfile modification plugin - use withPodfileProperties instead.

function withPodfile(
  config: ExpoConfig,
  action: Mod<PodfileProjectFile>
): ExpoConfig;

Helper Types

interface InfoPlist extends Record<string, JSONValue | undefined> {
  UIStatusBarHidden?: boolean;
  UIStatusBarStyle?: string;
  UILaunchStoryboardName?: string | "SplashScreen";
  CFBundleShortVersionString?: string;
  CFBundleVersion?: string;
  CFBundleDisplayName?: string;
  CFBundleIdentifier?: string;
  CFBundleName?: string;
  CFBundleURLTypes?: URLScheme[];
  CFBundleDevelopmentRegion?: string;
  ITSAppUsesNonExemptEncryption?: boolean;
  LSApplicationQueriesSchemes?: string[];
  UIBackgroundModes?: string[];
  UISupportedInterfaceOrientations?: InterfaceOrientation[];
  UISupportedInterfaceOrientationsIPhone?: InterfaceOrientation[];
  UISupportedInterfaceOrientationsIPad?: InterfaceOrientation[];
  UIRequiredDeviceCapabilities?: string[];
  NSAppTransportSecurity?: Record<string, any>;
  NSLocationWhenInUseUsageDescription?: string;
  NSLocationAlwaysAndWhenInUseUsageDescription?: string;
  NSCameraUsageDescription?: string;
  NSMicrophoneUsageDescription?: string;
  NSPhotoLibraryUsageDescription?: string;
}

interface URLScheme {
  CFBundleURLName?: string;
  CFBundleURLSchemes: string[];
}

type InterfaceOrientation =
  | "UIInterfaceOrientationPortrait"
  | "UIInterfaceOrientationPortraitUpsideDown"
  | "UIInterfaceOrientationLandscapeLeft"
  | "UIInterfaceOrientationLandscapeRight";

interface AppDelegateProjectFile {
  path: string;
  contents: string;
  language: "objc" | "swift";
}

interface PodfileProjectFile {
  path: string;
  contents: string;
}

type Plist = Record<string, any>;

type XcodeProject = any; // From 'xcode' package

Usage Examples

Complete iOS Setup Plugin

import { 
  withInfoPlist, 
  withEntitlementsPlist, 
  withXcodeProject, 
  withAppDelegate,
  IOSConfig,
  ConfigPlugin 
} from "@expo/config-plugins";

const withCompleteiOSSetup: ConfigPlugin<{
  appName: string;
  bundleId: string;
  urlScheme: string;
  framework: string;
}> = (config, { appName, bundleId, urlScheme, framework }) => {
  // Update Info.plist
  config = withInfoPlist(config, (config) => {
    const infoPlist = config.modResults;
    
    infoPlist.CFBundleDisplayName = appName;
    infoPlist.CFBundleIdentifier = bundleId;
    infoPlist.CFBundleURLTypes = [
      {
        CFBundleURLName: bundleId,
        CFBundleURLSchemes: [urlScheme]
      }
    ];
    
    return config;
  });
  
  // Setup entitlements
  config = withEntitlementsPlist(config, (config) => {
    const entitlements = config.modResults;
    
    entitlements["com.apple.developer.associated-domains"] = [
      `applinks:${urlScheme}.com`
    ];
    
    return config;
  });
  
  // Configure Xcode project
  config = withXcodeProject(config, (config) => {
    const xcodeProject = config.modResults;
    
    // Add framework
    xcodeProject.addFramework(`${framework}.framework`);
    
    return config;
  });
  
  // Modify AppDelegate
  config = withAppDelegate(config, (config) => {
    const appDelegate = config.modResults;
    
    // Add import
    const importLine = `#import <${framework}/${framework}.h>`;
    if (!appDelegate.contents.includes(importLine)) {
      appDelegate.contents = appDelegate.contents.replace(
        /#import "AppDelegate\.h"/,
        `#import "AppDelegate.h"\n${importLine}`
      );
    }
    
    return config;
  });
  
  return config;
};

Privacy Permissions Setup

const withPrivacyPermissions: ConfigPlugin<{
  locationUsage?: string;
  cameraUsage?: string;
  microphoneUsage?: string;
}> = (config, { locationUsage, cameraUsage, microphoneUsage }) => {
  return withInfoPlist(config, (config) => {
    const infoPlist = config.modResults;
    
    if (locationUsage) {
      infoPlist.NSLocationWhenInUseUsageDescription = locationUsage;
      infoPlist.NSLocationAlwaysAndWhenInUseUsageDescription = locationUsage;
    }
    
    if (cameraUsage) {
      infoPlist.NSCameraUsageDescription = cameraUsage;
    }
    
    if (microphoneUsage) {
      infoPlist.NSMicrophoneUsageDescription = microphoneUsage;
    }
    
    return config;
  });
};

Advanced Xcode Configuration

const withAdvancedXcodeConfig: ConfigPlugin = (config) => {
  return withXcodeProject(config, (config) => {
    const xcodeProject = config.modResults;
    
    // Get build configurations
    const configurations = xcodeProject.pbxXCBuildConfigurationSection();
    
    Object.keys(configurations).forEach(key => {
      const configuration = configurations[key];
      if (configuration.buildSettings) {
        // Set deployment target
        configuration.buildSettings.IPHONEOS_DEPLOYMENT_TARGET = "12.0";
        
        // Enable bitcode
        configuration.buildSettings.ENABLE_BITCODE = "YES";
        
        // Add compiler flags
        configuration.buildSettings.OTHER_CFLAGS = [
          "$(inherited)",
          "-DCUSTOM_FLAG=1"
        ];
        
        // Add linker flags
        configuration.buildSettings.OTHER_LDFLAGS = [
          "$(inherited)",
          "-framework CustomFramework",
          "-lc++"
        ];
      }
    });
    
    return config;
  });
};