# Expo Config Plugins
Expo Config Plugins is a collection of community-maintained configuration plugins for the Expo SDK's `npx expo prebuild` command. These plugins enable automatic native code configuration for popular React Native libraries that don't ship their own built-in Expo config plugins. The repository maintains a one-to-one mapping between native packages and their corresponding `@config-plugins/*` wrappers, ensuring seamless integration with the Expo managed workflow.
This monorepo contains plugins for WebRTC, Branch deep linking, Apple Settings UI, iOS stickers, Siri Shortcuts, PDF viewing, analytics (Adjust), VoIP (CallKeep), Bluetooth utilities, and dynamic app icons. Each plugin handles platform-specific native configuration including permissions, build settings, and required dependencies. The plugins require custom native code and cannot be used in the Expo Go app—they are designed for development builds generated via `npx expo prebuild`.
## @config-plugins/react-native-webrtc
Automatically configures `react-native-webrtc` for real-time communication features including video/audio calls. The plugin handles iOS permission strings, disables Bitcodes, and configures Android permissions and build settings including minimum API level 24.
```json
// app.json
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-webrtc",
{
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera for video calls",
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone for audio calls"
}
]
]
}
}
```
```sh
# Installation
npx expo install react-native-webrtc @config-plugins/react-native-webrtc
npx expo prebuild
```
## @config-plugins/apple-settings
Generates custom Apple Settings UI panels using a React Native-like declarative API. The plugin creates `.plist` files and supports localization, nested pages, text fields, switches, sliders, and child panes.
```js
// app.config.js
const {
default: withAppleSettings,
TextField,
Switch,
Slider,
ChildPane,
Group,
Title,
} = require("@config-plugins/apple-settings");
module.exports = (config) => {
return withAppleSettings(config, {
Root: {
locales: {
en: { Name: "User Settings" },
es: { Name: "Configuración" },
},
page: {
PreferenceSpecifiers: [
TextField({
title: "Username",
key: "username_preference",
value: "",
keyboardType: "Alphabet",
autoCapitalize: "None",
autoCorrect: "No",
}),
Switch({
title: "Enable Notifications",
key: "notifications_preference",
value: true,
}),
Slider({
key: "volume_preference",
value: 0.5,
minimumValue: 0,
maximumValue: 1,
}),
ChildPane({
title: "Advanced",
}),
],
},
},
Advanced: {
page: {
PreferenceSpecifiers: [
Title({
title: "App Version",
key: "version_preference",
value: "1.0.0",
}),
],
},
},
});
};
```
```js
// Reading settings dynamically in your app
import React from "react";
import { Button, Settings, Text, View } from "react-native";
function useSetting(key) {
const [value, setValue] = React.useState(() => Settings.get(key));
React.useEffect(() => {
const callback = Settings.watchKeys(key, () => {
setValue(Settings.get(key));
});
return () => Settings.clearWatch(callback);
}, [key]);
return [value, (newValue) => {
Settings.set({ [key]: newValue });
setValue(newValue);
}];
}
export default function SettingsScreen() {
const [notifications, setNotifications] = useSetting("notifications_preference");
const [username] = useSetting("username_preference");
return (
Username: {username}
Notifications: {notifications ? "On" : "Off"}
);
}
```
## @config-plugins/react-native-branch
Configures Branch.io deep linking SDK with support for API keys, app domains, and universal link domains for attribution and deep link handling.
```json
// app.json
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-branch",
{
"apiKey": "key_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"iosAppDomain": "myapp.app.link",
"iosUniversalLinkDomains": [
"myapp.app.link",
"myapp-alternate.app.link",
"myapp.test-app.link"
]
}
]
]
}
}
```
```sh
# Installation
npx expo install react-native-branch @config-plugins/react-native-branch
npx expo prebuild
```
## @config-plugins/ios-stickers
Creates iOS iMessage sticker packs with configurable icons, layouts, and sticker assets. Supports local files, remote URLs, and accessibility labels.
```json
// app.json
{
"expo": {
"plugins": [
[
"@config-plugins/ios-stickers",
{
"name": "My Stickers",
"icon": "./assets/imessage-icon.png",
"stickerBundleId": "com.myapp.stickers",
"columns": 4,
"stickers": [
"./assets/stickers/happy.png",
"./assets/stickers/sad.png",
{
"image": "./assets/stickers/custom.png",
"name": "Custom Sticker",
"accessibilityLabel": "A custom sticker for messages"
},
"https://example.com/remote-sticker.png"
]
}
]
]
}
}
```
## @config-plugins/react-native-dynamic-app-icon
Enables runtime app icon switching on iOS. Icons can be specified as local paths, remote URLs, or detailed objects with prerendering options.
```json
// app.json - Array format (icons named '0', '1', '2', etc.)
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-dynamic-app-icon",
[
"./assets/icons/default.png",
"./assets/icons/dark.png",
"./assets/icons/holiday.png"
]
]
]
}
}
```
```json
// app.json - Object format (custom icon names)
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-dynamic-app-icon",
{
"Default": {
"image": "./assets/icons/default.png",
"prerendered": true
},
"DarkMode": {
"image": "./assets/icons/dark.png",
"prerendered": true
},
"Holiday": {
"image": "https://example.com/holiday-icon.png",
"prerendered": false
}
}
]
]
}
}
```
```js
// Usage in app
import AppIcon from "react-native-dynamic-app-icon";
// Switch to dark mode icon
AppIcon.setAppIcon("DarkMode");
// Or with array format
AppIcon.setAppIcon("1");
```
## @config-plugins/react-native-siri-shortcut
Configures Siri Shortcuts integration by registering shortcut identifiers in the Xcode project for voice-activated app features.
```json
// app.json
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-siri-shortcut",
[
"com.myapp.StartWorkout",
"com.myapp.LogMeal",
"com.myapp.CheckProgress"
]
]
]
}
}
```
```sh
# Installation
npx expo install react-native-siri-shortcut @config-plugins/react-native-siri-shortcut
npx expo prebuild
```
## @config-plugins/react-native-adjust
Configures Adjust mobile analytics SDK with support for Android 12+ advertising ID, SDK signature, and Meta install referrer tracking.
```json
// app.json - Basic configuration
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-adjust",
{
"targetAndroid12": true
}
]
]
}
}
```
```json
// app.json - Full configuration with SDK signature and Meta referrer
{
"expo": {
"plugins": [
[
"@config-plugins/react-native-adjust",
{
"targetAndroid12": true,
"metaInstallReferrer": true,
"sdkSignature": {
"android": "./adjust-signature.aar",
"ios": "./AdjustSigSdk.xcframework"
}
}
]
]
}
}
```
## @config-plugins/react-native-pdf
Configures native PDF rendering capabilities. Requires `react-native-blob-util` as a dependency for Android file handling.
```json
// app.json
{
"expo": {
"plugins": [
"@config-plugins/react-native-blob-util",
"@config-plugins/react-native-pdf"
]
}
}
```
```sh
# Installation (both plugins required)
npx expo install react-native-pdf react-native-blob-util \
@config-plugins/react-native-pdf @config-plugins/react-native-blob-util
npx expo prebuild
```
```js
// Alternative: Display PDF via WebBrowser (no native code required)
import * as WebBrowser from "expo-web-browser";
const openPDF = () => {
WebBrowser.openBrowserAsync("https://example.com/document.pdf");
};
// Alternative: Display PDF via WebView
import { WebView } from "react-native-webview";
const PDFViewer = ({ uri }) => (
);
```
## @config-plugins/react-native-callkeep
Configures VoIP call integration for native call UI on both iOS and Android, enabling apps to display incoming calls on the lock screen.
```json
// app.json
{
"expo": {
"plugins": ["@config-plugins/react-native-callkeep"]
}
}
```
```sh
# Installation
npx expo install react-native-callkeep @config-plugins/react-native-callkeep
npx expo prebuild
```
## @config-plugins/react-native-blob-util
Android-only plugin that configures file system access for blob/binary data handling. Required as a dependency for `react-native-pdf`.
```json
// app.json
{
"expo": {
"plugins": ["@config-plugins/react-native-blob-util"]
}
}
```
```sh
# Installation
npx expo install react-native-blob-util @config-plugins/react-native-blob-util
npx expo prebuild
```
---
The primary use cases for these config plugins include: building real-time communication apps with WebRTC video/audio calls, implementing deep linking and attribution with Branch.io, creating customizable iOS Settings panels, adding iMessage sticker extensions, enabling dynamic app icon switching for seasonal themes or user preferences, integrating Siri voice shortcuts, displaying PDF documents natively, tracking mobile analytics with Adjust, and handling VoIP calls with native call UI.
Integration follows a consistent pattern across all plugins: install the native library and its corresponding config plugin via `npx expo install`, add the plugin to the `plugins` array in `app.json` or `app.config.js` with any required configuration options, then run `npx expo prebuild` to generate the native code. Each plugin version is tied to specific Expo SDK versions (documented in versioning tables), so ensure compatibility when upgrading. These plugins cannot be used with Expo Go—they require development builds or standalone app builds.