> For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://manual.bubble.io/account-and-marketplace/building-plugins/building-elements.md).

# Building elements

<details>

<summary>System hard limits</summary>

When creating plugins for Bubble, it's important to be mindful of Bubble's hard system limits. These constraints for plugin development mirror those in general Bubble development. The article below covers this subject:

Article: Hard limits

</details>

Building elements is one of the main things Bubble plugins let you do. You write the element's code, and the people using your plugin add it to their pages through the visual editor, display dynamic data with it, and so on. Web elements are written in JavaScript, and mobile elements in React Native.

Building an element means being comfortable with how elements work in Bubble and the different field types they can use, along with some coding knowledge: JavaScript and web development for web elements, React Native for mobile. If you need guidance, it's worth asking on the forum. You can see a simple implementation [here](https://bubble.io/plugin_editor?id=1487181547537x364191731148390400\&tab=tabs-4).

{% hint style="info" %}
Different parts of a plugin have different character limits, depending on where they appear in the UI. Preview your plugin before publishing to make sure everything looks the way you want.
{% endhint %}

## Adding elements to a plugin

A plugin can offer any number of elements. Click **New** to add one, and switch between elements by selecting the relevant element or subsection in the left panel.

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2FJymLfEG0BXYg4pq4RGS4%2Fadd-element-plugin-editor.png?alt=media&amp;token=1dc502f2-4978-4af3-bff5-82f283dcf21c" alt=""><figcaption></figcaption></figure>

### Web and mobile elements

When you add an element, you choose its platform: web or mobile. A single plugin can contain both web and mobile elements, but each individual element is one platform only, since the two are built on different underlying code. Your choice here determines which code editor you'll use further down, covered in the *Code* section below.

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2F71tSwpkIwrTDbI7lvSIH%2Felement-platform-type.png?alt=media&amp;token=3ad40456-85ae-4527-b26e-24291bbee5a4" alt="Selecting the platform to which the element will belong: web or mobile."><figcaption><p>You choose an element's platform when the element is created.</p></figcaption></figure>

## Testing a plugin

Test your elements in both the editor and run mode. You'll use edit mode to see how the element property editor renders, and mostly run mode to test your code.

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2FpjpBzpNLCVqRlOwouSEE%2Ftest-app-plugin-editor.png?alt=media&amp;token=113d8b96-3df0-42c5-a4f3-9fa876989358" alt=""><figcaption></figcaption></figure>

To test a plugin, add an app to your plugin, then click the test button. If the plugin isn't already installed in your test app, it's added automatically. It's a good habit to keep the test app open. Clicking **Go to test app** refreshes the existing tab and fetches the latest version of your plugin.

## Building the element

### Defining general properties

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2FSlvpSNUC4t8ny96Y42pV%2Fplugin-element-properties.png?alt=media&amp;token=3f3f473c-a35f-48fb-acab-f1f7694bc2bb" alt=""><figcaption></figcaption></figure>

The first thing to do when building an element is define the edit mode properties that control how it behaves in the editor. You'll pick a name, a category, an icon, and a placeholder image. (The element's code can't run in the editor, so the placeholder image is what represents it there.)

Next, you'll choose the properties that apply to the element and define the fields the user fills in when they use it. You can start with Bubble's standard properties for simple CSS options: background, dimensions, borders, and so on, which apply to the outer div. These are optional, and you can build an element without them, with one exception: if you want the element to be resizable, you'll need to select the *Resizable* option.

{% hint style="warning" %}
When loading fonts from a source other than Google Webfonts, the library Bubble uses appends the `font_face` property with the suffix `:::custom` rather than the font family name.
{% endhint %}

### Defining fields

A field is a property the user fills in through the element property editor. Each field has a name, a caption, and an editor type.

You have several choices for the editor type:

<table data-search="false"><thead><tr><th width="166.87109375">Editor type</th><th>Description</th></tr></thead><tbody><tr><td>Static text, static number</td><td>A simple input where users type a value.</td></tr><tr><td>Checkbox</td><td>A checkbox that returns true or false in run mode.</td></tr><tr><td>Color</td><td>A color picker. The value is the RGBA code of the color.</td></tr><tr><td>Dropdown</td><td>A set of options for the user to choose from. Enter the options separated by commas in the input that follows.</td></tr><tr><td>Static image</td><td>Lets the user upload an image.</td></tr><tr><td>Dynamic value</td><td>Shows a control where the user builds a dynamic expression using the Bubble composer. You define which data type the control expects (text, number, address, and so on), and it can return a list if you check the relevant box.</td></tr><tr><td>App type</td><td>Lets the user define which data type your element works with. For a map element, for example, you might have a <em>Type of markers</em> field, and the user picks one of their own types. You can then add fields that prompt the user to pick a field within that type, such as which field holds the address, and restrict those to a specific field type so only addresses show.</td></tr></tbody></table>

A field can be optional, so it isn't flagged as missing in the element property editor. A field can also be marked *In style*: when checked, it's included when a user defines a style for your element in the Bubble editor. Styling options like colors typically go in styles, while data sources don't.

### Defining states

States let you expose data from your element to other elements and actions in the application editor. An input can have a value, a map can have a selected marker, and so on. Your code is responsible for keeping each state set to the right value, but you need to declare the states you want to expose. For each one, you define its data type so Bubble knows how to interpret the value in the editor.

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2FLJCn486on9iaWkA8wxKK%2Felement-exposed-states.png?alt=media&amp;token=3d488c7f-e14d-4446-95aa-afd65dcd5b6b" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
States defined in plugin elements run initialization code that's evaluated with all dynamic properties for that element. If you have a conditional plugin-defined (non-Bubble) property that depends on that element's own value, it creates a circular dependency error.

Until a fix is released, you can avoid this by initializing the plugin element state in the element's init code instead, for example: `instance.publishState(state_id, initial_value)`
{% endhint %}

### Events and actions

Events and actions are how your element triggers a workflow and how the user's workflows modify it.

Events are triggered by your element. For your element to trigger a workflow, like a click, you declare the events it can trigger so Bubble can populate the relevant list in the *Workflow* tab. Your code is then responsible for triggering the event.

Actions are applied to your element, such as resetting a map to hide all markers. As with events, the action itself is defined in code, but you declare the action names and the fields that apply to each one. Defining these fields works the same way as defining the element's fields.

### Code

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2FKMSNghGhbJap1jdLwjv5%2Fplugin-code.png?alt=media&amp;token=2058af14-4008-46d8-be25-684d03ced2cc" alt="The Code tab for a web plugin element, showing the initialize and update JavaScript functions and the instance and context reference documentation beside them."><figcaption><p>A <strong>web element's code</strong>, defined with separate initialize and update functions written in JavaScript.</p></figcaption></figure>

<figure><img src="https://34394582-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M5sbzwG7CljeZdkntrL%2Fuploads%2F2PH62gX98hI2hPouq8Vk%2Freact-native-code-editor-plugins.png?alt=media&amp;token=37394c0b-8b61-4cc5-a1d3-a811e16b158f" alt="The Code tab for a mobile plugin element, showing a single React Native component function written in JSX, plus a preview function below it."><figcaption><p>A <strong>mobile element's code</strong>, defined as a single React Native component function.</p></figcaption></figure>

Once these pieces are defined, you can write the element's code at the bottom of the editor. For each function, you'll see a code editor alongside contextual documentation showing the objects you can access. The `instance` object represents the element, while the `context` object gives you access to utilities like the current user and a function to upload files.

How you write the code depends on the element's platform.

* **Web elements** are defined by a few functions. The `initialize` function runs once per instance, as soon as the element is visible on the page. The `update` function runs whenever one of the element's properties changes, so it can run many times. Your code should track what changed to avoid unnecessary work. Actions are represented by a run action. For more, see loading and asynchronous versus synchronous code.
* **Mobile elements** use the React Native text editor. Instead of the web element's `initialize` and `update` functions, you write a single `component` function, which is interpreted as a React Native functional component. You also define a `preview` function, which renders a preview of your element in the editor. Any actions on the element are written as separate functions, the same as they are for web.

{% hint style="info" %}
When building a mobile element, refer to the inline documentation for details on the mobile element API.
{% endhint %}

When testing your functions, you can add a debugger point so execution stops when you run it with the debugger on and the web inspector open. This lets you step through your custom code click by click.
