The Shared tab is where you define technical settings that apply across your whole plugin, rather than to a single element or action. This covers dependencies, code you want injected into the pages of apps that use your plugin, extra keys, shared assets, and the React Native libraries available to mobile plugins.
Dependencies
Dependencies are the shared building blocks your plugin relies on to run.
What is a dependency?
What is a dependency?
A dependency is external code that your own code needs in order to work. Instead of writing everything from scratch, you rely on code someone else has already written and tested, and your plugin "depends on" it being available. A plugin that shows a chart, for example, might depend on a charting library that does the actual drawing.
Bubble plugin API version
The Bubble plugin API version sets which version of Bubble's plugin API your plugin runs against. Each version introduces changes to how plugins behave, and you can see what changed in each one by clicking Show changelog.
We recommend using the latest version, since it includes the most recent improvements and fixes. If you're maintaining an older plugin, though, be aware that moving up a version may require changes to your code, so review the changelog before switching.
Include jQuery 3
Check Include jQuery 3 in apps using this plugin if you're building an element that relies on jQuery 3. When checked, the API gives you access to jQuery.
What is jQuery?
What is jQuery?
jQuery is a long-established JavaScript library that makes it simpler to find, change, and animate elements on a web page. Many older web plugins were built with it, which is why Bubble lets you opt in to including it.
HTML header
The HTML header lets you add code to the <head> section of every page in an app that uses your plugin. This is common for services like analytics tools, which usually need a snippet present on all pages to work.
What is the HTML header?
What is the HTML header?
An HTML page is split into a <head> and a <body>. The body holds what you see on screen, while the head holds behind-the-scenes information and code that the page needs to load, like scripts and styling. Code placed in the head runs on every page it's included on.
To let the people using your plugin supply their own values, like an API key or a tracking code, wrap a dynamic value in the sequence _*_NAME_*_. That value then appears as a key in the Plugins tab of any app using your plugin, and Bubble replaces it with the actual value in run mode.
The only valid header tags are <script>, <meta>, and <link>. Any other tag ends up in the body instead, because of automatic repair logic in most modern browsers.
When a browser like Chrome parses your page and finds an invalid tag in the header, it assumes the closing </head> tag was left out by mistake and moves the tag into the body automatically.
Additional keys
Authentication keys defined in your API calls are added automatically, so you don't need to re-enter them here. Use the Additional keys section to expose any extra keys your elements or actions need. Once defined, these keys are available in the context object that's passed to all the functions in your elements and actions.
What is the context object?
What is the context object?
The context object is a bundle of information Bubble passes into your plugin's code each time one of its functions runs. It carries things your code may need, such as key values and helper utilities, so they're available wherever you need them.
Shared assets and resources
The Shared assets and resources section lets you upload files your plugin code references at run time, such as logos, fonts, or fixtures. Uploaded files are hosted on Bubble's CDN, so they load quickly, and their URLs stay stable across plugin versions, so links in your code won't break when you publish an update.
What is a CDN?
What is a CDN?
A CDN (content delivery network) is a group of servers spread around the world that store copies of files. When someone loads your app, the files come from a server near them rather than one central location, which makes them load faster.
Mobile libraries
If you're building a mobile plugin, you have access to a set of React Native libraries that Bubble has already installed. These give you native components and APIs to build with, so you can reach device features and native functionality directly from your plugin. You can reference any of them in your plugin's code and test them on BubbleGo out of the box.
You'll only see the mobile libraries section once you've added a mobile element or action to your plugin.
Using a library isn't required. You can write plain React Native to build more generic elements and actions that don't rely on any external libraries or APIs. The libraries are there when you need native functionality, not something you have to reach for every time.
This list is subject to change. The most up-to-date version is always shown in the plugin editor.
Available React Native libraries
If your plugin asks for a different version of a library than the one Bubble has installed, Bubble uses its own installed version instead. If the two versions differ significantly, this can cause bugs, so it's worth building against the versions listed here.
"@bbob/preset-react": "^4.2.0", "@bbob/react": "^4.2.0", "@expo/metro-runtime": "~55.0.6", "@gorhom/bottom-sheet": "^5.2.8", "@gorhom/portal": "^1.0.14", "@microsoft/react-native-clarity": "^4.2.2", "@react-native-community/audio-toolkit": "^2.0.3", "@react-native-community/datetimepicker": "8.6.0", "@react-native-community/netinfo": "11.5.2", "@react-navigation/bottom-tabs": "^7.8.9", "@react-navigation/elements": "^2.8.5", "@react-navigation/native": "^7.1.22", "@react-navigation/native-stack": "^7.8.3", "@sentry/react-native": "~7.11.0", "@shopify/flash-list": "2.0.2", "browserify-zlib": "^0.2.0", "crypto-browserify": "^3.12.0", "expo": "~55.0.7", "expo-asset": "~55.0.9", "expo-audio": "~55.0.14", "expo-auth-session": "~55.0.8", "expo-blur": "~55.0.10", "expo-camera": "~55.0.10", "expo-clipboard": "~55.0.9", "expo-constants": "~55.0.8", "expo-crypto": "~55.0.10", "expo-document-picker": "~55.0.9", "expo-file-system": "~55.0.11", "expo-iap": "^3.4.10", "expo-image": "~55.0.6", "expo-image-manipulator": "~55.0.11", "expo-image-picker": "~55.0.13", "expo-linear-gradient": "~55.0.9", "expo-linking": "~55.0.7", "expo-location": "~55.1.3", "expo-media-library": "~55.0.10", "expo-notifications": "~55.0.13", "expo-secure-store": "~55.0.9", "expo-sharing": "~55.0.19", "expo-splash-screen": "~55.0.11", "expo-status-bar": "~55.0.4", "expo-updates": "~55.0.14", "expo-video": "~55.0.11", "expo-web-browser": "~55.0.10", "fast-text-encoding": "^1.0.6", "path-browserify": "^1.0.1", "react": "19.2.0", "react-dom": "19.2.0", "react-native": "0.83.2", "react-native-gesture-handler": "~2.30.0", "react-native-localize": "^3.5.1", "react-native-maps": "1.27.2", "react-native-mmkv": "^4.2.0", "react-native-modal-datetime-picker": "^18.0.0", "react-native-nitro-modules": "^0.35.0", "react-native-reanimated": "4.2.1", "react-native-redash": "^18.1.1", "react-native-safe-area-context": "^5.6.2", "react-native-screens": "~4.23.0", "react-native-svg": "15.15.3", "react-native-web": "~0.21.0", "react-native-webview": "13.16.0", "react-native-worklets": "0.7.2", "rn-fetch-blob": "^0.12.0", "stream-browserify": "^3.0.0"
Adding additional libraries
Beyond the built-in libraries, you can import additional React Native libraries into your plugin. Declare the library in the Additional libraries section using the same JSON shape as the built-in list: the library name as the key, and the version as the value.
{
"expo-contacts": "~57.0.4"
}
This works the same way as declaring a dependency in a package.json file. Once you've added a library, you'll need a development build to test an app that uses your plugin, since the library has to be compiled into the app.
Version conflicts
A mobile plugin can declare a third-party library at a specific version. Since an app can have several plugins installed, two plugins might declare the same library at different versions. When that happens, only one version can load, an app can't run multiple versions of the same library at once.
Bubble resolves this in a set order:
If Bubble already has the library installed, that version is used.
If Bubble doesn't have it installed, the newest declared version is used.
Because of this, a plugin that expects an older version of a library may not work as expected when a newer version ends up being the one that loads.
If you run into a conflict, the practical step is to reach out to the plugin's developer, since resolving it usually means aligning on a compatible version.
Testing
Bubble's web preview runs on React Native for web, so not every plugin can be tested there, depending on compatibility. If your plugin uses a feature web preview can't run, like opening the device camera, test it on a device instead. BubbleGo covers plugins that only use Bubble's built-in libraries; for any other library, use a development build.
Native configuration
Some libraries need access to device features, like contacts, the camera, or location. On both iOS and Android, an app has to declare up front which of these features it intends to use, or the app store will reject it and the feature won't work on the device. The Native configuration section is where you make those declarations for the libraries your plugin uses: plist keys on iOS, and manifest entries on Android. The people using your plugin can override these values before they build their app.
If a permission is already handled by the editor, it isn't requested again. For example, if the editor already offers camera access, a plugin that uses a camera library won't prompt the user for it a second time.
Why do I have to declare device permissions?
Why do I have to declare device permissions?
Both iOS and Android protect sensitive device features (contacts, camera, location, and so on) behind permissions. Before an app can use one, it has to declare its intent to do so in a specific place: a file called Info.plist on iOS, and the Android manifest on Android. If a library your plugin uses touches one of these features, the declaration has to be there, even if the app only uses that feature occasionally. Without it, Apple or Google will reject the app during review, or it will crash when it reaches the feature.
iOS plist entries
On iOS, each protected feature has a matching plist key, and every key you add needs a description string, known as a purpose string. This string is shown to the user in the system permission prompt, so it should explain clearly why the app needs access. For a plugin that reads contacts, for example, you'd add the NSContactsUsageDescription key with a description like "Lets you find and invite people from your contacts."
The description string isn't optional. Apple rejects apps that reference a protected feature without a purpose string for it, so make sure every plist entry your plugin's libraries need has a clear description.
To add one, select a plist key, enter a default description string, and click Add iOS entry.
What is a plist key?
What is a plist key?
A plist (property list) is a settings file that every iOS app carries, called Info.plist. It holds configuration the system reads before and while the app runs, including which protected features the app wants to use. Each protected feature has its own key, such as NSContactsUsageDescription for contacts or NSCameraUsageDescription for the camera.
External page: iOS plist keys (developer.apple.com)
Android manifest entries
On Android, permissions and other native settings are declared as entries in the app's manifest. You select an element type and enter its XML attributes.
The most common entry is a uses-permission element, which requests a single system permission. To request camera access, for example, you'd add a uses-permission element with the attribute android:name="android.permission.CAMERA", which produces:
<uses-permission android:name="android.permission.CAMERA" />
The manifest can hold other kinds of entries too, not just permissions, so some libraries may ask you to add a different element type with its own attributes.
To add one, select an element type, enter its attributes, and click Add Android entry.
What is the Android manifest?
What is the Android manifest?
The Android manifest (AndroidManifest.xml) is a file every Android app carries that tells the system essential facts about the app before it runs, including which permissions it needs and which device features it uses. Permissions are declared with a uses-permission element, where the android:name attribute names the specific permission, such as android.permission.CAMERA or android.permission.READ_CONTACTS.
External page: Android manifest <uses permission> (developer.android.com)
External page: Android manifest (introduction) (developer.android.com)
