# Introduction

Welcome to openBuild

openBuild is a [framework](/introduction/the-framework) for building Bubble apps professionally. It is the result of years of Bubble design and development experience packed into a Bubble template.&#x20;

{% hint style="success" %}
Get the Bubble template here 👉 <https://bubble.io/template/openbuild-framework-1586724133568x174997519488516100>
{% endhint %}

{% hint style="danger" %}
The 2.0 version of the openBuild extension, designed to work with the latest responsive engine, is currently in closed beta testing. The current version of the extension only works with the legacy template, which was built on the old responsive engine. The updated version of the extension will be made available to the public soon.
{% endhint %}

openBuild is built on top of [Bubble](/core-concepts/bubble-vs-openbuild) and cannot be used as a standalone product.

{% hint style="info" %}
openBuild is a professional framework for Bubble.io. While its concepts are easy to understand and learn, it is not a beginner template.
{% endhint %}


# The Framework

The most flexible Bubble template for your next project

openBuild is a starter template for Bubble. It comes with different starting point pages, prebuilt navigation, an admin page, login/signup, profile settings, other useful reusable components, workflows and beautiful transactional emails.

The framework uses the Bubble new responsive engine with a smart design system, taking care of the bulk responsive work while you can focus on creating beautiful user interfaces.

This template has everything you need to build beautiful responsive, clean and scalable web applications.

1. Different app [Layouts](broken://pages/-M4dVflJRAUVQDqHLAl7)
2. [Responsive grid](broken://pages/-M4dc1YWvMRVC3MTcmvZ) compatible with openBuild Library
3. openBuild [styles](broken://pages/-M4dcCL1Xg6nZT1z9p7P)
4. [Option sets](broken://pages/-M4dfqTIvgpV_UwJGoND)
5. [Navigation](broken://pages/-M4deT3hJC8HLOHAIp-F) with workflows (including mobile navigation with hamburger menus and nav bar)
6. [Menus ](broken://pages/-M4i09OuK9kRFRhs1jVK)with workflows
7. [Login & Sign up](broken://pages/-M4deWZW4PlipAfxAx5n)
8. [Transactional email](broken://pages/-M4dehZeRjo9M_vW6gur)
9. [User Settings](broken://pages/-M4de_639YZ2fjlDkYia)
10. [Admin panel](broken://pages/-M4deeMQOudxhWx90ep1)
11. Workflows for creating and inviting users
12. [Reusable elements ](broken://pages/-M4dgA9zTMURl-LzKzJ2)


# The Library

Coming soon!


# Release Notes


# Bubble vs openBuild

How is openBuild different from Bubble?

openBuild is a framework for using Bubble. It is meant to help you build more structured and more easily than simply using ‘vanilla’ Bubble.

You can compare it best to CSS frameworks you may already be familiar with. Similarly, you can compare openBuild to UI builders for Wordpress.

> **For Wordpress there is Elementor and Divi. For CSS there is Bootstrap and Tailwind. For Bubble there is openBuild.**

On top of that, the openBuild Bubble template is full of best practices of having been used to build thousands of Bubble apps, all rolled into one powerful starting point for your next app!

Ultimately, openBuild is a thoughtful process for building responsively on Bubble as well as a vast library of components and widgets to help you build even faster. This process consists of the way we structure applications: many apps are single page. With openBuild we have a system in place to help you deal with navigating ‘pages’ within the page to create a single page app (SPA). It also helps you deal with data in a better way, making sure you never have too many data queries on your page, or duplicate a query reducing performance of your app.

{% hint style="info" %}
openBuild is a way of building responsively on Bubble as well as a vast library of style-matching components and widgets to help you build even faster.&#x20;
{% endhint %}


# Responsive Design

One structure to create 90% of all app and websites layouts, fully responsive.

The openBuild structure consists of 5 levels of containers, with their own specific rules making the framework to be responsive from small phone (320px) to 4K monitor. But don't worry, you only need to worry about one to build!

## Specifications

<table><thead><tr><th width="202">Element</th><th width="120">Container Type</th><th width="116">Min Width</th><th width="130">Padding</th><th width="174">Gap</th></tr></thead><tbody><tr><td><a href="#page">Page</a></td><td>Column</td><td>-</td><td>-</td><td></td></tr><tr><td><a href="#content-area">⃞     Content Area</a></td><td>Column</td><td>-</td><td>-</td><td></td></tr><tr><td><a href="#section">❖ Section</a></td><td>Column</td><td>-</td><td>-</td><td>20</td></tr><tr><td><a href="#row-container">▭ Row Container</a></td><td>Row</td><td>-</td><td>0 0 20 20</td><td>20</td></tr><tr><td><a href="#block">⧆ Block</a></td><td>Varies</td><td>280px</td><td>Varies</td><td>Varies</td></tr></tbody></table>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FVUcgNIgoba7biGyeBbH2%2FopenBuild%20-%20Framework%20structure.png?alt=media&amp;token=de02f1df-93ce-49e1-b985-bc07e55204e1" alt=""><figcaption><p>The Block element is where all the stuff in your app happens.</p></figcaption></figure>

### Page

This is a bubble page. By default we use Page as column and set up the UI width at 1280px.

![Width of the editor is 1280px.](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FMZ9qkQvf6X430yr2IBck%2Fimage.png?alt=media\&token=7896b226-5f7b-4359-bb22-d7b98838d64e)

### Content Area

A content area is the container holding all your sections. So it's basically holding all your page contents except your page navigation (Header, Left Menu, etc.). As the content area is located differently whether your page is with a left menu, a header or a right menu for example, its margins will be modified according to the page layout.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fp1u72PHMdpksyu8y7Y9u%2FopenBuild%20-%20Framework%20Layout.png?alt=media&amp;token=ecd42002-4661-421e-9d00-dc374ef4d9b6" alt=""><figcaption><p>Example of content area according to page layout</p></figcaption></figure>

### ❖ Section

A section is the container holding all your row containers. Depending on how you use your page (Single Page App (SPA) or website) a section has a different usage. In the case of a website page, think of the hero image of a site as a section, or the features area as a section. In the case of SPA, a section is used as a 'virtual' page that is hidden/shown depending the [navigation URL parameter](/working-with-the-framework/navigation).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F5viZcAv4YuaKtjLypgRV%2FMultiple%20sections.png?alt=media&amp;token=28c642d1-a918-45f0-9507-a13e16d43287" alt=""><figcaption><p>In SPA's a Section acts as a Page.</p></figcaption></figure>

### ▭ Row Container

Row containers are used to build the contents of a section. As the name explains, these are rows that build the section interface from top to bottom. Row containers always have 20px padding on left/right, to ensure a 20px distance from the screen edges on any device.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Ff5TVystzMhl62PDlyBmh%2FRow%20Container.png?alt=media&amp;token=c52b45d0-9a1d-4c09-915f-b28126c32f0a" alt=""><figcaption><p>Row containers build your content in neat rows.</p></figcaption></figure>

### &#x20;⧆ Block

Finally, blocks are components that are added into row container. This is your actual page content, like a table, image, map or card.

One or multiple blocks can be combined together. Note that a standard block has a minimum width of 280px to ensure correct display on 320px Mobile (280px + 20x2 padding from their Row container).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FuqDm7TLeLJoyoXe70MeG%2Fblocks.png?alt=media&amp;token=cb0ad9da-83c8-4119-85bc-1372350e9511" alt=""><figcaption><p>Blocks make up of the actual visual content of your page.</p></figcaption></figure>


# Repeating groups

Anything list related

Repeating groups follow specific rules to be compliant with openBuild. In order for RG's to have the same alignment, we have a specific RG containers containing our RG's, ensuring 20px gap between our items as well as 20px padding on both sides.

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FTAfM4rrrbuegoogVuYpp%2Frgcontainer.png?alt=media\&token=da1e52da-bac0-497a-b7c4-6623bd97cc3e)

<table><thead><tr><th width="238">Element</th><th>Padding</th></tr></thead><tbody><tr><td>RG container</td><td>10px Left/Right</td></tr><tr><td>RG</td><td>-</td></tr><tr><td>Outer</td><td>10px Left/Right/Top/Bottom</td></tr><tr><td>Inner</td><td>Depends (how the card is designed)</td></tr></tbody></table>

#### RG number of columns

While Bubble allows you to set up the number of columns you want in your RG, this number is fixed. With openBuild framework, you can play with RG column min width to get the desired layout.

<table><thead><tr><th>RG column min wdth</th><th width="171"># of columns on 1280 px</th><th width="162"># of columns on 768px</th><th># of columns on 320px</th></tr></thead><tbody><tr><td>280px</td><td>4</td><td>2</td><td>1</td></tr><tr><td>224px</td><td>5</td><td>3</td><td>1</td></tr><tr><td>204px</td><td>6</td><td>4</td><td>1</td></tr></tbody></table>

#### Set up max column # (CSS)

Another possibility offered to set up the maximum number of RG column you need is to use custom CSS.

```
<style>
@media only screen and (max-width: 640px) {
#rg-col-2 {
grid-template-columns: repeat(1, minmax(280px, 1fr))!important;
}
#rg-col-3 {
grid-template-columns: repeat(1, minmax(280px, 1fr))!important;
}}
@media only screen and (min-width: 641px) and (max-width: 960px) {
#rg-col-3 {
grid-template-columns: repeat(2, minmax(280px, 1fr))!important;
}}
</style>


```

&#x20;


# Advanced Responsiveness

While our standard specifications allow you to generate consistent layouts, you might want to use some custom settings to build your desired UI.

For example, having blocks of different widths within the same row container might be important in a certain layout. In order to do that, we override the min-width of the blocks and/or make the width fixed for certain blocks.

![Example of different blocks width](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fw4y1F1gFdz2o26o6o81X%2Fimage.png?alt=media\&token=2b88b7b2-52ab-4fe3-a4d7-e68a973c8aa8)

When you're using this method, it's likely also that you want your layout to behave differently on  smaller devices. Using the [Viewport Option Set](/framework-elements/option-sets), you can then either hide certain blocks or make those full width for certain devices.

![Make element full width when not desktop](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fon2r3oJh8pFjZdC0wLkh%2Fimage.png?alt=media\&token=3a1dce35-301a-4756-b3c7-a145efabdb72)

![Hiding an element when not desktop](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FUa0vYBugfO4BVIIEmTQN%2Fimage.png?alt=media\&token=adfcae67-684f-4854-9136-2f7cb1f12c36)


# Styles

{% hint style="warning" %}
All openBuild styles include the ⊝ icon as a first character to avoid mixing those with your own created styles. Remember to not delete openBuild styles if you want later to swap your style guide for another one.
{% endhint %}

##

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FejPFs8KOe85W2zbACjyP%2FStyleguide.png?alt=media\&token=9183f40a-baf7-4450-ad06-e288ab947434)


# Typography

openBuild typography consists of 9 Headings, 4 Bodys, Caption and Overline.&#x20;

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FDvOuBTX6S7zKeTYQlJ2q%2Fimage.png?alt=media\&token=2faf3ad3-f94a-4e92-a577-3dd057dc9c00)

Regarding variations, each text style is available in any variation of colors and alignment. Note that the style name syntax is always the same : ⊝TEXT STYLE-TONE-ALIGNMENT, like the example below.

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FEtNpqrcMHqtZ3MwsXOd1%2Fimage.png?alt=media\&token=8a231f02-b9a6-4773-a51e-c0d2f8d85205)

Additionally, we added 3 text styles related to navigation : NavText S, NavText M & NavText L. Those are used primarily in navigation components (header, left menu, sub navigation etc..).&#x20;

openBuild typography consists of 9 Headings, 4 Bodys, Caption and Overline.&#x20;

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FDvOuBTX6S7zKeTYQlJ2q%2Fimage.png?alt=media\&token=2faf3ad3-f94a-4e92-a577-3dd057dc9c00)

Regarding variations, each text style is available in any variation of colors and alignment. Note that the style name syntax is always the same : ⊝TEXT STYLE-TONE-ALIGNMENT, like the example below.

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FEtNpqrcMHqtZ3MwsXOd1%2Fimage.png?alt=media\&token=8a231f02-b9a6-4773-a51e-c0d2f8d85205)

Additionally, we added 3 text styles related to navigation : NavText S, NavText M & NavText L. Those are used primarily in navigation components (header, left menu, sub navigation etc..).&#x20;


# Colors

Flexible and in-depth 9-colors token to get structured and consistent color palette.

openBuild 9-colors palette structure has been carefully decided to allow variety of color schemes while keeping high consistency in your apps. This structure ensure infinite possibilities of color schemes (dark mode, saturated, monochromatic, triadic etc...).

![openbuild color palette example (from DeepBlue OB Style)](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F5iqKcAGrCrNKeqP9FbR7%2FGroup%20298.png?alt=media\&token=dc074a03-c33a-4b14-a1d3-ad83852f404b)

### Colors

While Main color is usually the main brand color, the two others are supportive colors. Depending the style guide you pick, those can be analogous, complementary or even inverted colors from the main one.&#x20;

Colors tones are used as variants in all OB text styles, as well as OB group styles. Buttons are available for Main color and Secondary color only.

### Shades

Shades represent 6 tones going from Primary to Negative. Depending the styleguide, those are slightly tainted toward the main Color, which reinforce the overall consistency of the app color palette.

Shades tones are used as variants across different OB styles like typography, groups, buttons.&#x20;

While the color palette is employed across style variations, it's important to note that the color palette is also saved in your app within the option Set 'UI Colors'. This allows you to use it outside of app defined styles (like in element properties, conditionals etc...).


# Groups & Box Shadow

### Main group styles

We have 6 types of group styles used across all the color tones.&#x20;

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F6XMdQji86kbhbMqvg8Ui%2Fimage.png?alt=media\&token=c4c3a6fb-fdbf-456c-98fd-3530c7f1c6a6)

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fw4psNK8FHvlOa7AypEEH%2Fimage.png?alt=media\&token=3bd1f6d6-4057-448f-9343-d42037f0aca0)

Flat : No radius, no border, no shadow.

Flat Rounded : Radius, no border, no shadow.

Bordered : Radius, Borders, No shadow.

Elevation S : Radius, Borders, Shadow, Padding

Elevation M : Radius, Borders, Shadow, Padding

Elevation L : Radius, Borders, Shadow, Padding

#### Empty Group

We have an additional group style name ⊝Empty which have no appearance attribute. This style is used mainly for group used purely as container with no design attributes.


# Inputs

All inputs elements are using two different styles in openBuild : Standard or Transparent.

### Standard

Standard input style are used for full input elements, and consist in a bordered input field used in combination with input label and optionnally input helper.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FzotTvCZwQtqPzlBW8zbZ%2Fimage.png?alt=media&amp;token=c8e130e7-5acf-4ad8-8a97-d272d4f467e0" alt=""><figcaption></figcaption></figure>

### Transparent

Transparent input styles are used when custom input need to be created. They consist in a full transparent / borderless styles.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FrVzl6nmGY06YWYrD400d%2Fimage.png?alt=media&amp;token=673c95a2-f143-40e9-a786-2c1f01219cbb" alt=""><figcaption></figcaption></figure>


# Buttons

Buttons styles are organized around size and appearance.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fz1PbgsTRubRlcwt6lV3f%2Fimage.png?alt=media&amp;token=20c5dc34-ba7e-4dc2-a075-764561b5edcb" alt=""><figcaption></figcaption></figure>


# Style Variations

Coming soon with Extension


# Changing styles

Coming soon!


# Custom CSS

This CSS is added via openBuild Toolkit plugin which links to CDN containing the file. You can download the plugin for free [here](https://bubble.io/plugin/openbuild-toolkit-1652100141816x544111532603605000) or adding it via plugin marketplace.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FXBZG2SFR9ifXelmEvD6Y%2FScreenshot%202023-01-24%20at%2011.32.59.png?alt=media&amp;token=fbdc50a6-699a-43f6-8736-edabab9015c5" alt=""><figcaption></figcaption></figure>

```
<style>

/* padding for dropdowns */
    
.dropdown {
    padding-left: 6px;
    }    
    

/* overflow for RGs */

#overflow {
overflow: visible !important;
}
    
    
/* removing inset shadow */
    
.iziToast:after {
box-shadow: rgba(0, 0, 0, 0.00) 0px 10px 15px -3px, rgba(0, 0, 0, 0.1) 0px 4px 6px -2px;!important;
}
    
 
/*  wrapping RG width to enable tag-like look */
    
#rg-wrapped{
        height: auto !important;
        min-height: auto !important;
        display: flex;
        flex-wrap: wrap;
    }

/* Scroll */
    
    
#scrollHorizontal {
    overflow-x: auto !important;
    }
    
#scrollVertical {
    overflow-y: auto !important;
    }

    
/* Full page height */
    
#fullHeight {
    height: 100vh !important;
    }
#demiHeight {
    height: 80vh !important;
    }

#rowreverse {
    flex-direction: row-reverse !important;
    }
    
#colreverse {
    flex-direction: column-reverse !important;
    }


/* openBuild Style Generator */

iframe#openpanel {
    height: 100vh;
    width: 400px;
    position: fixed;
    top: 0px;
    right: -400px;
    z-index: 2147483647;
    transition: all 0.8s ease 0;
    border: 1px solid #f0f0f0;
}

img#toggle {
    height: 35px;
    width: 35px;
    position: fixed;
    top: 20px;
    bottom: 20px;
    z-index: 2147483647;
    z-index: 2147483646;
    cursor: pointer;
}


#obBtn {
    height: 50px;
    width: 172px;
    position: absolute;
    /* align-self: center; */
    right: 192px;
    top: 32px;
    border-radius: 5px;
}

#sticky {
    position: sticky !important;
    }

</style>

```


# Pages


# index

Landing page

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F78XsAPqchajlniYs6tNI%2Fopenbase-template.bubbleapps.io_version-test_.png?alt=media&amp;token=74169864-5db7-4715-8787-05ffc2f94988" alt=""><figcaption></figcaption></figure>


# base-menu

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FTiFPx8yYDXoYiuhBXuQo%2F07AE7457-912F-470D-ABCF-25B08E2C5436.png?alt=media&amp;token=af2e7cf1-4d68-48bd-bcda-741458e7bcb3" alt=""><figcaption></figcaption></figure>


# base-top

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FGo3AqxyR5m2uBp5KLkGc%2FC78F7977-15C1-40A6-A0E7-75D4CBE90108.png?alt=media&amp;token=407398d0-e54d-429d-850f-7eee9be7c197" alt=""><figcaption></figcaption></figure>


# base-ribbon

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FCwJtILs4r2N45KS11vW0%2FE44C0671-FE7C-466A-BAD9-D5458364A611.png?alt=media&amp;token=7f9ad755-0214-41cb-8948-a0cf0bcf2d30" alt=""><figcaption></figcaption></figure>


# base-mobile

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F7Fm5rAP8PobihVz4d1He%2FScreenshot%202022-11-05%20at%2012.14.01.png?alt=media&amp;token=a4852464-736d-4dcb-94cd-4be0f0c776c6" alt=""><figcaption></figcaption></figure>


# admin

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FJJrX5XED1uXy1qcLjN35%2F7db3e6d3-5035-42ae-966b-9cafc774846a.png?alt=media&amp;token=1dd361e3-7d5c-4444-b476-b757c90b76d2" alt=""><figcaption></figcaption></figure>


# verify

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fc6tdjk9DQSvvXQ1GhQH3%2F62ee713e-dbe5-4b7f-8f8e-155ce8a2ca35.png?alt=media&amp;token=68579a29-5ac7-49a1-922f-02dedce36a70" alt=""><figcaption></figcaption></figure>


# styleguide

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FxxA915nxsNMXZSvPNJfM%2F40b600d3-9062-4428-8cb8-0559293dcd1e.png?alt=media&amp;token=023213f1-bcc1-4f70-97ca-d485c34b0da7" alt=""><figcaption></figcaption></figure>


# terms

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FNGzzf9dCxw3GEXTVfJ9o%2F369aa9a9-38c0-4fe4-ae9c-4b543ac11c48.png?alt=media&amp;token=602d3d7e-e999-4545-941c-78ff7926c2d7" alt=""><figcaption></figcaption></figure>


# login


# reset\_pw

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FTGmjcTB18qxNY66sflpf%2Fdownload.png?alt=media&amp;token=e63ae4e7-9a05-45e5-82ab-264505b863cf" alt=""><figcaption></figcaption></figure>


# privacy

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FxNm9liSHbiKFjCsiWoyX%2F6cb1f226-56b6-4387-b828-3652c953376d.png?alt=media&amp;token=b77230c1-9098-4e8c-9e8f-13288905ad59" alt=""><figcaption></figcaption></figure>


# 404

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FlTNqh6qUwkFnhElrjLKD%2F1b9383e6-8a1c-4411-b026-a35208e52ae6.png?alt=media&amp;token=b5f37c7d-21d2-4f89-9263-e4dbe030fd05" alt=""><figcaption></figcaption></figure>


# Menu

Depending of chosen page template you get access to following menus:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F2A0Jq9OAfzyLy8BLTSG6%2Fimage.png?alt=media&amp;token=8f595b44-9e92-4d30-89c3-a449bf545132" alt=""><figcaption><p>base-menu</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fvt1znA389pPcfE8vgxHR%2Fimage.png?alt=media&amp;token=edbbf6e5-ce47-46e3-9119-5d871cce115e" alt=""><figcaption><p>base-top</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FdqtKmEoU4VXVVDN9maa7%2Fimage.png?alt=media&amp;token=c578b98d-6e69-4253-adc8-a2d49bc53bb9" alt=""><figcaption><p>base-ribbon</p></figcaption></figure>


# Base Layouts

openBuild template comes with 2 page layout starter : base - left & base -  top

#### Base - Left

This page layout consists of a content area with sections surrounded by a left Ribbon menu. The left menu become invisible on tablet (screen width < 1024 px) and it's replaced by a header with a hamburger menu. This layout is recommended as a starting point for SPA.

#### Base - Top

This pages layout consists of a content area with sections along with a header menu. The navigations items are replaced by a hamburger menu on tablet (screen width < 1024 px) . This layout is recommended either for SPA or website.


# Getting Started

Throughout the editor you will find references to openBuild documentation, that you will help you understand how we work.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FSMIPK5suJFaoUTENyYEK%2FScreenshot%202023-01-20%20at%2016.28.18.png?alt=media&amp;token=a1973d47-9e1b-49d4-88e9-0eb49e56142d" alt=""><figcaption><p>Example: Send Email Instructions</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F5VdIEwEknERvubeZ8StF%2FScreenshot%202023-01-20%20at%2016.26.31.png?alt=media&amp;token=0ebe4879-ed4b-4685-8160-9ca3a988d16a" alt=""><figcaption><p>Example: Element Display Instructions</p></figcaption></figure>


# Navigation

How your users move around your app

openBuild uses 4 different ways of navigation:

* [Go to page action](#go-to-page)
* [Navigation through custom states](#navigation-through-custom-states)
* [Navigation through URL parameters](#navigation-through-url-parameters)
* [Navigation through URL parameters and w/ Option sets](#navigation-through-url-parameters-and-w-nav-pages-option-set) (recommended)

Depending on your use case it might make sense to use all of these in your app.&#x20;


# Go to page

The simplest for of navigating

This is the most straightforward navigational action. Simply define the destination page in the action and whenever a button or link is clicked with this workflow, the user is directed to this page.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FiyQwmbL1sNDBOktCL5Vi%2FScreenshot%202022-10-03%20at%2014.09.28.png?alt=media&amp;token=5a2b11c4-e20f-4d0b-9fb7-78b5d829315a" alt=""><figcaption></figcaption></figure>


# Navigation through custom states

Perfect for sub-navigating tabs or menus on your page

You can use custom states to navigate between tab menus for example. It's a perfect use case for simple sub-navigation in your groups.&#x20;

When a tab is clicked, you can set a custom state of 'show' to the parent section or group. This 'show' is simply a text field. A custom state is arbitrary data that you can load into a page or element and use without having to store it in the database.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FF0jypbcJIDquhMAGjcb0%2FScreenshot%202022-10-03%20at%2014.31.22.png?alt=media&amp;token=523fff6e-45c6-43ca-a884-2461e5a4328d" alt=""><figcaption><p>Setting a value to the 'show' state</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FGp40fjpWo03lQuqcULze%2FScreenshot%202022-10-03%20at%2014.41.38.png?alt=media&amp;token=91295dbd-f4dc-4d7c-9766-54fc9c814ba2" alt=""><figcaption><p>Conditional on the UI element. The element is invisible on page load by default. </p></figcaption></figure>

Here is a simplified diagram of what we're trying to accomplish. Let's say we have 3 tabs: Account, Billing, and Notifications.

Each time we click any of the tabs we set the custom state to the tab we clicked (eg. Account).

Each of the 3 tabs have a group with all the content inside. These are all hidden by default and have a condition that looks at the custom state.

When the custom state corresponds with one of the hidden groups, it shows.

![The navigation through custom states workflow explained](https://lh3.googleusercontent.com/buz-I_Wow8f6kKSTV_QZFX3hY2FHOeWs2qwGr0C6EWYEa_LaoaNCDXs3mkuVA0YpPg5Tdc4nizWg4PBRFvqnDgAzeSF9DE_SfBSdS_Kb_itf6zoj_bqr4qkbpTiJbnXmVuXvFwGFjwM)


# Navigation through URL parameters

Keep your navigation history

A more advanced way of navigating is to use URL parameters. These have two distinct advantages over custom states:

a) when you use url parameters, you still navigate by the URL even if you do not seem to leave the page. This means you build up a breadcrumb trail and can go back and forth in the browser to go to a previous page.&#x20;

B) you can append parameters to your URL's that can interact with your page as you navigate. You can add a URL parameter in a link in your emails to navigate to the right section of your page for example.

In general passing data along in URL parameters is a common practice and very versatile.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FmBhastDRthW9BYlDFMdF%2FScreenshot%202022-10-03%20at%2015.05.27.png?alt=media&amp;token=21fc2282-1e95-4510-ba42-7e71e44aa341" alt=""><figcaption><p>Set type of content for the section as 'text' and type in the text you want to refer to when navigating</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F6XigWwD9HEDYZp3QBsWL%2FScreenshot%202022-10-03%20at%2015.05.39.png?alt=media&amp;token=f18b1f0b-9d5b-4925-a51e-68c0f8960029" alt=""><figcaption><p>Section is invisible by default</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FsvZYlTf7vriBwl3T8HGc%2FScreenshot%202022-10-03%20at%2015.05.50.png?alt=media&amp;token=0ca87320-cc9e-4217-a094-8bf42b20b321" alt=""><figcaption><p>We are referring the URL parameter to make the right section visible </p></figcaption></figure>

Navigation action can refer to the text on the ❖ Section Users we set. The workflow will look like this:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F1j57Cee3f7BLzET2mUwK%2FScreenshot%202022-10-03%20at%2015.15.15.png?alt=media&amp;token=64c82ec7-60ef-443c-a0ae-005bff1fa5d5" alt=""><figcaption></figcaption></figure>

Additionally, you can use extra parameters such as 'tab' to create a sub-navigation. Or UID if you are working with data (read more about this in [this section](/working-with-the-framework/data-and-workflows/crud)).

You can also use more advanced practice such as using Option set to navigate. You can read about it in the [next section](/working-with-the-framework/navigation/navigation-through-url-parameters-with-option-sets).&#x20;


# Navigation through URL parameters with Option sets

A scalable way to handle navigation

### 🧭 Navigation - Option Set

Using the option set to navigate between pages and sections will help you build faster, avoid bugs and keep your app structure consistent. It also opens up a lot of possibilities around advanced navigation options such as in onboarding pages or more complex forms. It is our preferred means of navigation, especially in single-page apps.

By default, all [pages](/core-concepts/pages) across the template contain a [Source Popup](/working-with-the-framework/data-and-workflows/source-popup) in which you will find a 🧭 Source - Navigation group. It is connected to the 🧭 Navigation option set.&#x20;

<div align="center"><figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FLnfuGAuK6EkTO2AH4BeV%2FScreenshot%202022-10-24%20at%2014.56.50.png?alt=media&amp;token=d2b71a49-a2de-4f94-b81f-553f0e6e2f9f" alt=""><figcaption><p>🧭 Navigation Option set</p></figcaption></figure></div>

The simple structure contains two attributes: a) section and b) tab. The option has to at least have a Section filled for it to work properly.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F7W8NnnnBtj6zxZbzI8wN%2FScreenshot%202022-09-23%20at%2011.02.06.png?alt=media&amp;token=109fb5be-ffd0-4808-a394-5dc6dc9779ba" alt=""><figcaption><p>Example 🧭 Navigation Option set - Admin/Section A</p></figcaption></figure>

Inside the 🧭 Source - Navigation group you find the following logic implemented:

***If this 🧭 Navigation option's section matches the 'section' value that you we get from URL parameters and if this  🧭 Navigation option's tab matches the 'tab' value that we get from the URL then pick this Option.***

Note that if for example, the 'tab' URL parameter is empty it will still match with an option that has the 'tab' attribute empty.

You can see the logic implemented in the image below:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FiS7s4NkvxYLMW63ZumGR%2FScreenshot%202022-10-24%20at%2014.59.40.png?alt=media&amp;token=831526a5-3bea-4424-a75a-4873d9e8cd64" alt=""><figcaption><p>Filtering logic implemented</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FsEN5KAkc3MYAqkiUKSBx%2FScreenshot%202022-11-05%20at%2011.54.51.png?alt=media&amp;token=22eeb208-5390-4266-b78a-3edf25890e96" alt=""><figcaption><p>The section's conditional in referring to the  🧭 Source - Navigation Group 🧭 Navigation</p></figcaption></figure>

{% hint style="warning" %}
Having two 🧭 Navigation options using the same 'section' and 'tab' values will create a conflict since the logic defaults to picking the first option that matches the criteria. If you have to use the same attribute values for the same 🧭 Navigation option (for example for different pages), you may want to create a new additional attribute called 'page' and add it to the filtering criteria.
{% endhint %}

### 🧭 NAVIGATION - Custom Event

On every page you will find a 🧭 NAVIGATION Custom Event. The when triggering this event you need to pass at least 🧭 Navigation option from the option set.&#x20;

{% hint style="info" %}
For information on the basics of working with Custom Events in Bubble.io, refer to the official [documentation](https://manual.bubble.io/core-resources/actions/custom#custom-event-1).&#x20;
{% endhint %}

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FUYDPC1JkVkoiJ7EXQzIr%2FScreenshot%202023-02-09%20at%2010.11.16.png?alt=media&amp;token=fca73d12-c0f6-49b3-8e8f-192a69ba4eed" alt=""><figcaption><p>Notice that UID is optional</p></figcaption></figure>

Because we use option set Bubble allows us to pick the option from the list when triggering this event.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FrtkRYA6TsNjXeAVBeHNf%2FScreenshot%202023-02-09%20at%2010.14.17.png?alt=media&amp;token=f6449dcd-a9af-40d0-b65f-c25923271804" alt=""><figcaption></figcaption></figure>

In the Custom Event you will find a 'Go to page' action that will always send 3 parameters to the page.&#x20;

* section
* tab
* UID - only used when navigating to a section or tab which requires data source. Read more about use of UID in the URL structure in [this section](https://openbuild.gitbook.io/manual/working-with-the-framework/data-and-workflows/source-popup).

All these parameters work automatically with [Source Popup](/working-with-the-framework/data-and-workflows/source-popup) allowing you for seamless transitions between sections and at the same time displaying the data that you need.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FN30zfhEmWUhcb4FZsNeb%2FScreenshot%202023-02-09%20at%2010.11.23.png?alt=media&amp;token=408416ba-4e05-41fc-8f21-a7a7556a1c00" alt=""><figcaption></figcaption></figure>

Multiple subsections

If your section structure has multiple subsections you have to remember that their parent section e.g *Details C* does not exist on its own. In other words at least one of the subsections has to always be visible. That's why the conditional on the Section itself will contain the logic to make this section visible if 🧭 Source - Navigation 🧭 Navigation option is 'tab a', 'tab b' or 'tab c'

You can find the following logic implemented in the admin page under *Details C* section in the openBuild template.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FADVcJvNYwKxMkYu3nMR0%2FScreenshot%202022-10-24%20at%2015.02.56.png?alt=media&amp;token=82b75930-098e-4f5b-a173-419d87c6dc1f" alt=""><figcaption><p>Section with Tabs</p></figcaption></figure>

### 🧭 Element Display

Since navigating in the reusable elements is a bit different, in the template you will find a dedicated Option set specifically to use for Reusable elements, such as example CRUD Popup, CRUD Floating, Settings, and User Access Management.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FlvPeDzNgm3531Qdr1hFE%2FScreenshot%202022-10-24%20at%2015.06.21.png?alt=media&amp;token=32e7a0cc-e312-46f4-a3c9-b90cc9e31c37" alt=""><figcaption></figcaption></figure>

Using the 🧭 Element Display option follows the same logic as using [`🧭 Navigation to navigate the pages`](/working-with-the-framework/navigation/navigation-through-url-parameters). By default, the groups we want to navigate between are hidden.

🧭 Element Display option set has only two fields: display and text. The 'text' field is used in an action that gets triggered on page load (see explanation below).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FA0gR3PicOralDAvoOj9a%2FScreenshot%202022-10-03%20at%2017.42.41.png?alt=media&amp;token=f521b3df-9481-49be-bb69-3536a8f38aba" alt=""><figcaption></figcaption></figure>

For example, in the 👥 USER ACCESS MANAGEMENT reusable, the login section is visible by default. Adding the 'type=signup' parameter in the URL structure will change the section to the one that text matches the option set, in the case of 'signup' value it is going to be a signup section. You can see above that Option set 'Access - Signup' have 'signup' as 'text' field value.&#x20;

👥 USER ACCESS MANAGEMENT reusable comes with a pre-build 'page is loaded' workflow. It triggers a custom event which then changes the section depending on if the URL key 'type' is not empty and there is an Option set that matches the 'text' field value.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FE1kBWjEOEKOSKVXjxumZ%2FScreenshot%202022-10-24%20at%2015.07.10.png?alt=media&amp;token=21a105ff-8b9a-4411-8990-229fea514059" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Keep in mind that like with 🧭 Navigation logic, this action picks the first item from the list. If you have more than one Option having the same 'text' field value it will pick the first one on the list. If you find that limiting you can always add an additional attribute e.g. page and add it as an additional filter so you can use multiple Option using the same value.&#x20;
{% endhint %}

We set that state on the top parent element. In our example its 👥 USER ACCESS MANAGEMENT. Here you can also set which section should be visible by default by changing the 'Default value' field.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FGjdklrPYEZDbcVB6nMp9%2FScreenshot%202022-10-24%20at%2015.08.41.png?alt=media&amp;token=5b236b88-41da-439c-b677-5cd1bee16c91" alt=""><figcaption></figcaption></figure>

The sections follow the basic conditional logic of being shown/ hidden depending the on the state of the Reusable.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FdPU1Jld2d4v0JGkl2d8v%2FScreenshot%202022-10-03%20at%2017.13.24.png?alt=media&amp;token=5e483b14-f456-4dab-8faf-32b0685b53a1" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FbJT5st5Gtw49THpML361%2FScreenshot%202022-10-24%20at%2015.09.30.png?alt=media&amp;token=cb959766-568e-42ce-b3c9-75ad824588dd" alt=""><figcaption><p>Referring to the 🧭 Element Display state.</p></figcaption></figure>

Additionally, the 👥 USER ACCESS MANAGEMENT contains the 💡 CHANGE SECTION custom event which you pick the section you want to navigate to within that element

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fp0vOI5gP4tqfwJCy0YNv%2FScreenshot%202022-10-24%20at%2015.10.42.png?alt=media&amp;token=d73cc69b-11ec-4773-96dd-cde0bd39ce83" alt=""><figcaption><p>Because we use option set as a parameter you can pick the section you want to navigate to.</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F39aogv1OQMzAE6RNEbKF%2FScreenshot%202022-10-24%20at%2015.11.47.png?alt=media&amp;token=d5175ef8-e4b5-49f4-bd17-d3a8b26e6fb3" alt=""><figcaption></figcaption></figure>


# Data & Workflows

Everything your app revolves around

openBuild uses 5 concepts around data manipulation.

* [Custom states](/working-with-the-framework/data-and-workflows/custom-states) - learn how to store data temporarily on a page.
* [Custom events](/working-with-the-framework/data-and-workflows/custom-events) - learn why we recommend using custom events.
* [Source Popup](/working-with-the-framework/data-and-workflows/source-popup) - learn how we centralize data management on a page.
* [CRUD](/working-with-the-framework/data-and-workflows/crud) - learn how to work smart and communicate with reusable elements.
* [Backend Workflows](/working-with-the-framework/data-and-workflows/backend-workflows) - why & when you should use them.


# Custom States

A custom state is an arbitrary container capable of holding any type of data (single or list) that is readily available to the user in the current browser session.

{% hint style="warning" %}
It doesn't matter where you create the custom state (or how), as long as you keep in mind that when you add it inside a cell of a repeating group or inside a reusable element, you cannot access it through a normal 'set state' action.
{% endhint %}

Custom states have two major use cases:

* Storing temporary data on the page
* Navigation

{% hint style="danger" %}
Remember Custom states will not store the data you have saved if you reload the page. &#x20;
{% endhint %}

### Storing data on your page temporarily

In the example below, based on the pre-build admin page that you will find in the template, we want to select multiple users in a list and perform a bulk action on those selected users.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FivGRmWUvEPTaIcshOfSU%2FScreenshot%202022-10-03%20at%2012.10.04.png?alt=media&amp;token=ae83b558-6dc2-4a29-bc26-16f63b24622a" alt=""><figcaption></figcaption></figure>

When the user clicks the checkbox for selecting a user in the table, we add this user to our custom state list of users which we created previously.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FzLd3hBh4Q4tQu185hjsJ%2FScreenshot%202022-10-03%20at%2012.07.07.png?alt=media&amp;token=0a0c8270-de22-4ff6-a0a7-feae2debe4f8" alt=""><figcaption><p>We selected 3 users from the table. All of them are added to the Custom state list.</p></figcaption></figure>

We can then send the list of users from the ⚡️selectedUsers to the backend workflows to delete them.&#x20;

{% hint style="warning" %}
Make sure that the custom state is of the type you want to work with and the 'is a list' checkbox is checked.&#x20;
{% endhint %}

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FNiiAtQWdWRHl5rqJof8I%2FKapture%202022-11-05%20at%2011.02.38.gif?alt=media&amp;token=8615d3b4-3ce8-421f-8fcd-0d230efee20b" alt=""><figcaption><p>Using list &#x26; states in action</p></figcaption></figure>

### Working with pre-loaded data

If you work with set of data that has be pre-loaded on a page it's better to use Repeating Group element rather than a custom state as a list.

For example imaging we have a field called ' Permissions' on the User data type. If you would like to  display list of Permission on page load for that User via state would have to set that values on the page load since you cannot set default values of a state if it's a list or custom datatype.

If you have more then one custom state list or custom state field where data needs to always be available on page load, the 'Page is loaded' can quickly become bulky with 'Set state' action, especially if you have multiple elements where you want to set the state.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FZ6H5eJFdKiqpikkQPd55%2FScreenshot%202022-10-12%20at%2012.52.13.png?alt=media&amp;token=811be19f-a114-4515-b386-997b7fbd3aaf" alt=""><figcaption><p>Setting default state on page load</p></figcaption></figure>

It's much better to work with repeating groups when it comes to lists. On the page load, you do not have to worry about setting the state of the list as it will automatically pre-populate since it's a repeating group. You can structure your repeating groups in the [Source popup](/working-with-the-framework/data-and-workflows/source-popup) or use the Repeating group in which you display the data.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FG1AfhVHoMEVh1ZRD1HRi%2FScreenshot%202022-10-12%20at%2012.53.16.png?alt=media&amp;token=53586633-99bf-41f4-b236-210af2dbf32c" alt=""><figcaption><p>Repeating group storing permissions of the User</p></figcaption></figure>

Additionally manipulating the list in the Repeating group is as easy as manipulating the custom state with the 'Display list in a repeating group' action.


# Custom Events

From the Bubble manual:

> *Custom events are a way to define a workflow in your page that can be reused multiple times ("functions" in a code-driven language).*

You will find multiple uses of custom events in the template.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fxl8kQYXUVrGzyDxY59Bv%2FScreenshot%202022-10-03%20at%2013.26.22.png?alt=media&amp;token=4e39867f-b966-404c-9c45-3bed409a2425" alt=""><figcaption><p>Dedicated custom events for sending emails. You will find these in 👥 USER ACCESS MANAGEMENT reusable.</p></figcaption></figure>

Read more about the basics of Custom events in [Bubble manual](https://manual.bubble.io/help-guides/building-workflows/using-custom-events).

Advanced practices of using Custom events are based on the connection between Custom events and Reusable elements (you can read about the basics of Reusable elements in [Bubble manual](https://manual.bubble.io/help-guides/structuring-an-application/reusable-elements))&#x20;

Reusable elements can be used as sections with UI's or just workflows (no UI). A great use case for creating reusable with only workflows in it is for example integrating payments in your app. Workflows created in one place could be then reused on multiple pages throughout your app.&#x20;

{% hint style="info" %}
We are heavy proponents of Custom events as we try to avoid duplicate work as much as we can. Custom events are a great tool to keep your workflows lean, your debugging time short and your teammates happy.&#x20;
{% endhint %}

Read how we use custom events and reusable elements together [in this section](/working-with-the-framework/data-and-workflows/crud).

### Workflow execution rules

Bubble actions do NOT run sequentially. Most of the time actions will not be completed in the same order as they are triggered.&#x20;

In the example below you cannot be sure that every time you run this workflow step 3 will be executed after step 1 and step 5 will always be before step 2 etc. The execution order is dependent on the type of action of client-side criteria (e.g. the newly created object needs to be displayed immediately on the page etc.)

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FvAJddBsQCBbUiEmsDpjn%2FScreenshot%202022-10-13%20at%2011.57.47.png?alt=media&amp;token=fbbcbd93-8ed5-4e05-b9cc-485271cf8fc9" alt=""><figcaption><p>Example</p></figcaption></figure>

There are two ways you can force Bubble to run your actions sequentially:

a) Use 'Result from Step X' in your conditional logic. For example 'Result of step 1 unique id is not empty'

b) use Custom Events. In the example below Bubble will first trigger Custom Event A meaning all actions inside the Custom Event will be run *before* triggering Custom Event B.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FYRckDW6HF8gbKESjNF9h%2FScreenshot%202022-10-13%20at%2012.04.49.png?alt=media&amp;token=c27b001f-80c9-4179-8372-1292a027f391" alt=""><figcaption></figcaption></figure>

From [Bubble manual](https://manual.bubble.io/help-guides/building-workflows/using-custom-events#execution-of-a-custom-event):

> *When a workflow is triggered in Run-mode and hits a trigger a custom event action, the first workflow will pause, the custom event will be run till completion, and the first workflow will resume. Using the debugger can be very helpful to understand the flow of actions if you are hitting some difficulties setting things up*

Learn more about order of execution from this Bubble video:

{% embed url="<https://www.youtube.com/watch?v=IbhCrciOKHM>" %}


# Working with Reusables

### Communicating with reusable elements

This explanation is based on pre-built workflows in the openBuild template.&#x20;

In 🍿CRUD FLOATING GROUP and 🍿CRUD POPUP reusable elements you will find a pre-built 💡SHOW POPUP workflow.&#x20;

The workflow consists of 2 actions:&#x20;

1. &#x20;setting states on the reusable itself and&#x20;
2. showing the reusable.  When triggering this Custom event we are required to always pass the 🧭 Element Display parameter (which is based on the option set) and User datatype.&#x20;

The second parameter is optional since we don't always need to manipulate the User object. When you will add additional parameters to this Custom Event, most of the time all of them (except the Nav Reusables) should be marked optional.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fz3AlWdsTeYP2ZTvATD1c%2FScreenshot%202023-02-09%20at%2009.58.14.png?alt=media&amp;token=b4b9030f-cda1-4d4c-9032-8469ee7a2a43" alt=""><figcaption><p>Notice that only 🧭Nav Reusable parameter is required</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FjPWIyVT8AmkMyo2Bq2l4%2FScreenshot%202023-02-09%20at%2009.58.14.png?alt=media&amp;token=4ee80b2f-5342-42e4-a96c-5a028d29c070" alt=""><figcaption></figcaption></figure>

The passed parameters are set as a state on the reusable so we can act based on the information provided.&#x20;

When we place a reusable element on the page or inside another reusable element we do get access to an action called *Trigger a custom event from a reusable element.*

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FW2sz3rAyTH8bUhtgPPQ8%2Fimage.png?alt=media&amp;token=92eb94f0-e5db-43b4-a38d-58840f49fee7" alt=""><figcaption></figcaption></figure>

In our case, we are clicking RG User Row which contains information about the User datatype. When clicked we want to trigger the 💡SHOW POPUP workflow from the reusable and the information we need to manipulate the object.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F9mf7MhHnxX5UaNCt0r6L%2FScreenshot%202023-02-09%20at%2009.58.54.png?alt=media&amp;token=4762538f-f81c-4f86-b129-0d6d88ef8fb3" alt=""><figcaption><p>We want to show CRUD User section so we pass 'CRUD - User' from Nav reusables Option Set</p></figcaption></figure>

When triggering 💡SHOW POPUP we are required to pass the right 🧭 Element Display option set to display the right section. Since we want to display the user details section we are passing the 'CRUD - User' parameter.&#x20;

The visibility of the CRUD - User section in 🍿CRUD Floating is based on conditional logic.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FlHN7lzhMX8566H0vVCFB%2FScreenshot%202022-09-19%20at%2014.54.15.png?alt=media&amp;token=dd8427ab-f32d-48df-983e-3cb5b2eea4f2" alt=""><figcaption><p>When conditional is true, the CRUD - User section will be visible</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fz14gcWEJaaGQWSVnKVAy%2FScreenshot%202022-09-19%20at%2014.55.07.png?alt=media&amp;token=53f3e7e1-d73c-4297-b7f2-6c3a6b140959" alt=""><figcaption><p>User details section inside the 🍿CRUD Floating</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FbtwpoNxsrmsvDvtb4oYS%2FScreenshot%202023-02-09%20at%2010.00.23.png?alt=media&amp;token=2821b3e7-4474-4ae2-acb4-9df29a99f2d4" alt=""><figcaption><p>The state 'show' on the 🍿 CRUD Floating Group is an option set type '🧭 Nav Reusables'</p></figcaption></figure>

The elements inside the CRUD - User section are referring to the main datapoint which in this case is 🍿CRUD FLOATING GROUP User - the top-level datapoint in the Reusable which values we set with '💡SHOW POPUP' custom event.

### How to add a new group in the reusable element

#### 1. Add a new option to 🧭 Element Display option set

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FzNGJCWfrkzyDAwjooqzu%2FScreenshot%202023-02-09%20at%2010.00.45.png?alt=media&amp;token=ff238005-d3a0-4740-9f9f-ce9c4a8116b5" alt=""><figcaption></figcaption></figure>

#### 2. Copy or add a new group section

In the template, you will find 3 template sections inside the 🍿 CRUD Popup and 🍿CRUD FLOATING GROUP. These are:

a) CRUD Template&#x20;

b) MSG Template

c) MSG Template Icon

You can duplicate those or you different section with workflows already connected (e.g. CRUD User).

#### 3. Set or update conditional on the newly created section

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F51Hia7TCE6aR0fpiNDYg%2FScreenshot%202022-10-13%20at%2011.39.56.png?alt=media&amp;token=965f44a3-c6a4-46cd-8d04-b451703bf626" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Remember that all sections inside the reusable should not be visible by default!
{% endhint %}

#### 4. Make sure to use the new option when triggering 💡SHOW POPUP custom event

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FR5Zww4PiICcpSLWmFweX%2FScreenshot%202023-02-09%20at%2010.02.01.png?alt=media&amp;token=26fc5828-aea7-430e-98dd-a4d24830fe1c" alt=""><figcaption><p>Trigger a custom event from reusable and pick your newly created option</p></figcaption></figure>


# CRUD

### Create, Read, Update and Delete

CRUD is the acronym for CREATE, READ, UPDATE and DELETE. These terms describe the four essential operations for creating and managing persistent data elements.

Custom events are great for repetitive tasks. When you allow users to edit a Thing in multiple places on a page, you can add a 'make a change to' workflow each time you want to save this data. You can imagine that managing multiple workflows could result in errors or, at best, a lot of duplicate work.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FnJ0kAZIR82n81o8tukon%2FScreenshot%202022-10-03%20at%2012.52.21.png?alt=media&amp;token=60585479-a02e-4c9f-8f72-b47c2dbbff31" alt=""><figcaption></figcaption></figure>

Alternatively, you can create a Custom Event. It is a generic workflow that can be triggered or scheduled and use any type of data or no type of data at all.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fxyh64fbpeN4nMZWHKc3q%2FScreenshot%202022-10-03%20at%2012.36.47.png?alt=media&amp;token=e5e10dcd-60f2-47fa-9a77-0a90e37ec592" alt=""><figcaption><p>We are sending the User object that we want to update to the Custom event.</p></figcaption></figure>

Instead of having multiple 'make changes to Thing' workflows, you just create one and it's triggered by a custom event.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FjufwVFNQRGLOKcf2zfBX%2FScreenshot%202022-10-03%20at%2012.21.52.png?alt=media&amp;token=f510df50-3004-4266-9e28-aa37e2d6c1ec" alt=""><figcaption><p> A custom event that updates a User</p></figcaption></figure>

In this Custom Event we make changes to the User (we pass the user to the custom event and it will be accessible as the 'User'), but we can also use it to reset the form and trigger a Toast notification or edit the User in another way.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fgnoxu1pECxEbTJ9FGnub%2FScreenshot%202022-10-03%20at%2012.38.12.png?alt=media&amp;token=fb06b62d-2d40-4e49-8cc3-a0e274de79a2" alt=""><figcaption><p>Make changes to thing is placed inside Custom event</p></figcaption></figure>

Inside the update action, we refer to the inputs where we define that values. Note that we have the ability to define multiple parameters when triggering the Custom event and it means that you don't always have to refer to input but you could also refer to data that you send via Custom event. See the example below:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F6etY7PeXu1NRnXo04tTb%2FScreenshot%202022-10-03%20at%2012.44.46.png?alt=media&amp;token=cdb0d02c-4f95-42d4-b96c-83f3632da5c5" alt=""><figcaption><p>Here the suspended value could be also a dynamic variable. This is just for example purposes.</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fgg56dzd0EmLujmeEtgYw%2FB6FAB0FD-224F-450D-BFA1-5C7A5B744AC5.png?alt=media&amp;token=a61db619-f2f8-4fc4-ab78-98699e81cd5e" alt=""><figcaption><p>Example of passing additional value </p></figcaption></figure>

You should also use this custom event when you create a new Thing. You create the Thing in step 1 and send it to the Custom event in step 2:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F4KHTDunREY9TI1cYlCMt%2FScreenshot%202022-10-03%20at%2012.32.05.png?alt=media&amp;token=0447bb80-dac2-45d9-ba31-568dd3f8775e" alt=""><figcaption><p>Create a User and save all the fields in the custom event.</p></figcaption></figure>

{% hint style="info" %}
This principle applies to all data types and not just only to the User data type.&#x20;
{% endhint %}


# Source Popup

Declutter your data sources

To centralize the management of data points in your app, we default to using a Source Popup. A singular reference point for your data sources. By default, all [pages](/core-concepts/pages) have this popup.

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FoLHnbq3e1H6dhSCrLhhT%2FFDB99BAD-97E8-4C7A-8CE9-0596F32D3B52.png?alt=media\&token=1d652fb7-d60a-4f34-a2da-7a4f9479845c)

Group naming should follow: 🚩 Source - \[object]. If you want to read more how we name elements read [this article](/working-with-the-framework/best-practices/syntax).

Because we follow the convention of using UID in the URL, we can reuse the same parameter as a different source for different data types.

For example, by selecting type Customer in the 'Get from Page URL action, the UID will be recognized as a Customer data type.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FnRfXWdT6xWB9LgoGs631%2FScreenshot%202022-08-26%20at%2010.22.25.png?alt=media&amp;token=d75425ce-7fe8-4200-8726-a222a9bcb719" alt=""><figcaption><p>By selecting type Customer, the UID will be recognized as a Customer data type.</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F3IBby5S2eEBktXrwWBYZ%2FScreenshot%202022-08-26%20at%2010.21.26.png?alt=media&amp;token=1b8ee924-e510-4796-8310-34855ff61831" alt=""><figcaption><p>Now the same uid text is a Product</p></figcaption></figure>

Then when loading the User details section we can refer directly to the source. Thanks to the used icon and naming convention, it creates nice visual consistency in the editor's UI, especially when used in workflows and conditionals. &#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FfM6DngJFTTxPICj5lhMI%2FScreenshot%202022-08-26%20at%2010.24.51.png?alt=media&amp;token=663114d2-ba65-4b65-bed8-5771aede96df" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
When working with single-page apps, a good practice is to add the 'Reset data' action when navigating to reset the section that displays the data. Bubble sometimes does not overwrite the inputs and group values correctly with new data, especially when new data contains some empty field values which can create bugs when saving the object.
{% endhint %}


# Backend Workflows

All workflows that do not run on the page

Backend workflows are workflows executed on the server side of your application. In principle, the heavy actions that run on the backend should be at least a couple of times faster because they are use server resources and not the client. And because they are run server-side they will use your app's available capacity.&#x20;

Rule of thumb: you should use backend workflows for data changes that require substantial resource availability like the creation of dozens and dozens of database things, making changes to the lists or the result of the change or creation of the object does not have to be immediately visible to the user.&#x20;

When you create or update a thing on the client side, Bubble is smart enough to display the change first for the User and then make changes to the database behind the scenes. Because of that sometimes it makes sense to build a workflow specifically for client-side as it will provide better UX (changes will be visible faster for the User). For example: adding an item to a shopping cart, or adding 3 newly created items to the list.&#x20;

Other advanced use cases are for example exposing your endpoints to communicate with 3rd party solutions via webhooks integration.

Read more about server-side actions in the [Bubble manual](https://manual.bubble.io/help-guides/the-bubble-api):

* [Database triggers](https://manual.bubble.io/core-resources/events/trigger-event#trigger-event)
* [Data API](https://manual.bubble.io/core-resources/api/data-api)
* [Recurring events](https://manual.bubble.io/help-guides/the-bubble-api/scheduled-workflows#set-up-a-recurring-event)

Read about how to secure your backend [in this section](/working-with-the-framework/security-and-privacy/authenticating-endpoints).&#x20;


# Users and Roles

openBuild adds a few fields to the default User data type.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FBHSrbpcHgKDpcI8oanfQ%2FScreenshot%202022-10-04%20at%2014.20.00.png?alt=media&amp;token=e66fd86f-aaf2-48f8-a7d2-bea95aa27359" alt=""><figcaption><p>User datatype</p></figcaption></figure>

These are:&#x20;

* avatar - by default pre-built pages and elements use this field to display User avatar
* firstName - user first name
* lastName - user last name
* fullName - useful in workflows. Remember to update the field whenever firstName or lastName changes. You can either do this manually or create a database trigger
* phone - user phone number
* userType - it's a field linked to the [User Type](/framework-elements/option-sets) option set.

Read about the rules around creating syntax for fields and elements [in this section](/working-with-the-framework/best-practices/syntax).&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F1ZMre8tgcaHz0G2njTLv%2FScreenshot%202022-10-04%20at%2014.26.56.png?alt=media&amp;token=cedec067-33cf-4e80-bb3a-98db66ded7ee" alt=""><figcaption><p>By default template comes with two option's available </p></figcaption></figure>

User Types are used to create security rules around users accessing data and pages. For example only admin users (i.e. User's with User type of Admin) should have access to the admin page or see certain data.&#x20;

{% hint style="warning" %}
Remember that if you do not see the data on the page it does not mean it's not accessible to 3rd parties in some other way. Read more about security [in this section](/working-with-the-framework/security-and-privacy).
{% endhint %}

In the framework, you will also find that we use the User type option set in [Security Reusable](/framework-elements/security-redirect).


# Signup, Login, Password reset

The keys to your castle

The openBuild framework comes with a reusable that handles Sign up, Log in, Reset passwords and much more.

The resauble is used on the login page and reset\_pw page in the framework.

### Signup

Sign up with email workflows and UI for social logins.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FBRLGiYBgXPQ5Tm5gHzL3%2FScreenshot%202022-09-23%20at%2013.06.46.png?alt=media&amp;token=639000cb-ad1b-430b-9437-911cfbabb816" alt=""><figcaption><p>Signup section</p></figcaption></figure>

Workflows connected to Signup section are in the 'Signup' folder.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fu9f9WwaeTdFtgVkDg2sv%2FScreenshot%202022-10-10%20at%2013.15.04.png?alt=media&amp;token=05de47e3-bcdc-4705-878b-6bc976cf5516" alt=""><figcaption></figcaption></figure>

By default, the new user has to accept the *Terms and Conditions* and *Privacy policy* to be able to signup. That's why we use the conditionals logic on the button and pre-built workflows for changing the state.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fq0poO6XSUf3jIVprLOMT%2FScreenshot%202022-10-10%20at%2013.18.07.png?alt=media&amp;token=890640d6-8de4-47f7-af12-d1e34813fe1d" alt=""><figcaption><p>Only when the T&#x26;C is accepted, the workflow runs</p></figcaption></figure>

Signup workflow triggers a SIGN-UP custom event, that depending on your app settings will trigger a confirmation email sequence or not. Read about it in [this section](#enabling-email-validation-workflows).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FF6kqoiDgDUQwMuw2HKHi%2FScreenshot%202022-10-10%20at%2013.19.24.png?alt=media&amp;token=ffc615e9-22e3-40a6-a4b8-2b1b3bafe58e" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FXIctendfjkZc75HL45Ct%2FScreenshot%202022-10-10%20at%2013.19.33.png?alt=media&amp;token=d6886e24-32a7-443b-a9c3-78b72c597830" alt=""><figcaption></figcaption></figure>

### Login

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FdyvfuMa4f8LszlbELe3I%2FScreenshot%202022-09-23%20at%2013.08.29.png?alt=media&amp;token=e0cd0edc-0889-42df-84d0-77d6a535ff58" alt=""><figcaption><p>Login section</p></figcaption></figure>

Two main events connected to the login section are:

a) 'Log the user in' action - that gets triggered directly on the button click. It is placed there to enable the user to submit the login when hitting 'enter',

b) 'LOG IN' custom event - by default, only the redirect action is placed in this custom event, but this is the Workflow where additional actions should be placed. The same custom event is used for 3rd party signup/login.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FoBcepFgXDGmtuF9n1ylf%2FScreenshot%202022-10-10%20at%2012.54.44.png?alt=media&amp;token=76784ab1-6a9c-4657-96cf-36273935f1a6" alt=""><figcaption><p>Actions run when btn.login is clicked </p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FP7KzPdSc5Y0PjJcKE2IO%2FScreenshot%202022-10-10%20at%2013.00.18.png?alt=media&amp;token=e0d2724c-a614-41ca-9ac1-39479105e991" alt=""><figcaption><p>'LOG IN' Custom event</p></figcaption></figure>

### Forgot password

In the reusable, there is a dedicated section with workflows connected to password reset.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FzWq9OOLPTFOx2bTkNEWv%2FScreenshot%202022-09-23%20at%2013.09.02.png?alt=media&amp;token=fed94001-ea45-463f-bdab-0b037200258e" alt=""><figcaption><p>Forgot password section</p></figcaption></figure>

When a user inputs their email we send it to a custom event called '📧 SEND RESET PASSWORD EMAIL'&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FoBBx9mugrkXxycs2KwXB%2FScreenshot%202022-10-10%20at%2013.38.48.png?alt=media&amp;token=8194ffa4-9f33-480b-8d74-383b64db2e04" alt=""><figcaption></figcaption></figure>

In the custom event there are 3 actions:

a) Send password reset email - native Bubble action to generate reset password token

b) Send Email - Reset Password Link - a standard email with information about how to reset your password and dedicated link&#x20;

c) Send Email - Activation Link - from the [admin panel](/core-concepts/pages/admin) you are able to send user invites to the new users. The email content of that invite is different than a standard Reset Password email. &#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FZAwNNTbNtW7oUucq8fTR%2FScreenshot%202022-10-10%20at%2013.52.06.png?alt=media&amp;token=695a7f76-6871-4df9-b6c3-f47bbe7b11ac" alt=""><figcaption><p>📧 SEND RESET PASSWORD EMAIL</p></figcaption></figure>

Section visible after successful submission of the 'Forgot password?' form. &#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FUcsY9cvOmDFr2j6KNAVC%2FScreenshot%202022-09-23%20at%2013.06.59.png?alt=media&amp;token=60e8672f-7295-41cb-91ba-a80b1a98984c" alt=""><figcaption><p>Check your email section</p></figcaption></figure>

After clicking the link in the email user will be redirected to the Reset password section.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FBSX9gC7OgKPzNbrqVZTU%2FScreenshot%202022-09-23%20at%2013.20.45.png?alt=media&amp;token=9f588262-4c93-4487-b6ac-8b01d31d04f7" alt=""><figcaption><p>Reset password section</p></figcaption></figure>

### Password strength checker

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FpaoWwSmWIbhHL1XgzaOf%2FScreenshot%202022-09-23%20at%2013.17.00.png?alt=media&amp;token=6f51e353-421b-4d4a-9d5e-0108e06f1822" alt=""><figcaption><p>Want a password strength bar or checkbox details?</p></figcaption></figure>

In the framework, you will find two versions of the password strength checker i.e progress bar or displaying password details. Both of them work independently so you can choose one that matches your app, or you can keep using both.&#x20;

### Login with magic link

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F486bYliUb1w16voQ3ctU%2FScreenshot%202022-09-23%20at%2013.07.23.png?alt=media&amp;token=43c5e206-340a-4611-aece-f56e6424ab24" alt=""><figcaption><p>Login with magic link section</p></figcaption></figure>

Same as with the Reset Password workflows, there is a dedicated Custom event to handle the actions connected to sending the user magic link via email.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FUjCxXNVM3Bd2WLYj0rvY%2Fimage.png?alt=media&amp;token=6012a185-fbc6-40d6-8c64-cfda6bac76f5" alt=""><figcaption><p>Creating the magic link</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FNzRm3blbPPCiWMX0NdyC%2Fimage.png?alt=media&amp;token=1dc30599-3343-47c0-9f8c-b4ac3042ef3b" alt=""><figcaption><p>Sending the link via email </p></figcaption></figure>

### Invalid password token

Currently, the reset password activation token is only active for 24 hours from the creation date. This time window is definitely restrictive so we handle invalid tokens via a better User Experience.&#x20;

In openBuild we take advantage of the error-handling feature that allows us to trigger an action whenever the User tries to use an expired token.

By default whenever a user requests a reset password token via the User Access Management reusable we create a link that contains his email in the URL. If you did send your user a reset password email without the email parameter, the pre-built workflow logic will also handle that user.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FK0eOjWynItDUjO2nqBP6%2FScreenshot%202022-09-23%20at%2013.28.05.png?alt=media&amp;token=7b9a72c5-00c5-451f-9d5b-2d65d13b81a5" alt=""><figcaption><p>Catching the Invalid token error</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FVfl7cZv0Jxktbozlae2h%2FScreenshot%202022-09-23%20at%2013.25.02.png?alt=media&amp;token=b71d1c32-1978-4815-8fc4-40094f6511cb" alt=""><figcaption><p>If the is not email parameter this section will be visible</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fh74omUzgfQrrCrOUZpdx%2FScreenshot%202022-09-23%20at%2013.26.51.png?alt=media&amp;token=1a4f9ae0-b7b9-4570-86be-088f95f965bc" alt=""><figcaption><p>If the is an email in the URL parameter it will automatically send the a new reset password / activation email</p></figcaption></figure>

### Email validation workflows

openBuild template comes with pre-build validation workflows. To enable them set the verifyEmail attribute in 🔒 System option set to 'yes'.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F92Rr7QrXv66UCMElezEu%2FScreenshot%202023-04-03%20at%2011.08.46.png?alt=media&amp;token=ac7f193f-9f5c-4dba-88ae-e1a2758951bb" alt=""><figcaption></figcaption></figure>

If you enabled the email verification workflows, after the Signup we trigger CONFIRM-EMAIL custom event.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F1PC2N6Obk5FVap1fHfVd%2FScreenshot%202022-09-23%20at%2016.14.10.png?alt=media&amp;token=146174dd-1611-4c2f-aa3b-8cb93896ffea" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FxJ9coysH6nCeBCtTDdR9%2FScreenshot%202022-09-23%20at%2016.17.03.png?alt=media&amp;token=e5e3c30c-9472-4e1a-b826-ca671b81f4e8" alt=""><figcaption><p>Sending confirmation email</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FtBn9ozWhQmmRorIo8hyZ%2FScreenshot%202022-09-23%20at%2016.17.10.png?alt=media&amp;token=ec38cc76-b813-4115-8615-8083587fba3b" alt=""><figcaption><p>Redirecting to verify page</p></figcaption></figure>

In the verify page you find two sections.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FmD0JV2idOunSFMx4wy5c%2FScreenshot%202022-09-23%20at%2016.19.41.png?alt=media&amp;token=d4ce7181-5c93-4bfe-95c1-6bf2cd7f856b" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Remember to correctly connect redirect workflows to your app pages.
{% endhint %}

Additionally in the [🔐 SECURITY REDIRECT](/framework-elements/security-redirect) you find a disabled workflow that needs enabling if you want to block access to the app for every user who does not have his/her email verified.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fi9YLWuuHKA6cV8Nk6zcP%2FScreenshot%202022-09-23%20at%2016.23.21.png?alt=media&amp;token=ef6581da-2ba7-4e09-9f91-026ff6852939" alt=""><figcaption></figcaption></figure>

## User Access Management in a popup


# Security & Privacy

### Password policy

Bubble allows you to set up a password policy for user sign up. Stick to password best practices and force your users to create a secure password. The [User Access Management ](/framework-elements/user-access-management)element has a password validation workflows so users understand if their password is secure enough.

### Limit access to your app with a password

By default, Bubble requires a username and password to preview the development version of your app. It's a good practise to create a secure username and password during the development of your application. When someone knows the Bubble app name of the application you are developing, he or she can access the development version as you are building you app. You would want to avoid this for obvious reasons.

### Redirect rules

You may want to limit access to certain app pages for specific users or user roles. By setting up a [User Role](/working-with-the-framework/users-and-roles) on your users you can create workflows on your pages to redirect users away from that page. You can also use the 'user is logged in' or 'not logged in' expression to prevent users from accessing pages or content they should not have access to.

As the page can load data for a brief moment the user navigates to it, you can add additional security on your content groups, unhiding it for certain users.

There is a dedicated reusable element (Security Redirect) to handle redirects, you can read more about it [in this section](/framework-elements/security-redirect).

## Workflow API

When you use API/backend workflows, the endpoints you create can be accessed publicly unless you specify otherwise.

#### Expose as public endpoint

When an outside service needs access to your application, check this box. Otherwise the endpoint will never be visible from outside your application. If you create an API workflow for internal use only, you can uncheck this box.

#### Run without authentication

Your app has a private key that you can use to sign API requests. If you want a service or user to run the workflow without authentication (non-logged in), check this box. If you need to expose your public endpoint there are multiple ways you can secure it. Read more about how to authenticate your endpoints[ in this section.](/working-with-the-framework/security-and-privacy/authenticating-endpoints)

#### Ignore privacy rules

If you want the workflow to run as an 'Admin' user, having access to all data, check this box. Be very careful with this checkbox as it could potentially allow outside services access to running workflows that could potentially harm your application.

## Privacy Rules&#x20;

#### Privacy rules basics:

* View all fields: If unchecked User will not be able to read/display the field in UI and in workflows.
* Find this in searches: Limitation applies to do a search for repeating groups but if you use single Unique Id e.g. when displaying Product details then he will be able to access that data (only when he can view those fields)
* Exposing data without having privacy rules setup will allow 3rd parties to easily access data.
* Authenticating webhooks: see article → API's endpoints Authentication&#x20;

#### Advanced:

* If element referring to the data point is not rendered on the page data is not loaded on the page. The exception of this rule is loading data in repeating groups - even if the data is not displayed in repeating group, it is loaded on the page. Keep this in mind when creating privacy rules.
* As we do work a lot with repeating groups keep in mind that Privacy rules can break the ‘auto-refreshing’ of data on the page.
  * For example: If you give access to data type on page load, the page needs to be refreshed for Bubble to fetch the data again, now under different privacy rules.
* Also Privacy rules block access from accessing that data, but they sometimes show empty cells in repeating group etc. Best practice is to setup searches with constraints and privacy rules at the same time.

### File security

If you store files with sensitive information - you need to attach the images to datatypes for best file security. From Bubble manual:

* *This option is only visible if 'Make this file private' is selected. Private files uploaded with this element are permanently attached to a thing, which is used to determine who has access to view the file. Only users who have the 'View attached files' permission for that thing can view the file. Go to the Privacy section to create privacy rules that grant this permission. If the value of 'Attach this file to' is empty or the thing does not exist, the file will be visible to anyone who has the link, which is the same as if 'Make this file private' was not selected*

Files that are not attached to an object and exposed long enough will be vulnerable to a data breach.&#x20;


# Authenticating endpoints

Authenticating endpoints is a secure way to run workflows as admin of the app. Workflows will not get initiated if they are not authenticated.

<figure><img src="https://codahosted.io/docs/jX3dbcWciM/blobs/bl-OIDm5MfXNo/1112fa27456d38caec1779143c418e08fa32dbe8ab64b195fa6d19323a4c92101e6ad60bb7981b284de11eeb86e890f084ed80df679b1ef158dafc9395623bd40f4f08e3f48c44d0fb42717b3d9c858ff156668642ff89c3cbd33f346abf2f57a845583a" alt=""><figcaption></figcaption></figure>

### Method 1: Include the Authorization header in the call.

a) Generate a token in settings

b) Include the header 'Authorization' in your call. Use 'Bearer' + TOKEN as the value.

<figure><img src="https://codahosted.io/docs/jX3dbcWciM/blobs/bl-HxUGuwsyHB/74cf90f86d9b6a30b75e03e64bb6b88a309e2f1c9e9dd226948e8d205770f1d6e24de45ed1d3a88d32ddbef7bf3d83e762f4ab4f14b3a52b37ac7bb1fa4d2701981142dbd4908b462271b0ba90e093311bd5a57b7b5c13f1931535bcbb21c251a9a3bcb3" alt=""><figcaption></figcaption></figure>

<figure><img src="https://codahosted.io/docs/jX3dbcWciM/blobs/bl-8HHirbVHwW/5923542d9c9b70120c6a2000f6d74f03b84790c1d156f23fa0f40bfd2d88bfc6fbf756df294daa73207c165c2635ddf703b9016af469a407170bfdbcdeb55f7ee01e61dda422ba25bf76d12f37a36caa76217311281f8582e32b31c1d557c9350840ea2d" alt=""><figcaption></figcaption></figure>

### Method 2: URL parameter

If you are working with 3rd party API's and you are not able to add Custom header, include 'api\_token' parameter in the URL when making the call.

```
POST: https://app.bubbleapps.io/version-[env]/api/1.1/wf/create?api_token=TOKEN
```

### Method 3: Act on behalf of a API User

a) Create API endpoint that contains Log in action as a workflow (Have user created within your app or you can have a signup workflow before login action to create a new user)

<figure><img src="https://codahosted.io/docs/jX3dbcWciM/blobs/bl-6u2EvRPqGC/57e111c032766132738c8865a562b395ae838a87c679f7745d7315dd4e4d445dc7e684b859730a7af224681d13fc43584be7e406b6dc2d608ef30d8bafd559ffe4ec903f0ade79756938ca57f10f0808491e910e2f7e5f105a654725e51e4c45ea17e415" alt=""><figcaption></figcaption></figure>

* Setting the field “Stay logged in” to ‘yes’ will give you token valid 365 days.
* Setting the field “Stay logged in” to ‘no’ will give you token valid 24 hours.

b) Initiate the endpoint via Postman or API connector. The response of the api will look like this:

```
{
"status": "success",
"response": {
"token": "1646485307119x480839771339487600", // API TOKEN Generated
"user_id": "1646485006806x789796348942187500",
"expires": 31536000 // valid 365 days
}
}
```

In the response, you will get an API Token (valid 365 days) that will allow you to create an endpoint with the 'require authentication' option set to run the workflow, but all subsequent actions will have access to the data as that User and Privacy Rules set to that User (e.g. you can set a special Privacy Role set to that only API User, etc.)

\
c) see Method 1 or Method 2 to authenticate the endpoint.

<figure><img src="https://codahosted.io/docs/jX3dbcWciM/blobs/bl-qureU5Zduk/4a317d7bc9dfa6cec15891b6083c0ec1c0cd818b5da251c19713650f062a1e4c0c38d4ec774df0d9eb3b3482a5007062a0d7ee685719ff8a4a4b4844acb5a63af6db5ddec60a442656f889795ab88e4d7240188a4ffe424fe99eeeda9dd179884ac5ccea" alt=""><figcaption></figcaption></figure>


# Transactional Email

Send beautiful branded emails from your app 🤩

openBuild allows you to create beautifully styled and versatile emails, managed through the Mail Management reusable and sent with Postmark or Sendgrid. You can put the 📧 MAIL MANAGEMENT reusable on any page. By default it is part of the Admin page.

{% embed url="<https://www.youtube.com/watch?v=ycA9jT1UJnE>" %}

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FDPCVQgknPVzNVNF8Cqda%2Freusablemail.png?alt=media&amp;token=5e234679-6243-4888-b0ea-11c101f4d49e" alt=""><figcaption><p>You can put the MAIL MANAGEMENT reusable anywhere you want in your app</p></figcaption></figure>

By default openBuild comes with 4 default emails that you can change to your liking.&#x20;

* User email invite&#x20;
* Magic link login
* Activation email&#x20;
* Reset password

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FOlFiiIdQ7HhB6zjniXCM%2Fmails.png?alt=media&amp;token=923c9da0-4780-4dd3-888e-fd28d2a05e2e" alt=""><figcaption><p>Four default emails that you can edit, clone or delete</p></figcaption></figure>

## Creating and using transactional email&#x20;

There are 4 steps to creating and sending an email&#x20;

### 1. Set up your transactional email provider

&#x20;openBuild supports [Postmark](/working-with-the-framework/transactional-email/setup-postmark) and [Sendgrid](/working-with-the-framework/transactional-email/setup-sendgrid) but you can use many others.

### 2. Create your email

Create your email with a name and all the fields you want to add.&#x20;

Add dynamic content with the {{var}} notation. For adding a user’s first name you could use {{var1}}. For other dynamic data you use {{var2}} etc.&#x20;

Use the Var list field in each email to make a note of which {{varX}} belongs to what dynamic data.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FJ8zIftJVdJYVoevl7jwL%2Fcreatemail.png?alt=media&amp;token=0a57029d-2ff3-4330-8048-29effb67fe79" alt=""><figcaption><p>Create your email in the email builder and see a live preview.</p></figcaption></figure>

### 3. Test your email (optionally)

Instead of having to invoke the workflow that needs to send this email, you can test it in the Send Email tab. Note that it will not send dynamic data.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F7q0vTuKrUUxLrqQ6CWck%2Ftestmail.png?alt=media&amp;token=b067a96d-f634-407a-bc9a-28b58aa3519e" alt=""><figcaption><p>Test your email with a sender address you validated with your email provider.</p></figcaption></figure>

### 4. Send your email from a workflow with variables

Go to the workflow that should send the email and add the following action: Schedule API workflow.&#x20;

Select Send email and enter all the data to send.&#x20;

To select the right email, go to your mail management and find the email in the list.&#x20;

Click the copy button to copy the ID.&#x20;

In your action, for the email field, Do a Search for Emails with a constraint of unique ID is the copied UID of the email to send.&#x20;

For dynamic content use the Var list and check the email var list to understand what dynamic data is var 1, var 2 etc.&#x20;

Run the workflow to test if your email was sent successfully with the correct data.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FOlrgWXFbgNKyZecmeGnP%2Fsendemail.gif?alt=media&amp;token=a852277d-0354-4b4f-b11f-7cca9a9af307" alt=""><figcaption><p>Create a workflow to send your email</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FkdQvgsaQ3woFkxa5YhUm%2Fmailworkflow.png?alt=media&amp;token=736330c1-43af-4b04-813b-9a5795de2231" alt=""><figcaption><p>Simply schedule the API Workflow 'Send Email' with the parameters you need to send your email.</p></figcaption></figure>

## Anatomy of 📧 MAIL MANAGEMENT

&#x20;The 📧 MAIL MANAGEMENT module consists of:

#### **Reusable**&#x20;

**📧 MAIL MANAGEMENT** - with all the screens and workflows to create and update transactional emails.

#### Data Types

Email - the Data type that stores your emails. It contains the actual escaped HTML used to send the email as well as all the other fields that (could) make up your email like headers, body, images etc.

Email Footer Link - when you want to create footer links for your emails (and select which ones you want to add to which emails) you create an Email Footer Link in the Mail Management module. It is stored in the database as this data type.

Email Template - all the HTML and escaped HTML required to display your emails as previews in the mail management module and required to assemble your own unique emails. You would not need to touch this unless you want to change your email template.

**Workflows & Actions**

📧Send Email API Workflow

Sendgrid - Send Email - for sending Sengrid emails

Postmark - Send Email - for sending Postmark emails

{% hint style="info" %}
You can delete either the Postmark or Sendgrid action if you do not use them or add a condition to not run it (eg. 'When current date/time is empty'.)
{% endhint %}

## Sending custom emails

You can send your own custom html emails as long as you escape the html.

1. Escape your HTML (for example using <https://www.freeformatter.com/json-escape.html>)&#x20;
2. Create a new Email data type in the bubble editor.&#x20;
3. Give it at least a name and paste the escaped html in the html field
4. If you want to use dynamic content, make sure to add your {{var1}}, {{var2}} etc. in your escaped HTML&#x20;
5. Use the email the same way as the other emails for sending.


# Setup Sendgrid

{% hint style="warning" %}
If you verify only a single sender in Sendgrid, you can only send from that email address. Other email addresses will not be accepted unless you verify your domain.&#x20;
{% endhint %}

Go to sendgrid.com and register for a free account. Then, navigate to Settings > API Keys and Create a new API Key.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FXoGxmKivOGFZzTkkvq64%2Fimage.png?alt=media&amp;token=46bdbae9-5757-4080-9b5c-585fdb8abf73" alt=""><figcaption><p>Create an API Key with the settings you need. Full Access is usually enough.</p></figcaption></figure>

Then, back in your Bubble editor, navigate to Plugins > API Connector > Sendgrid and enter the API key you just generated in the Authorization header. Make sure it's preceded by 'Bearer'.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F80gN2ZKjJwL9LZ5IjrOe%2Fimage.png?alt=media&amp;token=de1cdf1b-b053-4680-baee-32adb7db92f8" alt=""><figcaption></figcaption></figure>


# Setup Postmark

{% hint style="warning" %}
Remember to confirm at least one Sender Signature inside the Postmark console. Only that email will work for sending emails. Or verify your entire domain.
{% endhint %}

Once you signup for the Postmark service pick the server you are going to use:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FCQEBArA2lpku63vG9p4h%2Fimage.png?alt=media&amp;token=9153d2c5-9924-4846-9954-7a34a558b01b" alt=""><figcaption><p>By default it's going to be 'My first server'</p></figcaption></figure>

Once in the right Server space go to API tokens and copy the Server API token and past it into the API call:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FK0JT62gVZ0SWLvN6QW9b%2Fimage.png?alt=media&amp;token=82aad6a7-56b9-4d18-a102-c913b06f6c43" alt=""><figcaption><p>The API Key</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FOygshxStKGlNT9lPkjuT%2Fimage.png?alt=media&amp;token=a83b1d91-8f7d-419a-9bb1-c59c7508ceaa" alt=""><figcaption><p>Paste inside the API connector in your Bubble editor</p></figcaption></figure>


# Alerts and Confirmations

### Toasts

{% hint style="warning" %}
This documentation is based on openToast plugin. Read more about it [here](https://bubble.io/plugin/opentoast-1583999894901x139148699044937730).
{% endhint %}

In all pages and reusable elements, you find a Custom event called 🔔 TOAST. When triggering it there are two required parameters to fill:

a) Message - this is the text that you want to display to a user.

b) Toast Category - this parameter is linked to the 🔔 Toast Categories option set. By default, you can pick Error, Success, or Info as the type oftoast.

Read more about this option set [here](/framework-elements/option-sets#toast-category).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FPXUyscWnKVzUkkljaCgW%2FScreenshot%202022-10-10%20at%2016.37.38.png?alt=media&amp;token=b26fd395-5f69-455e-be53-deae4e2a99d8" alt=""><figcaption><p>Required parameters</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FH3xjklXnfMWTezxSPPhF%2FScreenshot%202022-10-10%20at%2016.37.51.png?alt=media&amp;token=971011c3-a1a6-4c21-862d-65ed5fec5501" alt=""><figcaption><p>Toast action</p></figcaption></figure>

You can easily customize the toast by adjusting the settings on the action.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FgyYICYmiVOIpB1yap0qC%2FScreenshot%202022-10-10%20at%2016.48.01.png?alt=media&amp;token=779f7a20-a247-44b0-8d3c-7fb74cbeca81" alt=""><figcaption><p>Default look for the different toast types</p></figcaption></figure>

{% hint style="info" %}
You might consider using the App text for storing the contents of the messages for easier management. Read more about App text in [Bubble manual](https://manual.bubble.io/help-guides/customizing-an-application/language-and-app-communications).
{% endhint %}

### Confirmation popup

For longer or more complex messages it's better to use a dedicated section inside a popup.

Following our principles of using reusable elements, creating a confirmation popup to message the user is very easy.&#x20;

Read how to add new section in 🍿 CRUD POPUP REUSABLE [in this section](/working-with-the-framework/data-and-workflows/working-with-reusables#step-by-step-how-to-add-a-new-group).


# Customization

Basic configuration of the template (outside the styles) is done by managing two options sets 🎨 UI Colors and 🔒 System.

### 🎨 UI Colors

All 9 options are connected to elements used all over the app and also components from the openBuild extension.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FstPMNL5OZJshvhCTonhy%2FScreenshot%202022-10-10%20at%2016.28.01.png?alt=media&amp;token=38bbc03b-18ed-4d28-ad53-57e5f0bcc169" alt=""><figcaption><p>UI Colors option set</p></figcaption></figure>

### 🔒 System

In this option set you will basic app settings and as well branding options connected to images used throughout the app. (Such as header logos, logo's in email, etc.)&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Foh38TtIh9nmrr8vAW9Cc%2FScreenshot%202022-10-10%20at%2016.31.25.png?alt=media&amp;token=7c6ba87e-ce78-4f86-a73a-edcc46fcf45f" alt=""><figcaption></figcaption></figure>


# Best Practices

Some tips from the experts

Here are our best suggestions on how to work within the Bubble editor.&#x20;

* [Syntax](/working-with-the-framework/best-practices/syntax) - learn how to name database fields, elements, backend workflows
* [Color coding](/working-with-the-framework/best-practices/color-coding) - learn how to keep your workflow tab clean so you can work efficiently&#x20;


# Syntax

### Database

We recommend the [Camel case](https://en.wikipedia.org/wiki/Camel_case) naming convention when it comes to naming database fields.

> Camel case is the practice of writing phrases without spaces or punctuation, indicating the separation of words with a single capitalized letter, and the first word starting with either case e.g. firstName, lastName, fullDescription.

When linking to other data types follow the upper camel case method which uses an initial uppercase letter e.g. when the User have a field linking to a company data type: Company.&#x20;

Following this convention you will know that fields starting with uppercase are linked to other data types and those starting out with lowercase letters are fields saved directly on the data type (such as text, numbers, and dates).

Linking field to option sets should start with lowercase.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FCgCgZNIapTzMEELXLmZK%2FScreenshot%202022-10-12%20at%2014.09.14.png?alt=media&amp;token=c260c4ae-5e88-487a-b0cb-c835a725528d" alt=""><figcaption><p>User datatype</p></figcaption></figure>

### Inputs

All inputs elements should follow this syntax:

`object.input-type.field e.g.` [`user.input.email`](http://user.input.email) `should be used to modify the User’s email.`

Thanks to this convention searching for the right input will be fast and easy, as you will have multiple points of reference to the input and they are distinguished enough visually to locate them in the conditional dropdowns and field searches.&#x20;

![](https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FvK9vywMOATipwSnTfmFI%2F0CF784BC-6ED4-4A90-85C3-7CC81DA1497F.png?alt=media\&token=52c6b182-0473-4764-96c4-cab8403afb93)

### Elements

When building in the app logic most of the time we heavily really on referring to elements that store values.

{% hint style="info" %}
Read how to centralize the data management on a page in [this section](/working-with-the-framework/data-and-workflows/source-popup).
{% endhint %}

Ideally, the naming convention makes things easier for the developer to build fast and the most important factor enabling that is searching for the elements from the workflows tab:

Conditional dropdown:

* When using a group as a data source its best to keep the same naming conventions for all of the source groups and as well using visual cues that will help us find and locate it faster:
* Source: e.g. 🚩 Source - Property

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fr0dwQeawuiLeBCSApkhx%2FScreenshot%202022-10-12%20at%2014.25.43.png?alt=media&amp;token=7514e12b-da2f-41af-98a3-5aede8d0ada6" alt=""><figcaption><p>Texts and inputs referring the  🚩 Source - User</p></figcaption></figure>

Actionable elements such as buttons, icons, texts, link and other group elements follow this convention: *\[elementType].\[actionType]*

e.g btn.createUser, icon.toggleMenu, group.closePopup

{% hint style="info" %}
Tip: Best to rename things as you go, doing it all at the end of the build is not efficient in our experience.
{% endhint %}

### States:

States should follow the same naming convention as database fields. We recommend using Icon indication to see its representation in actions ⚡️ e.g. ⚡️Product. The icon will act as another visual cue that will help you distinguish between custom states and other input types.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FcaagiVIXabFCJ9psAIPa%2FScreenshot%202022-10-12%20at%2014.13.52.png?alt=media&amp;token=5c67cac9-5092-48a2-b098-8a0eaaeb9ec9" alt=""><figcaption><p>Setting state</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FhcbGljlTcrJKTIIpdBXL%2FScreenshot%202022-10-12%20at%2014.14.22.png?alt=media&amp;token=103bef7f-e29f-4b19-9b8e-f63ad68648b4" alt=""><figcaption><p>Referring to states in searches</p></figcaption></figure>

### Custom events:

For better organization and reading experience, we recommend naming all custom events workflows with capitalized letters and icons, which play a supporting role in distinguishing between different types of custom events.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fqd5DrErJNzpYww7uRBvd%2FScreenshot%202022-10-12%20at%2014.20.49.png?alt=media&amp;token=b81bd63d-73f3-499b-b803-acbd51ccdd08" alt=""><figcaption><p>ustom events among other workflows</p></figcaption></figure>

### API Workflows

Endpoints naming convention should use a dash when using multiple keywords:

* e.g. <mark style="color:green;">send-email</mark> vs <mark style="color:red;">sendemail</mark>

General tips:

* Avoid using jargon e.g. <mark style="color:green;">email-update</mark> vs <mark style="color:red;">ems</mark>
* No abridging e.g. <mark style="color:green;">phone-update</mark> vs <mark style="color:red;">tel-no</mark>

{% hint style="info" %}
There are exceptions to this rule which is making the API endpoint public. You might consider making the endpoint more cryptic especially if you are not using authentication. (See can read about webhook authentication [in this section](/working-with-the-framework/security-and-privacy/authenticating-endpoints))
{% endhint %}

### Workflows

Try to be descriptive when renaming your actions or workflows.

* Make a change to the Current User -> Update Current User Personal Data
* Scheduled API workflow -> API: Send Invite Email
* Make changes to thing... -> Add new Project to Company&#x20;


# Color Coding

This is how we currently take advantage of color coding of the workflows:

* Brown - workflows that are pre-built in the template. Any added workflows that are working and in live.
* Red - modified but not finished workflows that need follow-on work
* Cyan - modified or newly added workflows that are finished and tested.

When pushing live we keep the Cyan color for newly added workflows. After deploying we change these to brown only in the development version. Now live version contains Cyan & Brown workflows and we know that Cyan workflows are workflows that were just pushed live. That makes debugging a bit easier as you can see which workflows were changed compared to the previous live version.


# Chrome Extension

In progress!


# Menus

### ⇥ Popup Mobile Menu.&#x20;

Admin page and all page templates come with a pre-build ⇥ Popup Mobile Menu.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FqMTkJpQY2Ox0Z54gVsxo%2FKapture%202022-11-05%20at%2010.47.37.gif?alt=media&amp;token=dded47ae-c073-4ff5-9c83-9fa92f8abce8" alt=""><figcaption><p>⇥ Popup Mobile Menu</p></figcaption></figure>

### 🔄 CONTEXT MENU

In the User table on the Admin page you will find an example of using 🔄 CONTEXT MENU reusable element.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FK8md6XH2ojbYhWT2vb7l%2FScreenshot%202022-11-05%20at%2010.37.00.png?alt=media&amp;token=12d36c97-fffe-4f16-aac5-42ee93e4f5db" alt=""><figcaption><p>🔄 CONTEXT MENU</p></figcaption></figure>

### Pages

Per [page](/core-concepts/pages) template you get access to the following menus:​

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqQQPMcY8thnmAuEFBbEe%2Fuploads%2FA6vftiWU1tjv9yi4YnW5%2Fimage.png?alt=media&#x26;token=c578b98d-6e69-4253-adc8-a2d49bc53bb9" alt=""><figcaption><p>base-menu</p></figcaption></figure>

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqQQPMcY8thnmAuEFBbEe%2Fuploads%2F5aA8iyVUILgp4sMQ3iHX%2Fimage.png?alt=media&#x26;token=edbbf6e5-ce47-46e3-9119-5d871cce115e" alt=""><figcaption><p>base-top</p></figcaption></figure>

<figure><img src="https://files.gitbook.com/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FqQQPMcY8thnmAuEFBbEe%2Fuploads%2FqIt4zu2kYdXhGInnOROV%2Fimage.png?alt=media&#x26;token=8f595b44-9e92-4d30-89c3-a449bf545132" alt=""><figcaption><p>base-ribbon</p></figcaption></figure>


# Option sets

A list of all the option sets we use in openBuild (and why)

### 🔒 System

Main option set to manage your app-related assets and content like the app name or logo. Read more about it [in this section](/working-with-the-framework/customization#system).

### 🔔 Toast Category

Option set listing the type of Toast Messages. These are linked to the [Tag Colors](#tag-colors) option set. This option set is used for Alerts and linked to a Custom Event called 🔔 Toast used throughout the app. Read how it works in [this section](/working-with-the-framework/alerts-and-confirmations).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FWwOwIMUYyBqJAV39zXdS%2FScreenshot%202022-10-10%20at%2016.41.26.png?alt=media&amp;token=4923bbcf-0a20-4d61-877e-8eff380012c3" alt=""><figcaption></figcaption></figure>

### 🎨 UI Colors

UI Colors option set is used on top of the Styles in the app.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FLUIGhja7vOdlzALJHfO9%2FScreenshot%202022-10-18%20at%2013.37.06.png?alt=media&amp;token=410bbe7c-1b5f-4c12-a2e2-5f180d90364d" alt=""><figcaption><p>UI Colors display. Find yours on /styleguide page</p></figcaption></figure>

### 📱Viewport

The viewport option set is used throughout the app to give you granular controls on your responsive design.&#x20;

### User Types

Using a predefined user type will help you in setting permission rules as opposed to using a simple text field that is error-prone. By default you find two options in the User Types option set:

* Admin - administrator of the app. This type has access to the admin page.
* User - normal app user.

You can add as many User types as you want, but it's good practice to keep the list simple. If you need more flexible way to control what User can see and do, you might consider creating a Permission option set.

### Tag Colors

Tag Colors can be used by directly referring to it from the editor or it can also be used by linking it to a database field.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F6dRsyb5DBDIRqcv2pkUc%2FScreenshot%202022-10-18%20at%2013.22.31.png?alt=media&amp;token=284d9f0c-3dc1-4ad8-a02d-8258ce72826a" alt=""><figcaption><p>TAG Colors table. See it on /styleguide page in the template</p></figcaption></figure>

### 🧭 Navigation

Using an option set together with Custom events will allow you to build faster and reduce the number of bugs when working with Single Page Apps and cross-page navigation. It also opens up more advanced possibilities such as creating complex onboarding experiences.&#x20;

Read how to use it in [this section.](/working-with-the-framework/navigation)

### 🧭 Element display

This option set is dedicated to creating navigation in elements that can be used throughout multiple pages. It is used mainly in combination with reusable elements such as [🍿`CRUD Popup`](/framework-elements/crud-popup) or [👥 User Access Management](/framework-elements/user-access-management).&#x20;

Read more about how to use it in [this section](/working-with-the-framework/navigation/navigation-through-custom-states).


# Plugins

A list of plugins openBuild uses by default

Two plugins are required when it comes to combining the template with the openBuild extension. These are:

* openBuild CSS - this plugin adds a header linking to a CSS stylesheet which is compatible with openBuild template. See the CSS included [here](/core-concepts/styles/custom-css).
* [Heroicons](https://bubble.io/plugin/heroicons-1662714551448x987904425844277200) - an Icon set from the Heroicons library. &#x20;

{% hint style="danger" %}
Working with the openBuild components library without these plugins installed in your app might create issues.
{% endhint %}

#### Other plugins:

* [Air Color Picker](https://bubble.io/plugin/air-color-picker-1498952719168x889602776416649200)
* [API Connector](https://manual.bubble.io/core-resources/bubble-made-plugins/api-connector)
* [OpenBuild Toolkit](https://bubble.io/plugin/openbuild-toolkit-1652100141816x544111532603605000)
* Google
* Google Material Icons
* [Ionic Elements](https://manual.bubble.io/core-resources/bubble-made-plugins/ionic-elements)
* [openToast](https://bubble.io/plugin/opentoast-1583999894901x139148699044937730)
* LinkedIn
* Multiselect Dropdown
* Progress Bar
* [Toolbox](https://bubble.io/plugin/toolbox-1488796042609x768734193128308700)


# API Connector

API Connector is a plugin made by Bubble allowing you to connect to any 3rd party API giving you access to tens of thousands external solutions. Read more about the basics of using API connector in [Bubble manual](https://manual.bubble.io/core-resources/bubble-made-plugins/api-connector).&#x20;

When it comes to the template, by default, you find pre-built API calls such as:

* Sendgrid - Send Email - basic POST call for sending emails with Sendgrid. It also works with attachments. Learn how to work email work with openBuild template[ in this section](/working-with-the-framework/transactional-email). (See Sendgrid documentation [here](https://docs.sendgrid.com/api-reference/mail-send/mail-send))
* Postmark - see documentation [here](https://postmarkapp.com/developer/user-guide/send-email-with-api).&#x20;
  * Send Email&#x20;
  * Send Email (with Attachment)

Check our extensive API calls library in openBuild.


# User Access Management

How users signup and login to your app

All users accessing the app, either through signup or login are managed through a single element reusable called [👥 USER ACCESS MANAGEMENT.](/working-with-the-framework/signup-login-password-reset)&#x20;

Its composes of the different pre-built and ready to use sections such as:

* Login&#x20;
* Signup
* Magic link
* Forgot password&#x20;
* Reset Password with password validation
* Activate account
* Reset success
* Link expired
* Check your email

You can read about different sections and workflows [in this section](/working-with-the-framework/signup-login-password-reset).


# CRUD Floating Group

🍿 CRUD FLOATING GROUP is a reusable element used for CrateReadUupdateDelete (CRUD) operations.

By default, its width is limited to 480px.  But you can change the max width of the reusable by changing the max width of the element inside the element or on the page itself. Read more about responsive design in [this section](/core-concepts/responsive-design).

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FKjcHIcFp9y1HgJdhNyv4%2Fadmin-crud-floating.gif?alt=media&amp;token=7db52fae-c9cd-4d31-b9c1-7e38afeb6e1d" alt=""><figcaption><p>🍿 CRUD FLOATING GROUP in action</p></figcaption></figure>

It comes with 2 template sections that can be copied and used to create new ones. These are:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FvufbWIiSepDK9apPCVNw%2FScreenshot%202022-09-23%20at%2010.13.31.png?alt=media&amp;token=e648bb48-30e4-4f9d-bc6c-a7fc7aba4d93" alt=""><figcaption><p>CRUD Template</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FpkT7u7c9Bh8sR7vdcQlk%2FScreenshot%202022-09-23%20at%2010.16.18.png?alt=media&amp;token=594f4660-9893-416d-bdea-4974e3a9c63a" alt=""><figcaption><p>MSG Template Icon</p></figcaption></figure>

CRUD Popup contains 1 pre-build and working section:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FAuBpkIijUB6wmfij2iOx%2FScreenshot%202022-09-23%20at%2010.30.26.png?alt=media&amp;token=5594b1c9-a18a-482d-aeb0-b5fdfe4e5a2b" alt=""><figcaption><p>CRUD User</p></figcaption></figure>

### Data manipulation and navigation

CRUD popup follows the framework practices like navigating with option sets and manipulating data using states.

If you want to learn more about passing data into reusables and navigating to different sections you can read about it in [this section.](/working-with-the-framework/data-and-workflows/crud)


# CRUD Popup

🍿 CRUD POPUP is a reusable element dedicated to performing CRUD operations and as well confirmation actions.&#x20;

By default, its width is limited to 480px. If you want to read about the UI Framework, read [`this section`](/core-concepts/responsive-design).

It comes with 3 template sections that can be copied and reused to create new ones. These are:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FvufbWIiSepDK9apPCVNw%2FScreenshot%202022-09-23%20at%2010.13.31.png?alt=media&amp;token=e648bb48-30e4-4f9d-bc6c-a7fc7aba4d93" alt=""><figcaption><p>CRUD Template</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FpkT7u7c9Bh8sR7vdcQlk%2FScreenshot%202022-09-23%20at%2010.16.18.png?alt=media&amp;token=594f4660-9893-416d-bdea-4974e3a9c63a" alt=""><figcaption><p>MSG Template Icon</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fa4tHjOXMd6O7Rpb6TRAk%2FScreenshot%202022-09-23%20at%2010.18.03.png?alt=media&amp;token=e806fb87-32e1-4bf9-b03d-4e0c7f1da666" alt=""><figcaption><p>MSG Template</p></figcaption></figure>

CRUD Popup contains 2 pre-build and working sections:

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FAuBpkIijUB6wmfij2iOx%2FScreenshot%202022-09-23%20at%2010.30.26.png?alt=media&amp;token=5594b1c9-a18a-482d-aeb0-b5fdfe4e5a2b" alt=""><figcaption><p>CRUD User</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FuNLSHspadEzdO2fnhnD0%2FScreenshot%202022-09-23%20at%2010.31.31.png?alt=media&amp;token=1cefe791-1536-48ff-88dc-91aee33eecf9" alt=""><figcaption><p>CRUD Delete - Users</p></figcaption></figure>

### Data manipulation and navigation

CRUD popup follows the framework practices like navigating with option sets and manipulating data using states.

If you want to learn more about passing data into reusables and navigating to different sections you can read about it in [this section.](/working-with-the-framework/data-and-workflows/crud)


# Data Table

### Table

Properties of the base table:

* Fully responsive
* Build-in  'Name' & 'Joned' field sorting
* [Pagination](#pagination)
* Multiselect - you can read more about how to store data temporarily on the page work in [this section.](/working-with-the-framework/data-and-workflows/custom-states)

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F4FIpc8i1MF5wFPva1x1A%2FScreenshot%202022-11-05%20at%2011.09.04.png?alt=media&amp;token=c978a587-510d-421b-9652-61655e21d456" alt=""><figcaption><p>User data table in admin panel</p></figcaption></figure>

### Pagination

The user table used on the Admin page in the openBuild template comes with a pre-built Repeating group pagination.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FXhv13ZjusejNUHOWgMaT%2FScreenshot%202022-10-14%20at%2013.37.02.png?alt=media&amp;token=38ad76a8-d8a2-4deb-9a4b-60d2e86994ad" alt=""><figcaption><p>Pagination is limited to display up to 5 pages in current view</p></figcaption></figure>

{% hint style="warning" %}
the Toolbox plugin is required for the pagination to work
{% endhint %}

You can edit the number of rows displayed and the pagination bar will update automatically. There is no need to update workflows or other element's values.

For pagination to work correctly you have to update the number of rows in the Repeating Group and as well the state of the repeating group called "rows".

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FlXY6Co9wZV6Dq8w5B6ry%2Fpagination.png?alt=media&amp;token=10a612ff-ed3f-4d01-bb46-5fd41604c4da" alt=""><figcaption></figcaption></figure>

{% hint style="danger" %}
If the number of 'rows' state will be different than the number of rows in the repeating group, pagination will NOT work correctly.&#x20;
{% endhint %}

#### Copying and pasting the workflows to new repeating group

If you already have a Repeating Group and are in need of pagination you can copy the 'Pagination' element with workflows.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F6Kcq0UugEZW340vOEovh%2FScreenshot%202022-10-14%20at%2013.44.58.png?alt=media&amp;token=0d3e614b-1026-4ce7-aa8e-59f23fe954a0" alt=""><figcaption><p>Pagination group</p></figcaption></figure>

You will then need to update all elements that are placed within the Fields group. These are 5 Group elements that hold numeric values which are used to calculate pagination.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F4hOabgrLxyy3MAFdV1pd%2FScreenshot%202022-10-14%20at%2013.52.28.png?alt=media&amp;token=6afe49f2-2b9e-4be6-81aa-07739ef56e31" alt=""><figcaption><p>Example of Group holding numeric value</p></figcaption></figure>

Additionally, there are 5 action elements that will need to update as well. With the distinction that you only need to pick the right Repeating Group from the list of elements

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F2HKAgESCNwDLEzKkGCka%2FScreenshot%202022-10-14%20at%2013.53.29.png?alt=media&amp;token=521bac78-c99d-4f0c-9b30-800918669fd9" alt=""><figcaption><p>Example action that will need to be updated</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FjwtfZYYDmgc0dQTLJnoh%2FScreenshot%202022-10-14%20at%2013.54.58.png?alt=media&amp;token=2013fd88-d269-4b05-9bf9-c702fcd94bf8" alt=""><figcaption><p>You will find example of action in folder 'Pagination: Users' in the admin page</p></figcaption></figure>


# Security Redirect

Keep unwanted users out

Security Redirect is reusable that is used to centralize access to your app pages. It contains only workflows used to redirect users to other pages based on conditional rules.

A logged out user or a regular user visiting the admin page? The Security Redirect has a workflow to navigate them away from the page.

&#x20;We put that reusable conveniently in the [Source Popup](/working-with-the-framework/data-and-workflows/source-popup) in every page to keep it from cluttering.

{% hint style="warning" %}
Remember that just redirecting the user from the page that he should not access is not enough to make your app secure. Make sure to always set the privacy rules on data that is sensitive. Check if your app is secure via [checkSo](https://check.tinkso.com).
{% endhint %}

The easiest way to set up redirect workflows in complex apps is by separating the workflows by pages and then putting extra conditional logic onto the actions themselves.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FYi9Ivdee6aSWkzYmdwV7%2FScreenshot%202022-09-23%20at%2016.28.44.png?alt=media&amp;token=42c2d921-4a8a-44c7-8aaf-39c9eea3beda" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F0yFftghuWavZN1yXSfZa%2FScreenshot%202022-09-23%20at%2016.31.02.png?alt=media&amp;token=f95f5e1f-02fb-445c-818a-ca98178ac2d6" alt=""><figcaption><p>Example of redirect the user if he is not an Admin user</p></figcaption></figure>


# Mail management

⚡️ Superfast email builder

We have implemented a dedicated page or section within the admin panel specifically for handling transactional email templates. This user-friendly interface enables users to effortlessly create and manage various email templates as needed. Additionally, you can customize these templates by incorporating dynamic variables, resulting in personalized that meets your specific requirements.&#x20;

This dedicated solution streamlines the process of creating, editing, and managing transactional email templates for a more efficient workflow.

### Email providers

openBuild Framework integrates with Postmark and Sendgrid. It uses the openBuild Framework default email template but can just as well be used with any other HTML email template.

### Mail Management Section

The interface and workflows you need to list your stored emails, edit those emails and add new ones, and as well test send them.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FRMzQp9GfSEH1dwgXSCVu%2FDashboard-openBuild%20(1).png?alt=media&amp;token=b58d5a64-5d0c-43cf-8c03-f4271b681d9e" alt=""><figcaption><p>Manage all app emails</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FpfYLiS5HpuPsetmez3Yh%2FDashboard-openBuild.png?alt=media&amp;token=c8f7b91a-53ae-4c52-b796-29bb1d39175e" alt=""><figcaption><p>Build and edit your emails</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F8UmEmoJmYoJvIZaN1Ywu%2FDashboard-openBuild%20(2).png?alt=media&amp;token=59c5108a-ebdf-4a29-896f-6c083161cafb" alt=""><figcaption><p>Send test emails</p></figcaption></figure>

### Dynamic Content

Sending emails from your application typically requires incorporating dynamic content, such as a customized greeting, password reset links, or other personalized elements. We achieve this through a 'variable' (or 'vars') system. A variable serves as a placeholder for any type of text, such as a name, a URL, or a reset password token.

When constructing your email, you can insert variables anywhere using the format {{varX}}, where 'X' represents the variable number. An email might have only one variable or multiple variables, like 10 or more.

There will also be a section for defining variables as you create your email, which ensures that everybody understands the intended content when using this email, stored in your app's database. For example, '{{var1}}' might represent a user's first name in one email, while in another, it could be a URL. The variable placeholders remain consistent across all emails, but you determine the specific content for each variable when scheduling your email send events. This approach ensures clarity and personalization in your email communication.

### Escaped vs html

Each email template comes in two versions: 'escaped' and 'html'. We need to escape special characters to prevent issues when sending emails via Postmark or Sendgrid's APIs. In the option set containing the Email templates, there are two fields for each template section:

1. The original HTML version, used for previewing the email in the mail management page.
2. The escaped HTML version, required for actually sending the emails.

This setup ensures smooth interaction with email delivery APIs and allows you to preview your email templates accurately.

### Using your own templates

To escape your own HTML template, use this free tool: <https://www.freeformatter.com/html-escape.html>

### Email Templates

This data type will be used to retrieve the default email template or a custom email template you created. It consists of all the sections that make up the email in two versions: escaped and plain html.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FNg8dAQqvNoyklMsxvq5X%2FScreenshot%202023-03-22%20at%2010.52.33.png?alt=media&amp;token=cfcd0afe-5abc-46b5-abf3-7d92ef450887" alt=""><figcaption><p>Email Template</p></figcaption></figure>

### Email Data Type

This datatype stores all your emails, including welcome emails, password reset emails, and others. We have included some example templates which can be found under the App Data tab in the Bubble editor.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fk6Urk9zuqUhyCGcdd8yA%2FScreenshot%202023-03-22%20at%2010.54.17.png?alt=media&amp;token=a70956b7-e4e1-4d8e-a1c6-0863ff406a47" alt=""><figcaption><p>Email Datatype</p></figcaption></figure>

### Send Email Action

When creating a new email using the mail management tool, it will be saved in your database as an 'Email' datatype. To send an email, you will need to provide the Unique ID (UID) of the email template you want to send within the 'Send email' action. Additionally, you should include any dynamic content that you want to incorporate into the email. This approach allows for efficient organization and customization of your email templates.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fm4rXCdtF1GT1G8lunNzS%2FScreenshot%202023-03-22%20at%2011.24.25.png?alt=media&amp;token=8213c40e-ea20-4f53-be3f-36d604f85c82" alt=""><figcaption><p>Send Magic Link Example</p></figcaption></figure>

### The Standard Template

openBuild Framework offers one, flexible, transactional email template that you can use for basically every email you need to send.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FTIAjU5rptlIZQlcqWWrb%2FScreenshot%202023-03-22%20at%2010.56.58.png?alt=media&amp;token=7e9b0ca6-a35d-4ffd-9ab1-e7ed569d35d7" alt=""><figcaption><p>Standard email template with show/hide section</p></figcaption></figure>

### System Option Set (optional)

The openBuild Framework employs a 'System Option Set' to store information about the app, such as the app name, default color, app email, and logo. While you are not required to use the information from this option set, it's important to consider the formats of the images you wish to display in your email.

For instance, if you want to display a logo or any other image in your email, refrain from using the SVG format, as most email clients do not support it. Instead, opt for image formats like JPG or PNG to ensure proper display across various email clients.

### Email Footer Links

This datatype allows you to manage the footer links you wish to include in your app. Each entry consists of a display name and an associated link. By default, the following links are provided:

1. Privacy - a link to the privacy policy page
2. Terms - a link to the terms and conditions page

Feel free to add any number of additional links, and they will be automatically incorporated into your email footer. This versatile option set makes customizing your email footer easy and straightforward.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FUP4OaVn1B7he5wPrt6wY%2FScreenshot%202023-03-22%20at%2010.59.17.png?alt=media&amp;token=96a2cf54-2c80-4d54-87f0-729556cdf91b" alt=""><figcaption><p>Email Footer Link Datatype</p></figcaption></figure>

### Send Email Workflow

The send email workflow is composed of two distinct actions:

1. On the client side, a backend workflow is scheduled, which determines when the email will be sent.
2. The actual email-sending action is then triggered by this scheduled backend workflow.

This structure enables you to schedule emails conveniently and effortlessly include variable content within the messages.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FL2S19AUHJUHe55GPvmGt%2FScreenshot%202023-03-22%20at%2011.13.36.png?alt=media&amp;token=2494255b-c2e1-41f5-8203-ebbf425e71e7" alt=""><figcaption><p>Scheduling Backend Workflow</p></figcaption></figure>

You will find 📧 Send Email API workflow in Backend workflows. This is the actual POST API call that will send the email via Sendgrid.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FtCRfFWzJZTMKti3th68N%2FScreenshot%202023-03-22%20at%2011.14.53.png?alt=media&amp;token=c21b6990-889f-4ca2-81f1-743714342f93" alt=""><figcaption><p>Actual Send Email Action</p></figcaption></figure>

### Using emails in live version of the app

After creating and testing your emails in the development version, make use of the [Copy and Restore Database](https://manual.bubble.io/core-resources/bubbles-interface/data-tab#copy-and-restore-database) feature. This allows Bubble to transfer development data into live data, maintaining the same unique ID for your emails in both versions. As a result, you won't have to manage two distinct workflows since the email record will retain the same unique ID.

{% hint style="info" %}
Make sure you only copy the Email data type.
{% endhint %}

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FekFmsOrJJoEwsPpnmLAb%2FScreenshot%202023-04-03%20at%2009.35.45.png?alt=media&amp;token=df71d94e-a38f-40a2-949c-b046153efdc4" alt=""><figcaption></figcaption></figure>


# User Settings

The framework comes with a pre-built User Profile section with working credentials update section.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fd4ir50rhuSqKQRdRshrx%2FScreenshot%202022-09-23%20at%2016.58.28.png?alt=media&amp;token=d1681c08-334c-4fe7-9dea-26973ab8bac4" alt=""><figcaption><p>Account</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2Fo5InTtZkq8RIcjKYwWTo%2FScreenshot%202022-09-23%20at%2016.59.30.png?alt=media&amp;token=8ca44d71-5113-4839-8a09-308a2f64dd51" alt=""><figcaption><p>Credentials</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FrlKX56Pntm8P2wm9cnk9%2FScreenshot%202022-10-19%20at%2010.14.50.png?alt=media&amp;token=20662a39-6262-44d0-8532-b591595bf4fb" alt=""><figcaption><p>Updating your password</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FRI8f7ZsYWrMTppYbZZR3%2FScreenshot%202022-10-19%20at%2010.15.07.png?alt=media&amp;token=b1b33ad2-19d8-4627-ac63-8eb8f2802d19" alt=""><figcaption><p>Updating your email</p></figcaption></figure>


# Header & Footer

### 🔄 HEADER

In the template, you will find a reusable element 🔄 HEADER, which is dedicated to website pages such us landing pages, faq, about us, team, terms, and privacy.&#x20;

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F3NdVKz0c1bVISurDfHtt%2FScreenshot%202022-09-23%20at%2012.49.23.png?alt=media&amp;token=208616ba-33c9-48a3-b037-e5c1f4f0bd74" alt=""><figcaption></figcaption></figure>

The element is responsive and comes with a Popup Mobile Menu.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FGj1ZNtjSknTSYZuMivMo%2FScreenshot%202022-09-23%20at%2012.54.21.png?alt=media&amp;token=35fad854-edb0-4ee1-9e20-7c7d85e18d60" alt=""><figcaption><p>Mobile Popup Menu</p></figcaption></figure>

### 🔄  FOOTERS

openBuild has two reusable footers that you can edit to your liking.

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2F4khiVQWkMH5AQtcipenD%2FScreenshot%202022-10-18%20at%2014.02.31.png?alt=media&amp;token=f02d9650-f465-470a-a7cc-df4b4cafe5bf" alt=""><figcaption><p>Dark</p></figcaption></figure>

<figure><img src="https://3323346004-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FW4eajJmOk3q8BX2WzhCG%2Fuploads%2FszJ1ngxKosqc8lTDEjCW%2FScreenshot%202022-10-18%20at%2014.02.40.png?alt=media&amp;token=d5c32ce8-5ea7-4dce-b10c-3a69a5071dd7" alt=""><figcaption><p>Light</p></figcaption></figure>


