# Table of Contents - [Introduction | Bubble Docs](#introduction-bubble-docs) - [New? Start Here | Bubble Docs](#new-start-here-bubble-docs) - [Web | Bubble Docs](#web-bubble-docs) - [Building for... | Bubble Docs](#building-for-bubble-docs) - [What is Bubble? | Bubble Docs](#what-is-bubble-bubble-docs) - [Native iOS and Android | Bubble Docs](#native-ios-and-android-bubble-docs) - [What is a native mobile app? | Bubble Docs](#what-is-a-native-mobile-app-bubble-docs) - [Native mobile vs. web development | Bubble Docs](#native-mobile-vs-web-development-bubble-docs) - [Mobile app quick start guide | Bubble Docs](#mobile-app-quick-start-guide-bubble-docs) - [Getting started | Bubble Docs](#getting-started-bubble-docs) - [The Glossary | Bubble Docs](#the-glossary-bubble-docs) - [Payments in mobile apps | Bubble Docs](#payments-in-mobile-apps-bubble-docs) - [Differences in native and web elements | Bubble Docs](#differences-in-native-and-web-elements-bubble-docs) - [In-app purchases | Bubble Docs](#in-app-purchases-bubble-docs) - [Native mobile app terminology | Bubble Docs](#native-mobile-app-terminology-bubble-docs) - [Planning features | Bubble Docs](#planning-features-bubble-docs) - [Database structure | Bubble Docs](#database-structure-bubble-docs) - [Building your first app | Bubble Docs](#building-your-first-app-bubble-docs) - [Design and UX | Bubble Docs](#design-and-ux-bubble-docs) - [Checkout page | Bubble Docs](#checkout-page-bubble-docs) - [Previewing a web app | Bubble Docs](#previewing-a-web-app-bubble-docs) - [Previewing a mobile app | Bubble Docs](#previewing-a-mobile-app-bubble-docs) - [Maintenance | Bubble Docs](#maintenance-bubble-docs) - [About AI app generation | Bubble Docs](#about-ai-app-generation-bubble-docs) - [Connect to AI models | Bubble Docs](#connect-to-ai-models-bubble-docs) - [Support Dept | Bubble Docs](#support-dept-bubble-docs) - [Integrations | Bubble Docs](#integrations-bubble-docs) - [AI | Bubble Docs](#ai-bubble-docs) - [Neam | Bubble Docs](#neam-bubble-docs) - [Commenting | Bubble Docs](#commenting-bubble-docs) - [Global native mobile settings | Bubble Docs](#global-native-mobile-settings-bubble-docs) - [Web app | Bubble Docs](#web-app-bubble-docs) - [AI page designer | Bubble Docs](#ai-page-designer-bubble-docs) - [Security dashboard | Bubble Docs](#security-dashboard-bubble-docs) - [Testing and debugging | Bubble Docs](#testing-and-debugging-bubble-docs) - [Generate data types from the Data tab | Bubble Docs](#generate-data-types-from-the-data-tab-bubble-docs) - [Previewing your app | Bubble Docs](#previewing-your-app-bubble-docs) - [Capacity Usage (legacy) | Bubble Docs](#capacity-usage-legacy-bubble-docs) - [Copying the database | Bubble Docs](#copying-the-database-bubble-docs) - [Restoring database backups | Bubble Docs](#restoring-database-backups-bubble-docs) - [Supported browsers | Bubble Docs](#supported-browsers-bubble-docs) - [Best practices: Version control | Bubble Docs](#best-practices-version-control-bubble-docs) - [Notes on queries | Bubble Docs](#notes-on-queries-bubble-docs) - [Automated tests | Bubble Docs](#automated-tests-bubble-docs) - [Privacy rules checker | Bubble Docs](#privacy-rules-checker-bubble-docs) - [SEO | Bubble Docs](#seo-bubble-docs) - [Security tests | Bubble Docs](#security-tests-bubble-docs) - [Bubble account security | Bubble Docs](#bubble-account-security-bubble-docs) - [Security checklist | Bubble Docs](#security-checklist-bubble-docs) - [Generate apps with AI | Bubble Docs](#generate-apps-with-ai-bubble-docs) - [Publishing your app | Bubble Docs](#publishing-your-app-bubble-docs) - [Collaborators | Bubble Docs](#collaborators-bubble-docs) - [API workflow scheduler | Bubble Docs](#api-workflow-scheduler-bubble-docs) - [Wiping change history | Bubble Docs](#wiping-change-history-bubble-docs) - [The server logs | Bubble Docs](#the-server-logs-bubble-docs) - [Hard limits | Bubble Docs](#hard-limits-bubble-docs) - [Overview | Bubble Docs](#overview-bubble-docs) - [Terminology: Version control | Bubble Docs](#terminology-version-control-bubble-docs) - [Transitioning from the legacy version control | Bubble Docs](#transitioning-from-the-legacy-version-control-bubble-docs) - [Native mobile app | Bubble Docs](#native-mobile-app-bubble-docs) - [Publishing FAQ | Bubble Docs](#publishing-faq-bubble-docs) - [Issue explorer | Bubble Docs](#issue-explorer-bubble-docs) - [Test settings | Bubble Docs](#test-settings-bubble-docs) - [The Workflow API | Bubble Docs](#the-workflow-api-bubble-docs) - [Database maintenance | Bubble Docs](#database-maintenance-bubble-docs) - [The native mobile debugger | Bubble Docs](#the-native-mobile-debugger-bubble-docs) - [API | Bubble Docs](#api-bubble-docs) - [Introduction to SEO | Bubble Docs](#introduction-to-seo-bubble-docs) - [Plugins that connect to APIs | Bubble Docs](#plugins-that-connect-to-apis-bubble-docs) - [Authentication | Bubble Docs](#authentication-bubble-docs) - [API guides | Bubble Docs](#api-guides-bubble-docs) - [What is a RESTful API? | Bubble Docs](#what-is-a-restful-api-bubble-docs) - [Streaming API | Bubble Docs](#streaming-api-bubble-docs) - [Introduction to testing and debugging | Bubble Docs](#introduction-to-testing-and-debugging-bubble-docs) - [The Data API | Bubble Docs](#the-data-api-bubble-docs) - [Bulk operation methods compared | Bubble Docs](#bulk-operation-methods-compared-bubble-docs) - [Bubble AI Agent | Bubble Docs](#bubble-ai-agent-bubble-docs) - [SEO: Page | Bubble Docs](#seo-page-bubble-docs) - [API Glossary | Bubble Docs](#api-glossary-bubble-docs) - [Introduction to APIs | Bubble Docs](#introduction-to-apis-bubble-docs) - [Performance | Bubble Docs](#performance-bubble-docs) - [SEO: App | Bubble Docs](#seo-app-bubble-docs) - [Bubble API terminology | Bubble Docs](#bubble-api-terminology-bubble-docs) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Unknown](#unknown) - [Marketplace policies | Bubble Docs](#marketplace-policies-bubble-docs) - [Building Templates | Bubble Docs](#building-templates-bubble-docs) - [Sub-apps | Bubble Docs](#sub-apps-bubble-docs) - [Search | Bubble Docs](#search-bubble-docs) - [Native mobile apps | Bubble Docs](#native-mobile-apps-bubble-docs) - [Building Plugins | Bubble Docs](#building-plugins-bubble-docs) - [About the Beta features section | Bubble Docs](#about-the-beta-features-section-bubble-docs) - [Privacy | Bubble Docs](#privacy-bubble-docs) - [Vulnerability Disclosure Policy | Bubble Docs](#vulnerability-disclosure-policy-bubble-docs) - [Application and data ownership | Bubble Docs](#application-and-data-ownership-bubble-docs) - [Bug reports | Bubble Docs](#bug-reports-bubble-docs) - [Using the core reference | Bubble Docs](#using-the-core-reference-bubble-docs) --- # Introduction | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/master.md) . You’re reading the Bubble Manual, which has everything you need to know to build apps using Bubble. This documentation covers everything from basic concepts to advanced features and includes step-by-step tutorials, troubleshooting tips, and insights into best practices. If you haven't already, start by [setting up a free account and start building](https://bubble.io/login?mode=signup&utm_medium=bubble-docs&utm_content=introduction) . Bubble lets you turn your ideas into apps by combining the power of AI and visual development. Whether you're building your first app or you're an experienced developer, Bubble's AI-powered tools and intuitive visual editor make it possible to quickly generate, refine, and launch your vision—no coding required. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F5uqVAip91dkLAtoThsP0%252Flast%2520ned.webp%3Falt%3Dmedia%26token%3Dd21f9db0-28a8-43e9-8461-19e835a7e6ce&width=768&dpr=3&quality=100&sign=4188e08e&sv=2) B​ubble lets you turn your ideas into fully functional, scalable apps by combining the power of AI and visual development. Whether you're building your first app or you're an experienced developer, Bubble's AI-powered tools and intuitive visual editor make it possible to quickly generate, refine, and launch your vision —no coding required. [](https://manual.bubble.io/#build-your-app-using-ai) Build your app using AI ---------------------------------------------------------------------------------- Bubble's advanced AI app generator empowers you to create a fully functional app using simple prompts. Describe your idea in your own words, and watch as Bubble AI generates a personalized app structure, ready for you to customize. Confirm your features and add any the AI missed, then generate the app. This initial app will be fully functional with a built-in database and workflows — providing a strong starting point, dramatically reducing the time and effort needed to bring your idea to life. [](https://manual.bubble.io/#refine-and-customize-visually) Refine and customize visually ---------------------------------------------------------------------------------------------- After your AI-generated app is ready, Bubble's visual editor lets you fine-tune and expand your app exactly the way you want. Design your user interface, add custom events and workflows, and seamlessly integrate third-party services using plugins and the built-in API Connector. With Bubble, visual development means you have the freedom to iterate quickly, safely, and confidently. [](https://manual.bubble.io/#one-platform-limitless-possibilities) One platform, limitless possibilities ------------------------------------------------------------------------------------------------------------- Bubble's flexibility lets you create any type of app — ranging from simple MVPs to sophisticated, enterprise-grade applications. With a shared database, workflows, and infrastructure, Bubble supports creating seamless experiences across web, iOS, and Android, all from a single, unified editor. To get quickly started with native mobile app development, check out our Quick Start Guide below: Article: [Mobile app quick start guide](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide) [](https://manual.bubble.io/#learning-and-building-with-bubble) Learning and building with Bubble ------------------------------------------------------------------------------------------------------ Bubble's docs are designed to help you quickly master the essentials and continue as a valuable reference throughout your development journey. Whether you prefer a structured walkthrough or simply browsing topics that interest you, the Bubble Manual covers foundational concepts, terminology, best practices, and step-by-step how-to guides. If you're new to Bubble, start by checking out our Getting Started section. Learn the fundamentals, explore how AI and visual development come together, and discover just how quickly you can build powerful, professional apps. You can read more about [Bubble's mission](https://bubble.io/blog/mission/) and our [The Bubble Origin Story](https://bubble.io/blog/about-bubble/) in our dedicated blog articles. [](https://manual.bubble.io/#using-the-bubble-docs) Using the Bubble Docs ------------------------------------------------------------------------------ ### [](https://manual.bubble.io/#sections) Sections The Bubble documentation is divided into two sections: [**The User Manual**](https://manual.bubble.io/help-guides/getting-started) * Long-form articles for learning * In-depth explanation of tools and concepts * Organized by subject * Can be read from start to finish to learn Bubble [**The Core Reference**](https://manual.bubble.io/core-resources/using-the-core-reference) * Short, technical documentation * Covers all properties, settings and technical details * Organized by feature * Can be consulted as needed for specific information ### [](https://manual.bubble.io/#annotations) Annotations To help you get quickly up to speed with the terminology used in Bubble and in web app development in general, we have provided explanatory notes on select words and phrases. You will find these annotations marked with a dotted underline such as this. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FnGkk1X2eymQIFxaS5XHX%252Fannotation.png%3Falt%3Dmedia%26token%3D0aa789c3-ff0e-4c46-879e-c8d2104f6a54&width=768&dpr=3&quality=100&sign=3dee3cb9&sv=2) Clicking a phrase underlined with a dotted line reveals an annotation, and sometimes a link to learn more about the subject. [](https://manual.bubble.io/#other-ways-to-learn) Other ways to learn -------------------------------------------------------------------------- The user manual and core reference is just one part of Bubble's documentation. We also offer other ways to learn in the form of videos, interactive tutorials, demos, blog posts and forum posts. Look for the header _Other ways to learn_ in articles to find links to other relevant resources you may find helpful. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FG2W9sim7Xd0qdxwmbTTL%252FCleanShot%25202023-10-12%2520at%252013.20.53.png%3Falt%3Dmedia%26token%3D63eb7dcb-987d-46b6-bb65-bb65d7e6728d&width=768&dpr=3&quality=100&sign=b49fe47e&sv=2) Many articles offer multiple ways to learn a given topic. Look for the _Other ways to learn_ header at the bottom of the article. [](https://manual.bubble.io/#get-started-now) Get started now ------------------------------------------------------------------ [New? Start here:](https://manual.bubble.io/new-start-here) find the learning resources you need to master Bubble[](https://manual.bubble.io/#new-start-here-find-the-learning-resources-you-need-to-master-bubble) This section will give you an overview over the resources you have at your disposal to start your learning journey. Article: [New? Start here](https://manual.bubble.io/new-start-here) Last updated 2 months ago Was this helpful? --- # New? Start Here | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/new-start-here.md) . [](https://manual.bubble.io/new-start-here#one-platform-for-both-web-and-ios-android) One platform for both web and iOS/Android ------------------------------------------------------------------------------------------------------------------------------------ Bubble supports building apps for both web and iOS/Android. The power of Bubble’s infrastructure is that you don’t need to choose one—you can build for both, using a shared database, workflows, and backend logic. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FnMBErukxcIyZup6zTUkR%252FCleanShot%25202025-04-01%2520at%252011.59.06.png%3Falt%3Dmedia%26token%3Df6ef3060-9f83-419a-a8e8-790d488477eb&width=768&dpr=3&quality=100&sign=458ea08c&sv=2) With Bubble, your web app and native mobile app are built on the same platform—sharing a single database and backend logic to work seamlessly together. All of this happens in one editor, with no need to maintain separate codebases or integrations. This unified approach makes it easy to support multiple platforms while keeping your design, data and logic consistent across your entire app. Feature Web app Native mobile app Wrapper Can be installed from an app store ❌ ✅ ✅ Push notifications ❌ ✅ ⚠️ (manual setup) On-device camera access ❌ ✅ ⚠️ (manual setup) On-device photo library access ⚠️ (as file upload) ✅ (native access) ⚠️ (manual setup) Can open in a mobile browser without installation ✅ ❌ ✅ Database access ✅ ✅ ✅ Backend workflow access ✅ ✅ ✅ API access ✅ ✅ ✅ Access to styles ✅ ✅ ✅ [](https://manual.bubble.io/new-start-here#welcome-to-bubble) Welcome to Bubble! ------------------------------------------------------------------------------------- Before you start exploring, you can [sign up for your free Bubble account here](https://bubble.io/login?mode=signup&utm_medium=bubble-docs&utm_content=new-start-here) . [](https://manual.bubble.io/new-start-here#choosing-your-platform) Choosing your platform ---------------------------------------------------------------------------------------------- The native mobile app editor is currently in **beta**, meaning that you may experience issues or limitations while building or testing your app. Features may change, and not all functionality is final. We recommend thorough testing before publishing, and welcome feedback to help improve the experience. With Bubble, you can build for web, mobile or both at the same time. The guides below give you an introduction to each path: [](https://manual.bubble.io/help-guides/getting-started/building-for.../web) **Building for web** [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android) **Building for mobile** To get quickly started with native mobile app development, check out our Quick Start Guide below: Article: [Mobile app quick start guide](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide) [](https://manual.bubble.io/new-start-here#your-learning-and-building-journey) Your learning and building journey ---------------------------------------------------------------------------------------------------------------------- Bubble guides you step-by-step from idea to fully functional app, combining the power of AI with intuitive visual development. Here's what your learning and building process looks like: ### [](https://manual.bubble.io/new-start-here#id-1.-start-with-your-idea) 1\. Start with your idea Think about the app you want to build. Consider your audience, the core features you need, and the problems you're trying to solve. * [Planning your app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app) ### [](https://manual.bubble.io/new-start-here#id-2.-turn-your-idea-into-an-ai-prompt) 2\. Turn your idea into an AI prompt Using Bubble's AI app generator, describe your vision in simple terms. Clearly outline the key functionalities and style you envision. * [Prompt guide](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#prompt-guide) ### [](https://manual.bubble.io/new-start-here#id-3.-refine-the-blueprint) 3\. Refine the blueprint Bubble’s AI interprets your prompt and shows you a preview. You can explore this initial interpretation, refine your instructions, and ensure it aligns closely with your vision. * [Previewing and refining your app blueprint](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-is-a-user-story) ### [](https://manual.bubble.io/new-start-here#id-4.-generate-and-preview-your-app) 4\. Generate and preview your app Bubble automatically creates your app based on your refined prompt. The AI builds your design, workflows, database structure, and even populates your database with relevant sample data — ready for you to immediately test. * [Previewing your app](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) ### [](https://manual.bubble.io/new-start-here#id-5.-tweak-and-expand-with-visual-development) 5\. Tweak and expand with visual development Your generated app is a robust starting point. Using Bubble’s visual editor, you can adjust, customize, and expand every aspect of your app — no coding required. * [The Bubble Editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) ### [](https://manual.bubble.io/new-start-here#id-6.-launch-and-iterate) 6\. Launch and iterate Once you’re satisfied, Bubble helps you easily deploy your app to the web, iOS, and Android. Gather user feedback, iterate quickly, and continually improve your app over time. * [Launching your app](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app) Bubble makes the journey from idea to reality faster, more intuitive, and accessible for everyone [](https://manual.bubble.io/new-start-here#learning-resources) Learning resources -------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/new-start-here#the-user-manual) The User Manual The User Manual will take you through all the different concepts, how-to's, terminology and best practices needed to learn Bubble. You can read it from beginning to end, or pick the chapters that interest you the most. If you are new to building in Bubble, we recommend heading over to the Getting started section. Getting started: the introductory guide to building apps in Bubble[](https://manual.bubble.io/new-start-here#getting-started-the-introductory-guide-to-building-apps-in-bubble) Our introductory guide will not only take you through the Bubble basics, but will help you set your strategy for planning and building your app in general. We cover topics such as: * What is Bubble * Building your first app * Planning your features and versions * Database structure * Design and UX * Creating and managing apps * The Bubble editor and how it works * Setting up a custom domain and DNS * Application settings Article series: [Getting started](https://manual.bubble.io/help-guides/getting-started) ### [](https://manual.bubble.io/new-start-here#more-learning-resources) More learning resources You can learn Bubble in several ways, including: [The Glossary:](https://manual.bubble.io/the-glossary) Covering terms and phrases used in Bubble[](https://manual.bubble.io/new-start-here#the-glossary-covering-terms-and-phrases-used-in-bubble) The glossary contains widely used words and phrases used in Bubble, along with a short description of what it means. Most entries link to articles in the User Manual and/or the Core Reference where you can learn more about the relevant concept. Article: [The glossary](https://manual.bubble.io/the-glossary) [The Bubble Academy:](https://bubble.io/academy) _Video courses and lessons_[](https://manual.bubble.io/new-start-here#the-bubble-academy-video-courses-and-lessons) The Bubble Academy is a large and growing collection of video courses and lessons (some of them interactice) that tackle subjects ranging from beginner to advanced. Page: [Bubble Academy](https://bubble.io/academy) Page: [Video lesson search page](https://bubble.io/videos) [Youtube channel:](https://www.youtube.com/@BubbleIO) lessons (short and long) as well as community-created content[](https://manual.bubble.io/new-start-here#youtube-channel-lessons-short-and-long-as-well-as-community-created-content) Our Youtube channel, which includes lessons both short and long. There's also an ever-growing collection of community-generated content on Youtube. External page: [Youtube channel](https://www.youtube.com/@BubbleIO) [Bootcamps:](https://bubble.io/bootcamps#!) live group courses[](https://manual.bubble.io/new-start-here#bootcamps-live-group-courses) Bootcamps lets you get expert advice from experienced Bubblers, group discussions and feedback in your app. There are a range of different bootcamps available that cover different parts of your learning journey. Some bootcamps are set up so that you can learn while you are developing your app and get valuable feedback and live problem-solving. Page: [Bubble bootcamps](https://bubble.io/bootcamps#!) ### [](https://manual.bubble.io/new-start-here#getting-help) Getting help If you need help during your learning or building journey, the resources below can help you out with everything from account management to specific problem solving: The Bubble Success Team – Bubble – _experienced Customer Support agents_[](https://manual.bubble.io/new-start-here#the-bubble-success-team-bubble-experienced-customer-support-agents) The Bubble Success Team is a group of dedicated Bubble employees that answer questions and solve problems for thousands of users every month. Page: [Contact the Success team](https://bubble.io/support/contact) The Bubble Forum – Community – _questions, discussions and news_[](https://manual.bubble.io/new-start-here#the-bubble-forum-community-questions-discussions-and-news) Connect with over 2 million community members, get answers to your questions, and discover how to build better with Bubble. This is also where we publish major news and discuss features with the community. Here are a few things you should do to increase your chances of getting an answer: 1. Start with a clear question, so others know what you're trying to solve. 2. Describe what you have already tried; that will help others narrow down possible answers. 3. Share your app as an open app, so that others can access it. If your app is sensitive and private, use some screenshots to show what you have done so far. Page: [The Bubble Forum](https://forum.bubble.io/) Bubble Experts – Community – connect with experienced coaches, agencies, and freelancers[](https://manual.bubble.io/new-start-here#bubble-experts-community-connect-with-experienced-coaches-agencies-and-freelancers) Our Bubble Experts are comprised of curated network of community pros ready to help you build, troubleshoot, or launch. Page: [Bubble experts](https://bubble.io/experts) Last updated 17 days ago Was this helpful? --- # Web | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../web.md) . A web app is an application that runs in a web browser. Unlike native mobile apps, which are installed directly onto a user’s device via an app store, a web app lives online—accessible by visiting a URL. This includes everything from productivity tools like Google Docs, to social platforms like Facebook, to AI interfaces like ChatGPT. You don’t need to install a web app to use it. You simply open a browser (like Chrome, Safari, or Firefox), enter the web address, and sign in. Updates happen automatically, and the experience remains consistent across platforms, as long as the browser supports the features used by the app. [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#how-is-a-web-app-different-from-a-native-mobile-app) How is a web app different from a native mobile app? ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Native mobile apps are designed to run directly on a device’s operating system (iOS or Android). A web app, on the other hand, runs inside a browser and relies on an internet connection to access its content and features. Here are some of the main differences: ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#installation) **Installation** * **Web app**: No installation required. Accessed by URL. * **Native mobile app**: Installed from the App Store or Google Play Store. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#platform-integration) **Platform integration** * **Web app**: Limited access to device hardware (e.g., camera, GPS), usually via browser APIs. * **Native mobile app**: Deep integration with device features, like push notifications, local storage, Bluetooth, and offline access. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#distribution) **Distribution** * **Web app**: Instantly accessible—share a link, and users can open it right away. * **Native mobile app**: Requires submission and approval from app stores. Users must download and install the app before using it. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#updates) **Updates** * **Web app**: Updated centrally. Users always access the latest version. * **Native mobile app**: Users may need to update manually or wait for updates to be pushed via the app store. [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#building-a-web-app) Building a web app ----------------------------------------------------------------------------------------------------------------------- When you build a web app with Bubble, there's no need to write code. Instead, Bubble uses a combination of AI and visual tools to let you define how your app looks, how it works (with workflows, conditions, and dynamic expressions), and how it stores information using a built-in database. Behind the scenes, Bubble automatically generates the code that makes your app run: HTML for structure, CSS for styling, and JavaScript for interactivity. This output is fully compatible with modern browsers like Chrome, Safari, Edge, and Firefox, so your app works seamlessly across devices. This output is what allows your app to run in a browser. Because it uses standard web technologies, your app works across all modern browsers—like Chrome, Safari, Edge, Firefox, and others—without requiring any adjustments. The generated code is also set up to communicate directly with Bubble’s servers. This connection is what powers everything from your app’s database to user authentication, APIs, and encryption. Bubble manages all of these backend systems for you, so you don’t have to worry about setting up infrastructure or maintaining servers. This is what makes building with Bubble so efficient: while you focus on the interface and logic, Bubble handles everything technical under the hood, and it's all compatible with all modern browsers. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#cant-i-just-run-my-web-app-on-a-mobile-device) Can't I just run my web app on a mobile device? Sure you can! But with one caveat: the user has to access the app through the browser on their mobile device. That's not to say there's anything wrong about that: you probably already use many web apps through your phone's browser already, but they come with some restrictions: * Some browser-based APIs (like location or camera access) are available, but with restrictions. * You won’t be able to send push notifications or use offline features unless you're using advanced patterns like Progressive Web Apps (PWAs). * The app runs in the browser window, which may include the browser’s interface elements (e.g., the address bar or back button). ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#when-is-a-web-app-the-right-choice) When is a web app the right choice? A web app is often the best fit when: * You want to build and iterate quickly without going through app store approval processes. * Your audience is spread across devices and platforms. * You want users to access your app via a link—instantly and without installation. * Your app doesn’t need deep access to device hardware (like Bluetooth or offline file access). ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../web#can-i-build-both) Can I build both? Yes—and Bubble is designed specifically to support that. You can build your web app and native mobile app in the same editor, with both versions sharing the same database and backend workflow logic. That’s one of the things that makes Bubble so powerful: in traditional development, you’d need to build two separate apps and connect them through complex API calls and data handling. With Bubble, features like user authentication, database access, and workflows are already integrated and shared across platforms. You’re free to start with a web app, a mobile app, or focus on just one—there’s no need to decide upfront. If you’ve built a successful web app, you can extend it into a native mobile app at any time. Bubble is built to support both, and you can make that decision at any point in time. If you want to learn more about native mobile apps, keep reading our [Building a native iOS and Android app in Bubble section](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android) . Last updated 22 days ago Was this helpful? --- # Building for... | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for....md) . A native mobile app and a web app are not fundamentally different. They both offer the user a visual interface built on top of a foundation of workflows and a database. The primary difference lies in how they are delivered to the user. A web app runs within a browser, relying on HTML, CSS, and JavaScript, and is accessed via a URL. A native mobile app, on the other hand, runs directly on a mobile device's operating system, allowing for deeper integration with device-specific features such as cameras, push notifications, and biometric authentication. If you come from a non-technical background, and especially if you have no experience developing apps for Android and iOS, the difference between a web app and a native mobile app might not be entirely clear. Before diving into how to build native mobile apps, let’s first explore the key differences between these two types. ### [](https://manual.bubble.io/help-guides/getting-started/building-for...#web-applications) Web applications As we've explored, a web app is a set of code files made up of HTML, JavaScript, and CSS, which all modern web browsers can interpret, display, and interact with. In short, this means a web app operates within a web browser and cannot run independently of it. There are many advantages to this approach. Although web browsers are developed by different companies and can have slight variations in behavior, they are all designed to maintain full compatibility with a standard set of programming languages like HTML, CSS, and JavaScript. This ensures that web apps created on platforms like Bubble can run consistently across a wide range of devices and operating systems, whether on a desktop, tablet, or smartphone. Additionally, because web browsers are universally available and regularly updated to meet evolving standards, you don’t need to worry about platform-specific requirements. Your app can be accessed by anyone with a browser, without the need for users to download or install anything. This makes it easier to reach a broader audience while maintaining consistent functionality across various environments. This approach also simplifies deployment and updates since changes to your app are immediately available to all users without requiring them to manually update anything on their end. Bubble includes an advanced responsive editor that lets you design pages that automatically adjust to different devices and screen sizes. This ensures that your app’s pages look great and function smoothly whether viewed on a large desktop monitor or a small mobile screen. By adapting layouts and element sizes based on the user’s device, you can deliver a consistent, optimized experience across all platforms. This approach makes a responsively designed Bubble app just as available on a mobile device as on a desktop computer, but from the perspective of a mobile device user, it comes with a few limitations that a native mobile app does not. ### [](https://manual.bubble.io/help-guides/getting-started/building-for...#native-mobile-applications) Native mobile applications Unlike web applications that run inside a browser, native mobile applications are specifically designed to run directly on a mobile device’s operating system, such as Android or iOS. This allows them to fully integrate with the device’s hardware and software features, such as GPS, camera, and push notifications. Native apps offer a few key advantages. They can be installed directly from the Apple App Store or Android Play Store without relying on a third-party service, and they don’t rely on a web browser to function. They can leverage platform-specific features and design standards, giving users an experience that feels more integrated with their device. For example, native mobile apps can take full advantage of gestures, system-level navigation, and native UI components that users are already familiar with. The two methods of development are by no means mutually exclusive; in fact, many of today’s most popular web applications offer both a web version that users can access through any browser on any device, and a native mobile app specifically built to be downloaded in one or both app stores and leverage the features of a mobile device. You can get started with mobile development using the resources below: Article series: [Building for native iOS and Android](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android) Article: [Mobile app quick start guide](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide) #### [](https://manual.bubble.io/help-guides/getting-started/building-for...#cross-platform-compatibility) Cross-platform compatibility Building and maintaining native apps traditionally requires building separate versions for each platform (iOS and Android), which can be time-consuming and costly. Bubble’s Native Mobile App Editor aims to bridge that gap, allowing you to build native apps using Bubble’s visual tools, while maintaining the ability to deploy your app to both major platforms. [](https://manual.bubble.io/help-guides/getting-started/building-for...#learn-more-about-building-for-web-and-native-mobile) Learn more about building for web and native mobile ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To learn more about the differences between the two, keep reading this article series: [Web](https://manual.bubble.io/help-guides/getting-started/building-for.../web) [Native iOS and Android](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android) ### [](https://manual.bubble.io/help-guides/getting-started/building-for...#web-wrappers-and-pwas) Web wrappers and PWAs There are various third-party and custom code solutions that allow you to publish a Bubble app to one or both app stores. Many of these options, including plugins and services, enable access to on-device features like biometrics, file storage, the camera, and contacts. These solutions work by “wrapping” your web app in a native container, making it distributable through app stores while still relying on web technologies. Essentially, web wrappers function like a “full-screen browser,” masking the fact that the app is running on web technology in the background. Progressive Web Apps (PWAs) are another alternative that lets users add your app to their home screen, but PWAs have more limited access to native device features compared to fully native apps. Both of these solutions have been around for years and currently power many successful Bubble apps in the app stores. However, they come with certain limitations. While they can offer access to native features and provide a way to distribute your app on iOS and Android, they may not fully match the performance, seamless user experience, or deeper device integration that a fully native app can provide. They also rely on third-party solutions (services and/or plugins) and/or custom code to work. Last updated 22 days ago Was this helpful? --- # What is Bubble? | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/what-is-bubble.md) . [](https://manual.bubble.io/what-is-bubble#what-is-bubble) What is Bubble? ------------------------------------------------------------------------------- Rather than specializing in one or two aspects of web development (like designing landing pages or building databases), Bubble’s full-stack visual programming interface does it all. You can customize your UX with a drag-and-drop editor, build out logic, manage databases, and more. Plus, you can integrate with anything via plugins and API. In fact, it has all the tools you need to build a site like Facebook or Airbnb. [Sign up for your free account to start building here](https://bubble.io/login?mode=signup&utm_medium=bubble-docs&utm_content=what-is-bubble) . Here are a few key features you’ll encounter as you dive in: #### [](https://manual.bubble.io/what-is-bubble#ai-builder) AI builder Bubble includes an AI app builder that can generate a complete app from a single prompt. Based on your input, Bubble creates a blueprint that you can refine until you're satisfied. Once ready, Bubble will generate the full app for you. You can read more about this in the [AI section](https://manual.bubble.io/help-guides/ai) . #### [](https://manual.bubble.io/what-is-bubble#visual-programming-editor) Visual programming editor Bubble’s main interface — called the editor — allows you to build your app by pointing and clicking instead of writing code. It’s where you design the page, structure the database, and build workflows that respond to user actions. As you build, you’ll see the results on the screen, and you can preview your app with a single click. You can dive deeper in the sections on [designing your app](https://manual.bubble.io/help-guides/design) and [creating workflows and logic](https://manual.bubble.io/help-guides/logic) . #### [](https://manual.bubble.io/what-is-bubble#database-management) Database management Building and maintaining a database is a complex task, so Bubble automates every aspect of it. As soon as you create an app, its developer and live databases will be ready to use. We’ll perform continuous point-in-time backups with easy restoration, and industry-standard security and privacy management tools are built in. You can set up and manage all of this in just a few clicks, even if you have no prior database experience. Read more in the [database section](https://manual.bubble.io/help-guides/data/the-database) . #### [](https://manual.bubble.io/what-is-bubble#user-management-and-security) User management and security Bubble's built-in user management tools enable you to let users sign up for and log in to your app securely. All our user management functionality aligns with industry standards for security and privacy while giving you the flexibility you need to set up workflows and methods that suit your app. You can read more in the [user account management section](https://manual.bubble.io/help-guides/data/user-accounts) . If you work with a team of developers, you can also learn how to set up isolated working environments in the version control section. #### [](https://manual.bubble.io/what-is-bubble#third-party-integration) Third-party integration Most modern app development requires you to your app to third-party systems, from other apps to service providers like weather reports and generative AI models. Using one of our community-made plugins or Bubble's own [API connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) , [app connector](https://manual.bubble.io/help-guides/integrations/bubble-app-connector) , or [SQL connector](https://manual.bubble.io/help-guides/integrations/sql-database-connector) , you can set up connections to other systems quickly and securely. #### [](https://manual.bubble.io/what-is-bubble#scalability) Scalability From the platform to our pricing plans, Bubble was designed to scale with your app as it grows The Bubble engine and database is hosted securely on Amazon AWS, the world's largest network of internet servers and services, and file assets are spread out across the Cloudflare Content Delivery Network. This combination gives you the power to scale quickly and confidently. You can read more about Bubble’s tools for scaling in the [performance and scaling section](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling) . [](https://manual.bubble.io/what-is-bubble#building-for-web-and-native-mobile) Building for web and native mobile ---------------------------------------------------------------------------------------------------------------------- With Bubble, you can build both web apps (which run in a browser) and native mobile apps (which can be installed from the Apple App Store or Google Play Store). You don’t have to choose one over the other—Bubble supports both, and you can build them in the same editor. They share the same database, user authentication, and workflows, so your data and logic work seamlessly across both platforms. You can read more about this in our [Building for web and Android/iOS section.](https://github.com/bubblegroup/bubble-manual/blob/main/help-guides/getting-started/building-for...) ### [](https://manual.bubble.io/what-is-bubble#we-cant-wait-to-see-what-you-build) We can’t wait to see what you build Bubble exists to enable anyone from first-time entrepreneurs to enterprise-level companies to take an idea from concept to fully functional, scalable reality — faster and cheaper than you could with just code. So head over to the [Building your first app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app) section, and let’s dive in. Last updated 22 days ago Was this helpful? This site uses cookies to deliver its service and to analyze traffic. By browsing this site, you accept the [privacy policy](https://policies.gitbook.com/privacy/cookies) . AcceptReject --- # Native iOS and Android | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android.md) . The native mobile app editor is currently in **beta**, meaning that you may experience issues or limitations while building or testing your app. Features may change, and not all functionality is final. We recommend thorough testing before publishing, and welcome feedback to help improve the experience. **Warning: Limited support on Android 8 and 10** Bubble mobile apps may not function reliably on devices running Android versions 8 and 10. If you’re targeting users on these versions, we recommend additional testing. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android#navigating) Navigating -------------------------------------------------------------------------------------------------------------------------- Web apps and native mobile apps are built within the same environment and project in Bubble. Rather than thinking of them as separate projects, they are just different tools within the same Bubble editor, used to develop both the web and native versions of your app seamlessly. However, web apps and native mobile apps come with some differences in methods and terminology, and we've divided this introductory guide into three sections: ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android#understanding-the-native-mobile-tools) Understanding the native mobile tools In this section, we’ll explore how Bubble's native mobile app tools integrates with the same environment used for web app development. Rather than being a completely separate editor, it offers features that allow you to design and deploy native mobile apps alongside your web app in a unified workspace and with a shared backend and database. We’ll highlight both its current capabilities and what you can expect as the feature continues to evolve. Article: [What is a native mobile app?](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app) ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android#how-is-native-app-development-and-web-app-development-different) How is native app development and web app development different? In this section of the documentation, we'll explore the differences between web apps and native mobile apps, delving into the core principles of each to understand how they are used in development and how they function differently both in the editor and in the final app. Article: [Native mobile app development and web app development](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development) Article: [Differences in native and web elements](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements) ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android#terminology) Terminology The native mobile app editor introduces some new terminology. We recommend reviewing the table of terms and definitions before diving into the rest of the documentation, and encourage you to refer back to it whenever needed for clarification as you explore the editor’s features. Article: [Native mobile app editor terminology](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-app-terminology) Last updated 22 days ago Was this helpful? --- # What is a native mobile app? | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app.md) . A native mobile app is downloaded from the Apple App Store or the Google Play Store, and runs directly on the user’s device – without the need to open it in a web browser or rely on a “wrapper.” It is usually more performant, has native mobile interactions and accesses device hardware/software. [Learn more in the next section](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development) . ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app#how-is-the-process-different-from-building-web-apps) **How is the process different from building web apps?** In essence – it isn't. You can use the same Bubble editor to build for web and mobile. The tools for building the native mobile version of your app are built to work seamlessly with your existing Bubble projects. This means you don’t have to choose between building a web app or a native mobile app—you can add a mobile app to an existing web project and share the same database and backend workflows. Any changes made to the database by the web or mobile app will be instantly reflected across both platforms. Since both apps exist within the same project, you manage them through the same Bubble Editor. The mobile app has its own views and workflows, similar to how web apps are managed today. While backend workflows can be shared between the web and mobile apps, you also have the flexibility to create workflows specific to one app without impacting the other. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app#how-can-i-adapt-my-web-app-to-mobile-app) How can I adapt my web app to mobile app? Before you start building your mobile app, it’s important to understand the differences in the design process. Historically, Bubble apps are built for web browsers and follow design principles suited for browser-based environments. Native mobile apps, however, are built using the design principles and components native to Android and iOS operating systems. Because of these differences, you'll want to redesign your mobile interface to take advantage of all the native mobile elements, components, gestures, interactions and more. This means that any existing pages in your web app will need to be rebuilt specifically for the mobile app. While you can copy and paste certain elements and workflows from a web page to a mobile view, we recommend taking the time to rebuild these pages. Doing so allows you to fully leverage the native performance, snappiness, and platform-specific look and feel offered by the Native Mobile App Editor. Learn more in the Building section. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app#how-much-does-it-cost) How much does it cost? **Current (Private Beta) Pricing:** Bubble's native mobile app builder is currently in private beta. During this phase, building, hosting, and deploying native mobile apps is free if you have a paid web app (deploying mobile apps to the app stores will require a paid web plan since mobile apps require a live backend). **Future Pricing:** In the future, there will be an additional cost if you want to build a web app and mobile app in the same project. We will share more details about the different plans, and you will receive ample notice before any pricing changes take effect. **Workload Usage**: Since mobile and web apps share the same backend and database, workload usage for your project will be cumulative across both platforms. This means the workload generated by your web and mobile applications is combined. In the future, additional filters in the Logs tab will be introduced to help you differentiate and track the relative workload usage and traffic from your web and mobile apps separately. Last updated 22 days ago Was this helpful? --- # Native mobile vs. web development | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development.md) . A native mobile app and a web app are not fundamentally different. They both offer the user a visual interface built on top of a foundation of workflows and a database. The primary difference lies in how they are delivered to the user. A web app runs within a browser, relying on HTML, CSS, and JavaScript, and is accessed via a URL. A native mobile app, on the other hand, runs directly on a mobile device's operating system, allowing for deeper integration with device-specific features such as cameras, push notifications, and biometric authentication. If you come from a non-technical background, and especially if you have no experience developing apps for Android and iOS, the difference between a web app and a native mobile app might not be entirely clear. Before diving into how to build native mobile apps, let’s first explore the key differences between these two types. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#web-applications) Web applications As we've explored, a web app is a set of code files made up of HTML, JavaScript, and CSS, which all modern web browsers can interpret, display, and interact with. In short, this means a web app operates within a web browser and cannot run independently of it. There are many advantages to this approach. Although web browsers are developed by different companies and can have slight variations in behavior, they are all designed to maintain full compatibility with a standard set of programming languages like HTML, CSS, and JavaScript. This ensures that web apps created on platforms like Bubble can run consistently across a wide range of devices and operating systems, whether on a desktop, tablet, or smartphone. Additionally, because web browsers are universally available and regularly updated to meet evolving standards, you don’t need to worry about platform-specific requirements. Your app can be accessed by anyone with a browser, without the need for users to download or install anything. This makes it easier to reach a broader audience while maintaining consistent functionality across various environments. This approach also simplifies deployment and updates since changes to your app are immediately available to all users without requiring them to manually update anything on their end. Bubble includes an advanced responsive editor that lets you design pages that automatically adjust to different devices and screen sizes. This ensures that your app’s pages look great and function smoothly whether viewed on a large desktop monitor or a small mobile screen. By adapting layouts and element sizes based on the user’s device, you can deliver a consistent, optimized experience across all platforms. This approach makes a responsively designed Bubble app just as available on a mobile device as on a desktop computer, but from the perspective of a mobile device user, it comes with a few limitations that a native mobile app does not. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#web-wrappers-and-pwas) Web wrappers and PWAs There are various third-party and custom code solutions that allow you to publish a Bubble app to one or both app stores. Many of these options, including plugins and services, enable access to on-device features like biometrics, file storage, the camera, and contacts. These solutions work by “wrapping” your web app in a native container, making it distributable through app stores while still relying on web technologies. Essentially, web wrappers function like a “full-screen browser,” masking the fact that the app is running on web technology in the background. Progressive Web Apps (PWAs) are another alternative that lets users add your app to their home screen, but PWAs have more limited access to native device features compared to fully native apps. Both of these solutions have been around for years and currently power many successful Bubble apps in the app stores. However, they come with certain limitations. While they can offer access to native features and provide a way to distribute your app on iOS and Android, they may not fully match the performance, seamless user experience, or deeper device integration that a fully native app can provide. They also rely on third-party solutions (services and/or plugins) and/or custom code to work. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#native-mobile-applications) Native mobile applications Unlike web applications that run inside a browser, native mobile applications are specifically designed to run directly on a mobile device’s operating system, such as Android or iOS. This allows them to fully integrate with the device’s hardware and software features, such as GPS, camera, and push notifications. Native apps offer a few key advantages. They can be installed directly from the Apple App Store or Android Play Store without relying on a third-party service, and they don’t rely on a web browser to function. They can leverage platform-specific features and design standards, giving users an experience that feels more integrated with their device. For example, native mobile apps can take full advantage of gestures, system-level navigation, and native UI components that users are already familiar with. The two methods of development are by no means mutually exclusive; in fact, many of today’s most popular web applications offer both a web version that users can access through any browser on any device, and a native mobile app specifically built to be downloaded in one or both app stores and leverage the features of a mobile device. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#cross-platform-compatibility) Cross-platform compatibility Building and maintaining native apps traditionally requires building separate versions for each platform (iOS and Android), which can be time-consuming and costly. Bubble’s Native Mobile App Editor aims to bridge that gap, allowing you to build native apps using Bubble’s visual tools, while maintaining the ability to deploy your app to both major platforms. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#faq-native-mobile-vs-web-development) FAQ: Native mobile vs web development ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Why isn't the repeating group available in native mobile apps?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-isnt-the-repeating-group-available-in-native-mobile-apps) The repeating group is a web-specific element. Native mobile apps handle lists differently — each operating system has its own native list components, which Bubble uses instead. This maximizes both compatibility and performance, as list rendering is handled natively by the OS. Why does my app need to ask permission to send push notifications and access device features?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-does-my-app-need-to-ask-permission-to-send-push-notifications-and-access-device-features) Operating systems require apps to request explicit user consent before accessing device features like the camera, location, or push notifications. This is enforced at the OS level — it's not a Bubble limitation. Users can grant or revoke these permissions at any time through their device settings. Why do I need to submit my app to the App Store or Google Play?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-do-i-need-to-submit-my-app-to-the-app-store-or-google-play) Apple and Google require all native apps to go through their review process before they can be distributed to users. This is a platform requirement, not a Bubble limitation. Bubble simplifies this process by handling the build and packaging for you. Can I use the same database for both my web and mobile app?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#can-i-use-the-same-database-for-both-my-web-and-mobile-app) Yes. Bubble's backend is shared across your web and native mobile apps, so both use the same database, and data types. Changes made in either platform are immediately reflected in both. Why do elements in my mobile app look different from my web app?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-do-elements-in-my-mobile-app-look-different-from-my-web-app) Native mobile apps use OS-specific UI components and layout patterns that differ from web conventions. Can I use plugins in my native mobile app?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#can-i-use-plugins-in-my-native-mobile-app) Plugins can be used in native mobile apps, but they aren't cross-platform compatible. Many of Bubble's own plugins work on mobile, but third-party web plugins need to be rebuilt to support it. Use the _Mobile_ filter in the plugin sidebar to show only plugins that support native mobile. Why does my app need to be rebuilt and resubmitted for some updates[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-does-my-app-need-to-be-rebuilt-and-resubmitted-for-some-updates) Minor updates, such as text changes and UI tweaks, can be pushed via over-the-air updates without resubmission. However, changes that affect the app's native configuration, such as adding new device permissions, require a new build and app store submission. Can I test my mobile app without submitting it to the app stores?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#can-i-test-my-mobile-app-without-submitting-it-to-the-app-stores) Yes. You can test your app on a real device using BubbleGo during development, and use TestFlight for iOS beta testing before submitting to the App Store. Why are some web elements not available in native mobile?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development#why-are-some-web-elements-not-available-in-native-mobile) Many web elements rely on browser APIs and web technologies that don't exist in a native mobile environment. Bubble provides native equivalents where possible, but not every web element has a direct mobile counterpart. Last updated 22 days ago Was this helpful? --- # Mobile app quick start guide | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide.md) . Building a native mobile app with Bubble opens the door to new ways of designing, structuring, and delivering experiences — all while using the same powerful visual development tools you're already familiar with. This guide walks you through each step of the journey, from setting up your app’s interface to launching it on the App Store and Google Play. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#getting-started-quickly) Getting started quickly --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-1-your-frontend-mobile-building-blocks) 1 – Your frontend: Mobile building blocks **If you’ve already built a web app in Bubble**, building for mobile will have some similarities and differences Your backend setup—things like your database, workflows, conditions, and logic—can stay exactly the same. But to take advantage of what makes native mobile apps unique, you will have to adapt the the frontend. Mobile apps follow different design patterns and user expectations, so the interface will need to be reimagined using mobile-specific building blocks like mobile views, mobile elements, and native navigation. The layout is more constrained, the interaction patterns are different, and performance expectations are higher—especially on smaller screens and devices. **If you're starting fresh with mobile**, you'll learn how to build native mobile apps without any code. We recommend starting with our [Getting Started with Mobile series on YouTube](https://www.youtube.com/@BubbleIO/videos) to get a clear overview from Matt Neary, but you can also use this Quick Start guide to learn more. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#mobile-views) Mobile views: Instead of web “pages,” mobile apps have “views.” In your **app interface manager**, add and manage views like: * [Tab views](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/the-view#tab) for primary navigation * [Stack views](https://manual.bubble.io/help-guides/logic/workflows/actions#stack) for a smooth "back" button experience * [Modal views](https://manual.bubble.io/help-guides/logic/workflows/actions#modal) for focused tasks like forms or settings #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#mobile-elements) Mobile elements: Swap out common web elements with native mobile elements: * [Sheets](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers#sheets) instead of popups * [Short lists](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers#short-list) and selectable lists instead of repeating groups Need inspiration? Check out platforms like [Mobbin](https://www.mobbin.com/) to see how leading mobile apps structure their layouts. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-2-adding-native-mobile-features) 2 - Adding native mobile features A key difference between web and native mobile apps is that native apps can interact directly with the device they’re installed on. This gives you access to features like the camera, photo library, location services, and push notifications. With Bubble, you're not limited to wrapping a web app. You can build a true native experience that takes full advantage of mobile capabilities and feels integrated, responsive, and intuitive to users. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#dropdowns) Dropdowns: * [**Bottom sheets**](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers#sheets) – These are mobile-native elements that slide up from the bottom of the screen and feel familiar to mobile users. To use one, add the **Sheet** element from the visual elements panel. Sheets can contain other elements just like a regular group. * [**Modals with selectable lists**](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/input-forms#selectable-lists) – For cases where users need to pick from a list (like choosing a category or filter), you can add a **Sheet** or **Modal** element, then place a **Selectable List** inside it. This creates a mobile-friendly alternative to dropdowns that’s easier to use on smaller screens. Both approaches give you more control over the design and behavior of the selection experience—especially helpful on mobile where space and interaction patterns are different from the web. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#swipe-actions) Swipe actions: [Swipe actions](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers#list-item-swipe-actions) let users swipe left or right on list items to trigger actions like deleting or archiving — a familiar mobile interaction pattern. Swipe actions are available for **Vertical** and **Section Lists**, and each list item can include up to **three swipe actions** on each side: * **Leading** (left) actions * **Trailing** (right) actions To add swipe actions: 1. Add a Vertical or Section List to your view. 2. Select the **List Item** template. On the canvas, hover over the list item and click the **leading** or **trailing** swipe area to edit it. 3. Drag visual elements (icons, labels, etc.) into the swipe frame to represent the action. 4. In the workflow editor, use the **When swipe action is tapped** event to define the behavior (e.g., delete a task or mark it complete). 5. Optionally, you can enable **full swipe to trigger** — letting the user trigger the action by swiping all the way across. Swipe actions come with built-in animation and default behavior, making them quick to set up and easy to use. Layout controls are intentionally limited to ensure consistency and avoid clutter. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#device-capabilities) Device capabilities: Native mobile apps can access on-device features like the camera, photo library, location services, and push notifications, helping you create more interactive, native-feeling experiences. * [**Camera an photo library**](https://manual.bubble.io/help-guides/logic/device-resources/camera-photo-library) : Use the _Take photo_ and _Pick photo_ actions in workflows to let users capture or upload images. Permission prompts are triggered automatically and can be customized in the _Language_ settings. * [**Location services**:](https://manual.bubble.io/help-guides/logic/device-resources/location-services) Use the _Get current location_ action or _Current geographic position_ data source to access the device's location. You can also check permission status using _Has granted location permission_. * [**Push notifications**:](https://manual.bubble.io/help-guides/logic/workflows/actions#push-notifications) To send push notifications, you must first request permission using the Request push notification permission action. Then, use Send push notification to deliver messages to the user's device.You can also configure a **tap destination** on the Send push notification action to route users to a specific view — with optional parameters, overlays, and navigation context — when they tap the notification. Read more in [this article](https://manual.bubble.io/help-guides/logic/workflows/actions#sending-push-notifications) . * [**Deep links:**](https://manual.bubble.io/help-guides/logic/workflows/actions) Use the Create a mobile deep link workflow action to generate a shareable URL that opens your app to a specific view. The URL can be included in emails, SMS messages, clipboard actions, or stored in the database. Deep links use the same navigation model as push notification tap destinations — you configure a destination view, navigation type (stack or modal), overlay, base view, and view parameters. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#embedding-web-views) Embedding web views: You can embed web pages inside mobile views using the [**WebView** element](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/visual-native-app-elements#webview) . This is useful if you’ve already built parts of your app for the web and want to reuse them without recreating everything from scratch. Simply add a WebView element to your mobile view and point it to the relevant page in your app. Keep in mind: * WebViews can only display pages from your own Bubble app — external URLs are not supported. * Users can’t navigate to other pages inside the WebView, so make sure all needed content is on the same page. * Native features like location, camera, or push notifications will not work inside a WebView. Use native mobile components if you need access to those. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-3-adding-mobile-logic-workflows) 3 – Adding mobile logic: Workflows Once your mobile layout is ready, it's time to bring it to life with workflows. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#frontend-workflows) Frontend workflows: Instant interactions that run on the user's device, such as: * Tapping a button * [Swiping](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers#list-item-swipe-actions) on a list item * Requesting permissions (e.g., camera or location) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#backend-workflows) Backend workflows: Behind-the-scenes processes shared between web and mobile, including: * Saving form submissions * Triggering database updates * Integrating with a third-party API ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-4-testing-your-app) 4 - Testing your app Testing is crucial to ensure your app performs smoothly across devices and scenarios. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#web-preview) [Web preview](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#web-preview) : Great for checking basic layouts and workflows, but it won't simulate mobile-only features like push notifications. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#bubblego-ios-and-android) [BubbleGo (iOS and Android)](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#bubblego) : Download BubbleGo to preview your app on real devices — including full mobile functionality like camera access and swipe actions. When you're ready to test with broader audiences, use Apple TestFlight or Google's internal testing tools. Make sure your Apple Developer and Google Play Console accounts are set up early — approvals can take time. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-5-publishing-to-app-stores) 5 - Publishing to app stores Publishing to the app store involves several steps that take place outside of the Bubble platform, and the process can be a bit complex. To make things easier, we’ve created a detailed guide that walks you through each part of the process. Article series: [Publishing your native mobile app](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app) Once you've tested thoroughly, it's time to share your app with the world! #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#prepare-your-global-mobile-settings) Prepare your global mobile settings: Fill out required settings like app names, icons, app schemes, and platform-specific metadata. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#follow-our-publishing-guides) Follow our publishing guides: * [Publish to the App Store (iOS)](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/ios-app-store) * [Publish to the Play Store (Android)](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/google-play-store) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#plan-for-platform-requirements) Plan for platform requirements: Each store has its own guidelines and review processes, so make sure you meet their standards before submission. When your app is live, celebrate by sharing it with the [Bubble community](https://forum.bubble.io/) ! ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-6-updating-your-app-after-launch) 6 - Updating your app after launch #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#ota-over-the-air-updates) [OTA (Over-the-Air) Updates](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#how-ota-over-the-air-updates-work) : Push minor changes - like text edits or design tweaks — without needing App Store or Play Store re-approval. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#new-builds) [New builds:](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#what-is-a-live-version) Major updates, like adding new features, require a new build submission and app store approval. Quick tip: Bubble supports multiple live versions, allowing you to update new users while letting existing users continue using previous versions if needed. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#id-7-getting-discovered-app-store-optimization-aso) 7 - Getting discovered: App Store Optimization (ASO) After publishing, your next goal is to help users find your app. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#keywords) Keywords: 65% of downloads come from search. Use strong keywords in your app's title and description. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#visuals) Visuals: Your app icon and screenshots are often your first impression — make them count. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide#metadata-and-descriptions) Metadata and descriptions: Highlight your app's biggest benefits right away and back them up with real numbers or examples when possible. Building and launching a native mobile app with Bubble puts you in control of the entire process — from idea to live product — all within a single visual development platform. By following the steps in this guide, you'll not only create a mobile app that looks and feels polished, but also one that scales alongside your ambitions. You’re building something incredible. Let’s bring it to life 🚀 Last updated 22 days ago Was this helpful? --- # Getting started | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started.md) . The **Bubble user manual** is our long-form collection of articles that teaches you Bubble from start to finish. We've designed the manual so that you can read it from A-Z or pick the categories and specific articles that you need. Instead of delving into each individual setting and property, we explore broader topics such as design, data and logic, and we even touch on subjects not directly tied to Bubble, aiming to foster an overall understanding of web applications at large. If you are looking for more concise, technical documentation for each of Bubble's features, you may be interested in checking out the [core reference](https://manual.bubble.io/core-resources/using-the-core-reference) section of the docs. In [New? Start here section](https://manual.bubble.io/new-start-here) we also [list other resources](https://manual.bubble.io/new-start-here#learning-bubble) such as videos, user community and interactive tutorials. [](https://manual.bubble.io/help-guides/getting-started#how-to-read-the-user-manual) How to read the user manual --------------------------------------------------------------------------------------------------------------------- The user manual is designed like a guidebook, allowing you to either read it from beginning to end or select specific sections based on what you want to learn more about. If you have just getting started with Bubble, we recommend you check out each section and get to know the how the manual is structured. This way, if you don't want to read every section in full now, you can return to any subject for a thorough overview when you need it. [](https://manual.bubble.io/help-guides/getting-started#manual-sections) Manual sections --------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/getting-started#getting-started) Getting started This section focuses on the basics of Bubble and is meant for users who are new to the platform. Here we'll explore the basic stuff such as creating an app, navigating the editor and changing the general application settings. If you have played around with Bubble for a little while and know about the basic stuff already, you can use the navigation menu on the left to find the categories that interest you the most. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FrHWTqjsYEZv8uYm5uFmH%252Fcreate-bubble-app.png%3Falt%3Dmedia%26token%3Ddd988430-c866-46c6-88ae-abc4bb830f27&width=768&dpr=3&quality=100&sign=d52b3ce5&sv=2) [Building your first app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app) [](https://manual.bubble.io/help-guides/getting-started#building-your-first-app) This section takes a look at the theory and methods around planning your first app. We take a look at how you can break your app idea into features and versions, how you can plan out your database structure and finally how you make it ready for users with a user interface. If you've never built an app before, we recommend starting here. Article series: [Building your first app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app) [Creating and managing apps](https://manual.bubble.io/help-guides/getting-started/creating-and-managing-projects) [](https://manual.bubble.io/help-guides/getting-started#creating-and-managing-apps) Your Bubble account can hold as many applications as you want, and this section explores how you can organize your apps. Article: [Creating and managing apps](https://manual.bubble.io/help-guides/getting-started/creating-and-managing-projects) [Navigating the Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) [](https://manual.bubble.io/help-guides/getting-started#navigating-the-bubble-editor) Bubble contains all the tools you need to create awesome web applications, all wrapped into one editor. Learn how to navigate it in this article. Article: [Navigating the Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) Custom domain and DNS[](https://manual.bubble.io/help-guides/getting-started#custom-domain-and-dns) Your Bubble app will automatically be assigned a unique URL when it is created, such as `https://my-bubble-application.bubbleapps.io`. As you get close to launch, you may want to move it to your own domain, such as `https://www.my-bubble-application.com`. This article explores how to connect your app to a custom domain and set up the correct DNS settings. Article: Custom domain and DNS Application settings[](https://manual.bubble.io/help-guides/getting-started#application-settings) Each Bubble app comes with a set of general settings. This article goes through each different category of settings. Article series: Application settings ### [](https://manual.bubble.io/help-guides/getting-started#design) Design Bubble is a visual tools that lets you design your app by dragging and dropping elements such as text, buttons, links, tables and even maps on a page. This section covers how you design your app and helpful tools such as styles, color/font variables and the responsive engine. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FIrXvQE7j7MkpY1iytIei%252Fdesign.png%3Falt%3Dmedia%26token%3Dad62292d-bdcf-4442-8ae4-ec745ed7824e&width=768&dpr=3&quality=100&sign=e0a4d93b&sv=2) Bubble lets you set up flexible, responsive design and save them in styles that can be applied every in seconds. [Elements](https://manual.bubble.io/help-guides/design/elements) [](https://manual.bubble.io/help-guides/getting-started#elements) Elements are the things that you place on a page to display data and let your users interact with your app. Whether you want to create an elaborate presentation page with images and animations or a simple signup form, it's all done by combining different elements in a way that your users find useful and visually pleasing. Bubble offers a lot of different elements serving different purposes and this article series covers them all. Article series: [Elements](https://manual.bubble.io/help-guides/design/elements) [Styling](https://manual.bubble.io/help-guides/design/variables-and-styles) [](https://manual.bubble.io/help-guides/getting-started#styling) Each element that you add to your page has a default _styling_ applied to it. In short, styling refers to what your elements look like, and this is done by changing styling settings such as: * Background color, gradient or image * Border * Shadow * Font * Transitions Bubble also features ways to save styling settings to help you maintain and update how your app looks efficiently. Article series: [Styling](https://manual.bubble.io/help-guides/design/variables-and-styles) [Responsive design](https://manual.bubble.io/help-guides/design/responsive-design) [](https://manual.bubble.io/help-guides/getting-started#responsive-design) Responsive design is a method that gives your users a great experience no matter what kind of device they are using to access your app. Bubble features a _responsive engine_ that lets you control every aspect of your app's responsiveness in the same visual editor that you use to build your pages. It uses a grid-based layout to change the appearance of the page depending on the screen size and orientation of the device. Article series: [Responsive design](https://manual.bubble.io/help-guides/design/responsive-design) [The component library](https://manual.bubble.io/help-guides/design/the-component-library) [](https://manual.bubble.io/help-guides/getting-started#the-component-library) The component library is a collection of pre-built User Interface (UI) components that can be dragged and dropped onto your page to help you build beautiful interfaces faster. These UI components are fully responsive and are made up of containers, visual elements, and form inputs that can be individually customized once added to your page. Each component is a fully independent unit, but can be connected to each other or other parts of your app by adding workflows and data. Article: [The component library](https://manual.bubble.io/help-guides/design/the-component-library) [Importing from Figma](https://manual.bubble.io/help-guides/design/importing-from-figma) [](https://manual.bubble.io/help-guides/getting-started#importing-from-figma) Many users have a background from Figma. Bubble has a tool for importing your Figma design into Bubble, maintaining style attrbiutes such as colors, fonts, shadows, etc. This article covers how the import process works. Article: [Importing from Figma](https://manual.bubble.io/help-guides/design/importing-from-figma) ### [](https://manual.bubble.io/help-guides/getting-started#data) Data Data forms the foundation of any application. Indeed, creating an app that doesn't handle data in some way is unusual. Be it data produced by your users, added by you, or imported from external applications or services, the capability to collect, secure, and present information essentially drives the existence of most apps. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FwDYfLkyFstxaevuuA6Kt%252Fbubble-database-design.png%3Falt%3Dmedia%26token%3D751edbd0-4a34-4b94-9ffb-9df0a9c1f560&width=768&dpr=3&quality=100&sign=cc675d83&sv=2) Bubble's database editor lets you create, assign fields to and connect data types with no database experience. [The database](https://manual.bubble.io/help-guides/data/the-database) [](https://manual.bubble.io/help-guides/getting-started#the-database) The database manages all the dynamic data that both you and your users have added. You can create, modify, view, and delete data as needed and run bulk operations to make major updates. Data in the database is stored securely on Bubble's servers. Article series: [The database](https://manual.bubble.io/help-guides/data/the-database) [Files](https://manual.bubble.io/help-guides/data/files) [](https://manual.bubble.io/help-guides/getting-started#files) Bubble offers integrated tools within the editor and your app for handling file and image uploads and storage. Article: [Files](https://manual.bubble.io/help-guides/data/files) [Static data](https://manual.bubble.io/help-guides/data/static-data) [](https://manual.bubble.io/help-guides/getting-started#static-data) Static data in Bubble is defined as data that requires your app to be re-deployed to update and cannot be changed by your application's users (unlike dynamic and temporary data). This is useful for saving data that you need to re-use in your app, but that doesn't change very often, such as strings of text and options in a list. Article series: [Static data](https://manual.bubble.io/help-guides/data/static-data) [Temporary data](https://manual.bubble.io/help-guides/data/temporary-data) [](https://manual.bubble.io/help-guides/getting-started#temporary-data) Sometimes you'll need to store some information temporarily in your application. They can be considered _variables_ and are not in any permanent storage like the database, but live for as long as they are needed. This is useful for holding some information while the user is still one the same page and for navigation. Article series: [Temporary data](https://manual.bubble.io/help-guides/data/temporary-data) [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) [](https://manual.bubble.io/help-guides/getting-started#user-accounts) Bubble has a built-in feature to handle user accounts. In other words, your users can create and log in to their account purely with built-in tools that are secure, efficient and easy to set up. Article series: [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) ### [](https://manual.bubble.io/help-guides/getting-started#logic) Logic The _Logic_ section covers how to make Bubble _do_ stuff: by combining workflows and expressions, you can set Bubble up to perform tasks for your users ranging from very simple to highly complex. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F4EKvQH9AZzJPPYUtVU2I%252Fworkflow-editor.png%3Falt%3Dmedia%26token%3D78b8e5bd-b46a-47e6-a217-02f13de4ae90&width=768&dpr=3&quality=100&sign=ab82bbf4&sv=2) Bubble's workflow editor lets you drag and drop actions that happen whenever an event takes place, such as a button click. [The frontend and the backend](https://manual.bubble.io/help-guides/logic/the-frontend-and-backend) [](https://manual.bubble.io/help-guides/getting-started#the-frontend-and-the-backend) To understand Bubble, is useful to understand the difference between things happening on the page, and things happening on Bubble's server. This article takes a theoretical look at how the two are different – and how they work together constantly to make your app work. Article: [The frontend and the backend](https://manual.bubble.io/help-guides/logic/the-frontend-and-backend) [Workflows](https://manual.bubble.io/help-guides/logic/workflows) [](https://manual.bubble.io/help-guides/getting-started#workflows) Workflows in Bubble are sequences of actions that automate your app's operations. They trigger in response to events such as a button click or page load, allowing you to create dynamic and interactive applications. In short, they are what makes your app _do_ something. Article series: [Workflows](https://manual.bubble.io/help-guides/logic/workflows) [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) [](https://manual.bubble.io/help-guides/getting-started#dynamic-expressions) Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. They can fetch data, change and combine texts, calculate numbers and dates and a lot of other things. Article: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) [Conditions](https://manual.bubble.io/help-guides/logic/conditions) [](https://manual.bubble.io/help-guides/getting-started#conditions) Conditions in Bubble are the rules you set to make your application react to different scenarios. They define the "if this, then that" logic in your app, controlling how elements behave, look or function based on different variables, like user inputs or data changes. Article: [Conditions](https://manual.bubble.io/help-guides/logic/conditions) [Navigation](https://manual.bubble.io/help-guides/logic/navigation) [](https://manual.bubble.io/help-guides/getting-started#navigation) Navigation in Bubble is the way you manage the flow between different pages or parts of your app. It involves creating links, setting up redirects, or loading different groups or popups on a single page. Article series: [Navigation](https://manual.bubble.io/help-guides/logic/navigation) ### [](https://manual.bubble.io/help-guides/getting-started#maintenance) Maintenance Every app requires some testing and maintenance, and Bubble has many different tools for staying on top of it, as well as advanced collaboration features for teams. [Collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration) [](https://manual.bubble.io/help-guides/getting-started#collaborators) One of Bubble's big strengths is the ability to add up to 40 collaborators to your projects. Collaborators are registered Bubble users that you can give access to the editor in a specific app so that you can work on it together. You can also set up independent iterations of your app (called _branches_) that allow your collaborators to concentrate on specific features and changes, maintaining their work separate from other ongoing projects. See [_Version control_](https://manual.bubble.io/help-guides/getting-started#version-control) below. Article: [Collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration) [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) [](https://manual.bubble.io/help-guides/getting-started#version-control) Bubble's version control system lets you divide the development of your project into independent parts, so that you and other editors with access to the project can iterate on one part of the app without impacting other parts. This helps you simultaneously progress multiple streams of work and stay on top of the changes made as each goes from development to testing to deployment. Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) [Commenting](https://manual.bubble.io/help-guides/maintaining-an-application/commenting) [](https://manual.bubble.io/help-guides/getting-started#commenting) Every part of Bubble has a built-in commenting system that lets you add notes to it. For example, you can use commenting to describe what a particular workflow, element or data type is for. This helps you remember important details in your app, and makes it simpler to collaborate with other developers. Article: [Commenting](https://manual.bubble.io/help-guides/maintaining-an-application/commenting) [Database maintenance](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance) [](https://manual.bubble.io/help-guides/getting-started#database-maintenance) Bubble offers multiple tools for maintaining a healthy, secure and performant database. This article series takes a look at how you copy database versions, maintain backups and run bulk operations. Article series: [Database maintenance](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance) [Performance](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling) [](https://manual.bubble.io/help-guides/getting-started#performance) As your app scales, it's important to stick to some best practices to make sure it keeps performing well. This article series explores useful tips, as well as looking at some of the technical soft and hard limits in Bubble's different features. Article series: [Performance](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling) [SEO](https://manual.bubble.io/help-guides/maintaining-an-application/seo) [](https://manual.bubble.io/help-guides/getting-started#seo) SEO (or Search Engine Optimization) is the art of setting up a web page in a way that makes search engines give it a high ranking in its search results. In this section, we'll explore whether this is important for your app, and different ways to prepare your app for the search engine algorithms. Article series: [Search Engine Optimization (SEO)](https://manual.bubble.io/help-guides/maintaining-an-application/seo) [Testing and Debugging](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application) [](https://manual.bubble.io/help-guides/getting-started#testing-and-debugging) Every app needs to be tested and sometimes debugged both before it's published, whenever you add new features and to find the root cause of any issues that come up in the meantime. Bubble gives you tools to preview, test and debug your app isolated from the live version. Article series: [Testing and debugging](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application) [API workflow Scheduler](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler) [](https://manual.bubble.io/help-guides/getting-started#api-workflow-scheduler) API Workflows are scheduled in a log where they can later be cancelled before they run if needed. Bubble's API Workflow Scheduler lets you show all the scheduled workflows and pause or cancel them. Article: [API workflow scheduler](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler) ### [](https://manual.bubble.io/help-guides/getting-started#integrations) Integrations Among Bubble's most powerful features is its set of tools to connect your app to other apps and systems. [API](https://manual.bubble.io/help-guides/integrations/api) [](https://manual.bubble.io/help-guides/getting-started#api) By using what's called an API connection, your application can fetch data and execute commands in external software systems and vice versa. Article series: [API](https://manual.bubble.io/help-guides/integrations/api) [Plugins](https://manual.bubble.io/help-guides/integrations/using-plugins) [](https://manual.bubble.io/help-guides/getting-started#plugins) Bubble's plugin store contains thousands of plugins that extend the platforms core feature set. This can add new elements to your page, connect to external services, do complex calculations and a lot more. Article series: [Plugins](https://manual.bubble.io/help-guides/integrations/using-plugins) [SQL database connector](https://manual.bubble.io/help-guides/integrations/sql-database-connector) [](https://manual.bubble.io/help-guides/getting-started#sql-database-connector) Sometimes you'll need to connect to an external database to make the most of your Bubble app. The SQL Database Connector Plugin is a handy tool that allows you to connect to databases like: * Postgres * MySQL * Microsoft SQL By running SQL queries from within Bubble, you can access information or trigger actions. Article: [SQL database connector](https://manual.bubble.io/help-guides/integrations/sql-database-connector) [Bubble app connector](https://manual.bubble.io/help-guides/integrations/bubble-app-connector) [](https://manual.bubble.io/help-guides/getting-started#bubble-app-connector) Bubble can connect to most other apps by using the API Connector and/or the SQL Connector. Sometimes you may want to connect to another Bubble application, and we have made that option simple to set up using the plugin _Bubble App Connector plugin._ Article: [Bubble app connector](https://manual.bubble.io/help-guides/integrations/bubble-app-connector) ### [](https://manual.bubble.io/help-guides/getting-started#infrastructure) Infrastructure [Security](https://manual.bubble.io/help-guides/security) [](https://manual.bubble.io/help-guides/getting-started#security) Many apps will be handling sensitive information on behalf of its users. Our article series on Security shows you how you keep data safe, set up secure connections with external systems and avoid both malicious attacks and accidental data leaks. Article series: [Security](https://manual.bubble.io/help-guides/security) [Sub-apps](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps) [](https://manual.bubble.io/help-guides/getting-started#sub-apps) The sub-app feature sets up a relationship between a “main app” and one or more “sub applications” and makes it easier to push any changes from the main app to its sub apps, while all main and sub apps have their own database. This is especially useful for certain ideas that involve setting up different (sub/)domains for different clients, which is common in SaaS applications. Article: [Sub-apps](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps) [Bubble Release Tiers](https://manual.bubble.io/help-guides/optimizing-an-application/bubble-release-tiers) [](https://manual.bubble.io/help-guides/getting-started#bubble-release-tiers) The Bubble engine is evolving all the time - on a typical workday, we'll have multiple code rollouts representing any combination of bug fixes, infrastructure improvements, new features, and more. In this article, we'll look at the different options available for applying these updates. Article: [Bubble release tiers](https://manual.bubble.io/help-guides/optimizing-an-application/bubble-release-tiers) [Hosting and scaling](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling) [](https://manual.bubble.io/help-guides/getting-started#hosting-and-scaling) Bubble is not only a no-code platform, but a complete hosting solution that automatically scales as needed. In this article series we'll cover what exactly is included and how the system is designed to scale seamlessly. Article series: [Hosting and scaling](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling) [Compliance](https://manual.bubble.io/help-guides/optimizing-an-application/compliance) [](https://manual.bubble.io/help-guides/getting-started#compliance) When you're developing on Bubble, it's essential to get familiar with different compliance frameworks. They're not just a checklist; they're about building trust, ensuring your users' privacy, and meeting all the necessary legal requirements. In this article series, you'll learn about some of the top compliance frameworks and how they fit into your app's development on Bubble. Article series: [Compliance](https://manual.bubble.io/help-guides/optimizing-an-application/compliance) ### [](https://manual.bubble.io/help-guides/getting-started#bubble-for-enterprise) Bubble for Enterprise [Bubble for Enterprise](https://manual.bubble.io/help-guides/bubble-for-enterprise) [](https://manual.bubble.io/help-guides/getting-started#bubble-for-enterprise-1) Bubble's Enterprise plan is specifically designed to meet the demands and compliance requirements of large organizations. Beyond the standard features, Enterprise plan clients benefit from enhanced capabilities like centralized management for both users and apps, a dedicated support team, and the flexibility to choose their hosting location. Furthermore, our commitment to stringent security measures — from SOC 2 Type II security compliance to advanced DDoS protection — means that business operations remain robust and protected. Plus, with flexible payment options like invoicing or ACH, Bubble aligns with the financial workflows of large-scale organizations. Dive in to understand how our enterprise solutions can enable your organization's digital transformation. Article series: [Bubble for Enterprise](https://manual.bubble.io/help-guides/bubble-for-enterprise) [](https://manual.bubble.io/help-guides/getting-started#additional-resources-and-getting-help) Additional resources and getting help ----------------------------------------------------------------------------------------------------------------------------------------- We have a lot of different resources available to help you on your learning journey – everything from video lessons, live coaches and bootcamps. We list the different resources in the introductory article below: Article section: [Additional learning resources and getting help](https://manual.bubble.io/new-start-here#more-learning-resources) Last updated 22 days ago Was this helpful? --- # The Glossary | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/the-glossary.md) . This list highlights select Bubble-specific terms you might encounter in the user manual and core reference. It focuses on terms with unique meanings within Bubble. Many items on the list provide links to articles and core reference materials, offering deeper insights into the concepts and practical applications of the associated keyword. Use the search feature in your browser to quickly find the term or phrase that you are looking for. Search is usually activated with _CTRL+F_ or _⌘ + F_. Action[](https://manual.bubble.io/the-glossary#action) * An action is a part of a workflow * It is a step that a Bubble workflow takes, i.e. the different kinds of things that workflows can do * Examples include sending an email, logging the user in, showing an element, hiding an element, etc. #### [](https://manual.bubble.io/the-glossary#learn-more) Learn more Article series: [Workflows](https://manual.bubble.io/help-guides/logic/workflows) Article: [Actions](https://manual.bubble.io/help-guides/logic/workflows/actions) Core reference: [List of all actions](https://manual.bubble.io/core-resources/actions) Alert[](https://manual.bubble.io/the-glossary#alert) * The alert is an element type in Bubble that you can add to the page * It can be set to be displayed at any given place on the page, or stick to the top of the page. * It's not visible to the user until you trigger it using the _Show message in alert box_ action. * It's disappears a short (customizable) time after it is displayed. * It's useful for showing a quick warning, error, or confirmation message. API[](https://manual.bubble.io/the-glossary#api) * API is an umbrella term for allowing two apps or systems to exchange data * Bubble can accept inbound API requests and send outbound requests: * **Outbound**: made via the [API Connector plugin](https://manual.bubble.io/the-glossary#api-connector-plugin) * **Inbound**: made via the [Bubble API](https://manual.bubble.io/the-glossary#bubble-api) Learn more: * Article series: [API](https://manual.bubble.io/help-guides/integrations/api) API Connector (plugin)[](https://manual.bubble.io/the-glossary#api-connector-plugin) * The API Connector is a Bubble-built plugin that lets you set up outbound API connections with external services * Can set up the API calls to be used as data sources or workflow actions * Can be installed via the plugins library (Plugins > Add Plugins) #### [](https://manual.bubble.io/the-glossary#learn-more-1) Learn more Article series: [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) Article: [API Connector security](https://manual.bubble.io/help-guides/security/api-security/api-connector-security) Core reference: [API Connector properties](https://manual.bubble.io/core-resources/bubble-made-plugins/api-connector) API workflows[](https://manual.bubble.io/the-glossary#api-workflows) * A type of backend workflow which can be triggered via another workflow anywhere in the app or via an API call * These are defined in the "Backend workflows" page, which shows up in the page selector dropdown in the topnav, once the feature is [turned on in Settings > API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows#activating-and-accessing-the-backend-workflow-editor) * These can be scheduled to run at a later time * If the app's Workflow API is turned on, then an API workflow can also be initiated by an external API call to the app #### [](https://manual.bubble.io/the-glossary#learn-more-2) Learn more Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) Article series: [The Workflow API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api) Core reference: [API workflow properties](https://manual.bubble.io/core-resources/api/the-bubble-api/the-workflow-api) App connector (plugin)[](https://manual.bubble.io/the-glossary#app-connector-plugin) * A feature that lets you connect two Bubble apps so that they interact with one another more seamlessly (as opposed to connecting the two strictly via APIs as if one was a third party) * Can be installed via the [plugins](https://manual.bubble.io/the-glossary#plugin) library (Plugins > Add Plugins) * To learn more, see [section in the Reference](https://manual.bubble.io/core-resources/bubble-made-plugins/bubble-app-connector) #### [](https://manual.bubble.io/the-glossary#learn-more-3) Learn more Article: [The app connector plugin](https://manual.bubble.io/help-guides/integrations/bubble-app-connector) Core reference: [Bubble app connector properties](https://manual.bubble.io/core-resources/bubble-made-plugins/bubble-app-connector) Atom[](https://manual.bubble.io/the-glossary#atom) * Each block of a dynamic expression is known as an atom * Atoms can be: * A [data source](https://manual.bubble.io/the-glossary#data-source) * An [operator](https://manual.bubble.io/the-glossary#operator) * A [comparison](https://manual.bubble.io/the-glossary#comparison) Backend workflow[](https://manual.bubble.io/the-glossary#backend-workflow) * _Backend workflows_ is the umbrella term for any type of workflow you can create in the backend editor. * This is a category of workflow that runs independently of any page of your app - they run in the "backend" #### [](https://manual.bubble.io/the-glossary#learn-more-4) Learn more * Article: [The back-end versus the front-end](https://manual.bubble.io/help-guides/logic/the-frontend-and-backend) * Article section: [Bubble API terminology: Backend workflows](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#whats-the-difference-between-backend-workflows-and-api-workflows) * Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) Branch[](https://manual.bubble.io/the-glossary#branch) * A branch is an independent iteration of your application that can be developed in isolation. * You can see the creation of a branch as splitting your app into two copies, kind of like two cells dividing. The cells are genetically identical clones at first, but can keep evolving independently of each other. * This is useful if you have different developers/teams that are working on specific features in your app: they can work completely independently without disturbing each other's work * Branches are a part of the [version control](https://manual.bubble.io/the-glossary#version-control) feature #### [](https://manual.bubble.io/the-glossary#learn-more-5) Learn more Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Bubble API[](https://manual.bubble.io/the-glossary#bubble-api) * The Bubble API is the umbrella term for Bubble's API features * The [Workflow API](https://manual.bubble.io/the-glossary#workflow-api) * Allows external apps and systems to execute workflows in your app * The [Data API](https://manual.bubble.io/the-glossary#data-api) * Gives external apps and systems secure access to your database * The Bubble API offers security in two different ways * **Authentication** * The process of determining _who_ is trying to access the resource * **Privacy rules** * Conditions applied to data in your database that determines whether the authenticated client has access to search for, read, change or delete data of a specific type * The Bubble API is for _inbound_ API calls (calls made _to_ your app from the outside) as opposed to outbound calls that are made with the [API connector plugin](https://manual.bubble.io/the-glossary#app-connector-plugin) ) Using the Bubble API is among Bubble's most advanced features, but it also offers vast possibilities for integration with other online platforms. Cell[](https://manual.bubble.io/the-glossary#cell) * Each individual row or column in a repeating group or table element is called a _cell_. * Each cell's data source automatically represents the cell's index in the list of loaded data (for example, if you load a list of _users_, each cell will have one user as its data source) * Each cell has an index number, starting with 1 and increasing sequentially #### [](https://manual.bubble.io/the-glossary#learn-more-6) Learn more Article: [Repeating groups](https://manual.bubble.io/help-guides/design/elements/web-app/containers/repeating-groups) Article: [Finding data](https://manual.bubble.io/help-guides/data/the-database/finding-data) Core reference: [Repeating group properties](https://manual.bubble.io/core-resources/elements/containers#repeating-group) Collaborator / Collaboration[](https://manual.bubble.io/the-glossary#collaborator-collaboration) * Any Bubble user that you invite to edit your app is called a collaborator * You can control the access level of each collaborator in the _Collaboration_ setting #### [](https://manual.bubble.io/the-glossary#learn-more-7) Learn more Article: [Collaboration](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration) Comparison[](https://manual.bubble.io/the-glossary#comparison) * A comparison is a part of a [dynamic expression](https://manual.bubble.io/the-glossary#dynamic-expression) * Each part of a dynamic expression is known as an [atom](https://manual.bubble.io/the-glossary#atom) * It's used to compare two values, such as: * Checking whether to users have the same name * Checking whether the number 4 is bigger than the number 5 * Checking whether the creator of a [database thing](https://manual.bubble.io/the-glossary#thing-database) is the current user * A comparison will return either a _yes_ or _no_ * If you come from a traditional programming background, this would be the same as _true_ or _false_ #### [](https://manual.bubble.io/the-glossary#learn-more-8) Learn more Article: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) Current user[](https://manual.bubble.io/the-glossary#current-user) * The current user is a [data source](https://manual.bubble.io/the-glossary#data-source) which returns the [database thing](https://manual.bubble.io/the-glossary#thing-database) of the currently logged-in [user](https://manual.bubble.io/the-glossary#user) * If no user is logged in, it will return a temporary user profile that you can still save data to * Using the current user data source, you can return data such as _Current user's email_ in a [dynamic expression](https://manual.bubble.io/the-glossary#dynamic-expression) #### [](https://manual.bubble.io/the-glossary#learn-more-9) Learn more * Article: [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) Constraint / search constraint[](https://manual.bubble.io/the-glossary#constraint-search-constraint) * A search constraint narrows down the results of a database search by specifying certain conditions that the data must meet * For example, you can search for all users called "Jane Doe" by setting up a constraint that specifies that the field called _name_ should contain the text _Jane Doe_. * You can add as many constraints as you want to a search * Adding more constraints can lead to a faster search, since it helps Bubble rule out things quicker #### [](https://manual.bubble.io/the-glossary#learn-more-10) Learn more Article: [Finding data](https://manual.bubble.io/help-guides/data/the-database/finding-data) Core reference: [Search](https://manual.bubble.io/core-resources/data/search) Custom event[](https://manual.bubble.io/the-glossary#custom-event) * A custom event is a workflow that can be triggered by other workflows using the _Trigger a custom event_ or _Schedule a custom event_ actions. * You can customize the parameters that are passed to the custom event, and set them as optional or required as needed. * You can customize return values that can be passed back to the original workflow that triggered the custom event. They can be optional or required as needed. #### [](https://manual.bubble.io/the-glossary#learn-more-11) Learn more Article: [Custom events](https://manual.bubble.io/help-guides/logic/workflows/events/frontend-events/custom-events) Core reference: [Custom event properties](https://manual.bubble.io/core-resources/events/custom-events) Custom state[](https://manual.bubble.io/the-glossary#custom-state) * A custom state is a way to store temporary variables on an element that can be accessed from anywhere on the same page and during the same session * Custom states are reset when the page is refreshed, meaning they don't store data permanently * They can hold any kind of data like text, numbers, dates or custom data types and can be read, changed and reset as needed using [actions](https://manual.bubble.io/the-glossary#action) * Custom states can hold a default value #### [](https://manual.bubble.io/the-glossary#learn-more-12) Learn more Article: [Custom states](https://manual.bubble.io/help-guides/data/temporary-data/custom-states) Data API[](https://manual.bubble.io/the-glossary#data-api) * The Data API is the part of the Bubble API that lets you invite other apps and systems to read and make changes in your app's database securely * Allows querying of data, as well as creating, updating and deleting * You can secure the Data API using authentication and privacy rules * Must be enabled in _Settings - API_ #### [](https://manual.bubble.io/the-glossary#learn-more-13) Learn more Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) (the Data API is a part of the Bubble API) Article series: [The Data API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api) Core reference: [The Data API](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api) (includes a [list of all request types](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests) ) Data source[](https://manual.bubble.io/the-glossary#data-source) * A data source is any source from which Bubble can pull data, such as: * A database search * An outbound API request * The current user, current date/time and current geographical location #### [](https://manual.bubble.io/the-glossary#learn-more-14) Learn more Article series: [Data](https://manual.bubble.io/help-guides/data) Core reference: [List of data sources](https://manual.bubble.io/core-resources/data/data-sources) Database[](https://manual.bubble.io/the-glossary#database) * The database is where you store dynamic data in your app * It can be created by you, or added by your app's users * Every app has its own two databases; * Development * Live * They two are completely independent, so that you can use one for testing and one for live users * You can create [custom data types](https://manual.bubble.io/the-glossary#data-type) in your app to suit your own needs. For example, you might want to create data types like _projects, blog posts, tasks_ or _blog posts_. * To each of these data types, you can add [_fields_](https://manual.bubble.io/the-glossary#field-field-type) that contain data * Bubble is designed to allow you to set up and configure your database with no prior knowledge, but the underlying technology is PostgreSQL #### [](https://manual.bubble.io/the-glossary#learn-more-15) Learn more Article series: [The database](https://manual.bubble.io/help-guides/data/the-database) Deploying[](https://manual.bubble.io/the-glossary#deploying) * Deploying your Bubble app means pushing the changes you've made in the development environment to the live environment. * This allows users to see and interact with the latest version of your app. * Think of it as publishing or updating your app for the public. #### [](https://manual.bubble.io/the-glossary#learn-more-16) Learn more Article: [Deploying your app](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app) Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) (working with different app branches in isolation and deploying those changes) Do a search for[](https://manual.bubble.io/the-glossary#do-a-search-for) * _Do a search for_ is a [data source](https://manual.bubble.io/the-glossary#data-source) in a [dynamic expression](https://manual.bubble.io/the-glossary#dynamic-expression) , that performs a database search * You can add [constraints](https://manual.bubble.io/the-glossary#constraint-search-constraint) to each search to narrow down the results #### [](https://manual.bubble.io/the-glossary#learn-more-17) Learn more Article: [Finding data](https://manual.bubble.io/help-guides/data/the-database/finding-data) Core reference: [Search](https://manual.bubble.io/core-resources/data/search) Data type[](https://manual.bubble.io/the-glossary#data-type) * A data type is any _type_ of record that you set up your database, such as users, products, blog posts, tasks or whatever your app needs * The _user_ data type is built-in and cannot be deleted, but you can add as many fields as you need to it * Data types apart from the built-in _user_ type are known as _custom data types_ #### [](https://manual.bubble.io/the-glossary#learn-more-18) Learn more Article series: [Data](https://manual.bubble.io/help-guides/data) Debugger[](https://manual.bubble.io/the-glossary#debugger) * Bubble comes with a set of built-in debugging tools * They let you debug workflows and elements in run-time (while you preview your app) * The debugger appears automatically at the bottom of the screen when you preview your app #### [](https://manual.bubble.io/the-glossary#learn-more-19) Learn more * Article: [Debugging your app](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application) * Article: [Previewing your app](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) Dynamic expression[](https://manual.bubble.io/the-glossary#dynamic-expression) * Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. * Dynamic expressions consist of three different building blocks called _atoms_: * [Data source](https://manual.bubble.io/the-glossary#data-source) : any source of data * Operators: functions or actions that can be performed on the data source, such as counting, sorting and calculating * Comparisons: compare two compatible values, such as two numbers, data types or strings of text and get a yes/no result #### [](https://manual.bubble.io/the-glossary#learn-more-20) Learn more Article: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) Core reference: [list of data sources](https://manual.bubble.io/core-resources/data/data-sources) Core reference: [list of operators and comparisons](https://manual.bubble.io/core-resources/data/operations-and-comparisons) Edit mode[](https://manual.bubble.io/the-glossary#edit-mode) * When you are editing your app in the Bubble editor, as opposed to _Run mode._ #### [](https://manual.bubble.io/the-glossary#learn-more-21) Learn more * Article: [The Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) Editor, the / Bubble editor[](https://manual.bubble.io/the-glossary#editor-the-bubble-editor) * The tool you use to edit your Bubble app * Consists of the tabs (click for relevant articles) * [Design](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab) * [Workflow](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/workflow-tab) * [Data](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/data-tab) * [Styles](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/styles-tab) * [Plugins](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/plugins-tab) * [Settings](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab) * [Logs](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/logs-tab) #### [](https://manual.bubble.io/the-glossary#learn-more-22) Learn more Article: [The Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) Element[](https://manual.bubble.io/the-glossary#element) * Elements are the objects you place on the page when you design your app, such as text, buttons, images, icons and calendars * Everything visible on a Bubble page is an element * They are generally self-contained pieces of content that a user can see and potentially interact with #### [](https://manual.bubble.io/the-glossary#learn-more-23) Learn more Article series: [Design](https://manual.bubble.io/help-guides/design) Article series: [Elements](https://manual.bubble.io/help-guides/design/elements) Environments (Development/Live)[](https://manual.bubble.io/the-glossary#environments-development-live) * All deployed Bubble application consist of two different environments: * The **Development environment** allows you to develop and preview your app exactly as it will look when deployed. When testing changes in a branch in the Development environment, the Development database will get populated with test data, which you can view by going to the Data tab and toggling to the Development database. * The **Live environment** contains your live app, which is read-only. When users interact with your live app, the Live database will get populated with live data, which you can view by going to the Data tab and toggling to the Live database by clicking Switch to Live database. * Environments are part of the [version control](https://manual.bubble.io/the-glossary#version-control) feature #### [](https://manual.bubble.io/the-glossary#learn-more-24) Learn more Article: [Previewing your app](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Event[](https://manual.bubble.io/the-glossary#event) * Events are the triggers that start a workflow * Examples include: * An element being clicked * Certain data changing * A input form's value changing * A condition is true Article series: [Workflows](https://manual.bubble.io/help-guides/logic/workflows) Article: [Events](https://manual.bubble.io/help-guides/logic/workflows/events) Core reference: [list of all events](https://manual.bubble.io/core-resources/events) Field / field type[](https://manual.bubble.io/the-glossary#field-field-type) * A field is the actual place in a [data type](https://manual.bubble.io/the-glossary#data-type) where the data is stored, and a data type can have many fields * For example, on the built-in _user_ data type, you might have the fields: * First name (text) * Last name (text) * Address (address) * Some fields are built in: * Created date * Modified date * Unique ID * Slug * Email (only on the _user_ data type) * Fields can also contain a _list_ of a specific type, such as a list of numbers, texts or custom data types #### [](https://manual.bubble.io/the-glossary#learn-more-25) Learn more Article series: [Data](https://manual.bubble.io/help-guides/data) Article: [Data types and fields](https://manual.bubble.io/help-guides/data/the-database/data-types-and-fields) Group[](https://manual.bubble.io/the-glossary#group) * A group is a container element, used to contain other elements * You can load data into a group, and refer to that data on the elements within it * For example, you can load a user into a group, and then show the users email using a text element and the [dynamic expression](https://manual.bubble.io/the-glossary#dynamic-expression) _Parent group's user's email_. * Groups are also a way to control [responsive behavior](https://manual.bubble.io/the-glossary#responsive-design) in your app * You can show and hide groups to navigate within the same page * You can collapse their width and height when hidden to set up single-page-application #### [](https://manual.bubble.io/the-glossary#learn-more-26) Learn more Article: [The Group element](https://manual.bubble.io/help-guides/design/elements/web-app/containers/groups) Core reference: [List of container properties](https://manual.bubble.io/core-resources/elements/containers) Login[](https://manual.bubble.io/the-glossary#login) * In this context, we mean logging into your _app_ and not to your Bubble account * Bubble features a built-in, secure login system that lets users [create an account](https://manual.bubble.io/the-glossary#user) and log in using their preferred credentials * Using [plugins](https://manual.bubble.io/the-glossary#plugin) , you can also allow users to log in using a third-party service like Google or Facebook * Before users can log in, they must [sign up](https://manual.bubble.io/the-glossary#signing-up) #### [](https://manual.bubble.io/the-glossary#learn-more-27) Learn more * Article: [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) Logs / Server logs[](https://manual.bubble.io/the-glossary#logs-server-logs) * Every server-side action performed in a Bubble app is logged and can be viewed in the _Logs_ tab in the Bubble editor * You can use this for debugging your app by auditing the operations that have taken place at a specific time or by a specific user #### [](https://manual.bubble.io/the-glossary#learn-more-28) Learn more Article: [Server logs](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs) Operator[](https://manual.bubble.io/the-glossary#operator) * An operator is part of a [dynamic expression](https://manual.bubble.io/the-glossary#dynamic-expression) * Operators are used to manipulate or aggregate data from a [data source](https://manual.bubble.io/the-glossary#data-source) . For example: * Turning a string of text into UPPERCASE * Counting the number of characters in a string of text * Calculating the the number of results of a search * Operators can be chained together * Bubble will show relevant operators as you build your expression; or example, the _:number of characters_ operator will be visible when you are working with text, but not when you are working numbers #### [](https://manual.bubble.io/the-glossary#learn-more-29) Learn more Article: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) Core reference: [list of operators](https://manual.bubble.io/core-resources/data/operations-and-comparisons) Option set[](https://manual.bubble.io/the-glossary#option-set) * An option set is a static collection of options that can contain multiple fields * It behaves in much the same way as data types, but are not dynamic * This means they cannot be changed without re-deploying your app * It also means they cannot be updated by your users: only by a Bubble developer with access to the [Bubble editor](https://manual.bubble.io/the-glossary#editor-the-bubble-editor) * They become part of your app's source code * This means they load faster than the database, and remains cached on the user's device * It also means they should not contain any sensitive data, since they are downloaded in plaintext to every device that accesses ay page in your app * Option sets are great for storing data that doesn't change frequently, such as a list of: * Colors * Countries/states * Menu options * Dropdown options #### [](https://manual.bubble.io/the-glossary#learn-more-30) Learn more Article: [Option sets](https://manual.bubble.io/help-guides/data/static-data/option-sets) Plugin[](https://manual.bubble.io/the-glossary#plugin) * Plugins are extensions that you can install to add features, elements or integrates third-party services. * The plugin store features thousands of plugins. * Some are made by Bubble, while most are made by third parties * Some are free, while others require a one-time payment or subscription to use * Plugins are installed and paid per app, not per Bubble account * Agencies using the agency plan can install and use all plugins for free while the app is in development. #### [](https://manual.bubble.io/the-glossary#learn-more-31) Learn more Article: [Plugins](https://manual.bubble.io/help-guides/integrations/using-plugins) Privacy / privacy rules[](https://manual.bubble.io/the-glossary#privacy-privacy-rules) * Privacy refers to the protection of user data and information, ensuring it's accessed and shared only by the right user(s) * Privacy and security are closely intertwined, but are not the same thing: privacy is a policy, while security is what maintains that policy * Bubble uses privacy rules to protect data in the database from ever leaving the server if the user is not authorized to access it * Privacy rules also protect data accessed through the Bubble API * Privacy rules are applied to each data type as a condition (i.e. "If this user is logged in, they can access the data) #### [](https://manual.bubble.io/the-glossary#learn-more-32) Learn more Article: [Protecting data with privacy rules](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules) Article series: [Bubble security](https://manual.bubble.io/help-guides/security) Core reference: [Privacy rules settings](https://manual.bubble.io/core-resources/data/privacy) Property editor[](https://manual.bubble.io/the-glossary#property-editor) * The property editor is the part of the Design tab that appears when you double-click on an element or click it in the element tree * It's where you control the properties of that element * Different element types have different properties * It can be made to always be visible by toggling _View > Lock Property Editor_ * This is also where you control an element's responsive properties #### [](https://manual.bubble.io/the-glossary#learn-more-33) Learn more Article: [The property editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-property-editor) Article series: [The Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) Core reference: [Element properties](https://manual.bubble.io/core-resources/elements/shared-properties) Core reference: [Responsive properties](https://manual.bubble.io/core-resources/elements/responsive-properties) Repeating group[](https://manual.bubble.io/the-glossary#repeating-group) * A repeating group is a container element that lets you display a list of things from a data source * This can be any type of data: [things](https://manual.bubble.io/the-glossary#thing-database) from the database, a list of texts, the results of an [API call](https://manual.bubble.io/the-glossary#app-connector-plugin) or any other array of data * Repeating groups can be set up to be displayed horizontally, vertically and as a masonry grid * You can place any kind of [element](https://manual.bubble.io/the-glossary#element) (like text and images) inside each cell of the repeating group, which can load data from the thing in that cell #### [](https://manual.bubble.io/the-glossary#learn-more-34) Learn more Article: [Repeating groups](https://manual.bubble.io/help-guides/design/elements/web-app/containers/repeating-groups) Article: [Finding data](https://manual.bubble.io/help-guides/data/the-database/finding-data) Core reference: [Repeating group properties](https://manual.bubble.io/core-resources/elements/containers#repeating-group) Responsive design[](https://manual.bubble.io/the-glossary#responsive-design) * Responsive design means to design your app to adjust correctly to different screen sizes and resolutions * The goal of responsive design is to allow one page to be equally useful and visually pleasing on different devices such as computers, tablets and mobile phones * Bubble has an advanced responsive engine that allows you to set up pixel-perfect design and responsive rules to control the behavior on different screens #### [](https://manual.bubble.io/the-glossary#learn-more-35) Learn more Article series: [Responsive design](https://manual.bubble.io/help-guides/design/responsive-design) Core reference: [List of responsive properties](https://manual.bubble.io/core-resources/elements/responsive-properties) Run as[](https://manual.bubble.io/the-glossary#run-as) * The _Run as_ feature lets you preview your app as a specific user * This is useful to debug issues: you can see the app exactly as the user experiencing an issue does * It's available in both preview mode and your live app * You will find it in the _Data > App Data > "All Users"_ table. It's a small text link next to the user data in the table. #### [](https://manual.bubble.io/the-glossary#learn-more-36) Learn more Article section: [Previewing your app / Run as](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app#run-as-a-specific-user) Run-mode[](https://manual.bubble.io/the-glossary#run-mode) * When your app is actually running and you have users engaging with it, i.e. when you're running your app, as opposed to editing it ([edit mode](https://manual.bubble.io/the-glossary#edit-mode) ) * When you click _Preview_ in the editor, Bubble opens up the app in run mode, just as if you had visited the URL of your app * Both the "Development" version and the "Live" version of your app have run modes, i.e. if you are editing your app on the Development version and click "Preview", you will enter run mode of the Development version #### [](https://manual.bubble.io/the-glossary#learn-more-37) Learn more Article: [Previewing your app](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) SEO[](https://manual.bubble.io/the-glossary#seo) * SEO, or Search Engine Optimization, is the practice of optimizing your pages to rank highly in search engines such as Google and Bing * It's only needed for pages that you want users to find in search engines, and not for locked pages (pages requiring login for example) * SEO is generally done in two places in Bubble: * The overall app settings * Each individual page #### [](https://manual.bubble.io/the-glossary#learn-more-38) Learn more The article series below goes into both the theoretical part of SEO and how to set it up in Bubble. * Article series: [SEO](https://manual.bubble.io/the-glossary#seo) Signing up[](https://manual.bubble.io/the-glossary#signing-up) * In this context, we mean signing up an account in your _app_, not signing up to a Bubble account * Bubble features a built-in, secure sign-up system that lets users create an account and [log in](https://manual.bubble.io/the-glossary#login) using their preferred credentials * Using [plugins](https://manual.bubble.io/the-glossary#plugin) , you can also allow users to sign up using a third-party service like Google or Facebook #### [](https://manual.bubble.io/the-glossary#learn-more-39) Learn more * Article: [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) SPA (Single-Page Application)[](https://manual.bubble.io/the-glossary#spa-single-page-application) * A Single-Page Application (often abbreviated to SPA) is a way to set up your app's navigation as a single page, as opposed to navigating between pages * This is done by hiding and showing elements on the page * This is predominantly done using the group element, and collapsing its width and height when hidden to make room for another group * This happens instantaneously, making the switch between groups unnoticeable for the user #### [](https://manual.bubble.io/the-glossary#learn-more-40) Learn more Article series: [Navigation](https://manual.bubble.io/help-guides/logic/navigation) Article: [SPAs](https://manual.bubble.io/help-guides/logic/navigation/single-page-applications-spa) Static data[](https://manual.bubble.io/the-glossary#static-data) * Static data in Bubble means data in your app that needs your app to be re-deplyed to be updated * This includes * Option sets * App texts (translations strings) * Element data that's not the result of a dynamic expression (such as text in a text element) * Static data like the ones mentioned above become part of your app's JavaScript code files, and should not contain any sensitive information #### [](https://manual.bubble.io/the-glossary#learn-more-41) Learn more * Article series: [Static data](https://manual.bubble.io/help-guides/data/static-data) Style[](https://manual.bubble.io/the-glossary#style) * Styles are collections of styling properties (colors, borders, fonts, etc) that can be saved, named and applied to multiple elements * Styles are bound to one element type (i.e. styles for buttons, styles for text) * When you create an app, a default set of styles are automatically generated * Styles help keep the look and feel of your app consistent and speeds up development * They also help you make updates to multiple elements at once across pages. Any change you make to a style is automatically applied #### [](https://manual.bubble.io/the-glossary#learn-more-42) Learn more Article: [Styles](https://manual.bubble.io/help-guides/design/variables-and-styles/styles) Template[](https://manual.bubble.io/the-glossary#template) * A pre-built app that you can use as a starting point for creating your own app * Can only be used when starting a brand new app, i.e. cannot be applied retroactively * Usually includes a combination of pages, elements, styles, workflows, etc * There's a large collection of community-developed templates available (see link below) * Some templates are available at no cost, while others require a one-time payment per application #### [](https://manual.bubble.io/the-glossary#learn-more-43) Learn more Page: [Templates](https://bubble.io/templates) Article: [Using templates](https://manual.bubble.io/help-guides/design/using-a-template) Thing (database)[](https://manual.bubble.io/the-glossary#thing-database) * A database thing is a single record of any data type in your database * For example, one user who signs up in your app is one database thing #### [](https://manual.bubble.io/the-glossary#learn-more-44) Learn more Article series: [Data](https://manual.bubble.io/help-guides/data) Core reference: [List of data sources](https://manual.bubble.io/core-resources/data/data-sources) Unique ID[](https://manual.bubble.io/the-glossary#unique-id) * Every database thing in Bubble is automatically assigned a unique ID * I'ts a 32-character string that follows the following format: * 1675853365035x879057409457629600 * You cannot change or delete a unique ID * If you have a SQL database background, the unique ID is the _primary key_ of database records in Bubble #### [](https://manual.bubble.io/the-glossary#learn-more-45) Learn more Article series: [Data](https://manual.bubble.io/help-guides/data) URL parameter[](https://manual.bubble.io/the-glossary#url-parameter) * A URL parameter is a way to pass and read data using the URL in the browser * It follows a key-value format and starts with a "?" after the main URL. * For example, in "my-bubble-app.com/page?navigation=user-profile", "navigation=user-profile" is the URL parameter * URL parameters can be used to pass any kind of data, including custom [data types](https://manual.bubble.io/the-glossary#data-type) (by passing the [unique ID](https://manual.bubble.io/the-glossary#unique-id) of the thing you want to identify) * The upside of using URL parameters is that users can use the _back_ button in their browser to return to the previous URL if needed, meaning that they can use the back button in a [single-page application](https://manual.bubble.io/the-glossary#spa-single-page-application) * You set URL parameters using the go to page action, and the URL parameter is instantly applied without having to reload the page (if you are going to the same page the user is currently on). #### [](https://manual.bubble.io/the-glossary#learn-more-46) Learn more Article: [URL parameters](https://manual.bubble.io/help-guides/data/temporary-data/url-parameters) Article series: [Navigation](https://manual.bubble.io/help-guides/logic/navigation) Core reference: [To to page](https://manual.bubble.io/core-resources/actions/navigation#go-to-page-...) User[](https://manual.bubble.io/the-glossary#user) * Users are a built-in data type in Bubble * They are also the only data type that come with some specific things: * A built-in email field * An authentication system (allowing users to securely [sign up](https://manual.bubble.io/the-glossary#signing-up) and [log into](https://manual.bubble.io/the-glossary#login) your app) * You can set up [privacy rules](https://manual.bubble.io/the-glossary#privacy-privacy-rules) that govern what database data a user has access to * If a user has not yet signed up, Bubble automatically creates a temporary user that you can save data to. That data is transferred to the user when they sign up on the same device. #### [](https://manual.bubble.io/the-glossary#learn-more-47) Learn more * Article: [User accounts](https://manual.bubble.io/help-guides/data/user-accounts) Version control[](https://manual.bubble.io/the-glossary#version-control) * Version control is a set of features that allows you to set up separate [branches](https://manual.bubble.io/the-glossary#branch) in the [Bubble editor](https://manual.bubble.io/the-glossary#editor-the-bubble-editor) * These branches allow team members to work on separate features in isolation * Changes that you make in one branch will not be visible in other branches before they are synced #### [](https://manual.bubble.io/the-glossary#learn-more-48) Learn more Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Version-test[](https://manual.bubble.io/the-glossary#version-test) * The version-test is the preview version of your app * You can see _version-test_ in the URL when you preview your app: * https://my-bubble-application.bubbleapps.io/**version-test**/page * The development environment has a separate, independent database from the live environment to help you test your app's features without affecting live data * If you remove _version-test_ from the URL, you will be taken to the live app instead (if your app has been deployed) #### [](https://manual.bubble.io/the-glossary#learn-more-49) Learn more Article: [Previewing your app](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) Workflow[](https://manual.bubble.io/the-glossary#workflow) * A workflow is the combination of an [event](https://manual.bubble.io/the-glossary#event) (such as a button-click) and one or more [actions](https://manual.bubble.io/the-glossary#action) * Workflows either belong to a specific page (and thus only run when a user is on that page) or is an API Workflow that can be run or scheduled server-side, or with an API call * Workflows are what makes your app react to user interaction, including: * Making changes in the database * Hiding/showing elements * Navigating to another page or external site * Sending emails #### [](https://manual.bubble.io/the-glossary#learn-more-50) Learn more Article series: [Workflows](https://manual.bubble.io/help-guides/logic/workflows) Core reference: [List of events](https://manual.bubble.io/core-resources/events) Core reference: [List of actions](https://manual.bubble.io/core-resources/actions) Workflow API[](https://manual.bubble.io/the-glossary#workflow-api) * The Workflow API is a part of the Bubble API, and allows external apps and systems to trigger API workflows by making an API call to your app * The Workflow API must be enabled in _Settings > API_ * The Workflow API lets you set up [API workflows](https://manual.bubble.io/the-glossary#api-workflows) #### [](https://manual.bubble.io/the-glossary#learn-more-51) Learn more Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) Article series: [The Workflow API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api) Core reference: [API workflow properties](https://manual.bubble.io/core-resources/api/the-bubble-api/the-workflow-api) Last updated 1 year ago Was this helpful? --- # Payments in mobile apps | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps.md) . **Note:** The information in this article is provided as a general overview. Platform policies change over time, and the authoritative sources are the official documentation from each platform: * [App Store Review Guidelines](https://developer.apple.com/app-store/review/guidelines/) — Apple * [Google Play Payments policy](https://support.google.com/googleplay/android-developer/answer/9858738) — Google Always refer to these documents for the most up-to-date requirements before publishing your app. Payments in native mobile apps work differently from payments on the web. While a web app can integrate with any payment processor and charge users directly, native mobile apps are subject to platform rules set by Apple and Google. Understanding these rules is essential when planning monetization for your mobile app. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#why-mobile-payments-are-different) Why mobile payments are different Apple's App Store and Google Play have strict policies on how apps can charge users for digital goods and services. Both platforms require that purchases of digital content, features, or subscriptions go through their own in-app purchase systems — Apple's StoreKit and Google's Play Billing. These systems handle the transaction, take a commission, and distribute the remainder to the developer. This rule is enforced at the platform level. Submitting an app that bypasses these systems to charge users for digital goods will typically result in rejection during the review process. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#when-in-app-purchases-are-required) When in-app purchases are required In-app purchases are required for any digital goods or services consumed within the app. This includes: * Subscriptions to premium content or features * Unlocking app features or removing ads * Virtual currency or in-game items * Digital content such as articles, videos, or audio The platform takes a commission on these transactions — typically 15% to 30%, depending on the developer's agreement and revenue thresholds. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#when-in-app-purchases-are-not-required) When in-app purchases are not required Apple and Google allow external payment methods for certain categories of goods and services. These include: * Physical goods and services (such as ecommerce purchases or ride bookings) * Services consumed outside the app (such as a meal delivered or a ride taken) * Business-to-business transactions * Donations to nonprofit organizations For these categories, you can use any payment processor, including Stripe, PayPal, or others integrated through Bubble's API connector or plugins. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#in-app-purchases-in-bubble) In-app purchases in Bubble Bubble currently supports subscriptions through in-app purchases. This means you can offer recurring subscription products in your native mobile app and have them processed through Apple's or Google's billing systems. You can read more about in-app purchases in the article series below: Article series: [In-app purchases](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#choosing-a-payment-approach) Choosing a payment approach When planning payments in your native mobile app, consider what you're charging for: * If you're selling **digital subscriptions**, use Bubble's in-app purchase support. * If you're selling **physical goods or services consumed outside the app**, you can use external payment processors like Stripe. * If your app combines both — for example, an ecommerce store with a premium subscription tier — you may need to use both approaches, with each transaction routed through the appropriate system. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#platform-commission-and-pricing) Platform commission and pricing The rates below are provided as a general overview and may change over time. Always refer to the official platform documentation for current rates and terms. Apple and Google take a commission on all in-app purchases, which affects your pricing strategy. The standard rates are: * 30% on most purchases in the first year of a subscription * 15% on subscription renewals after the first year * Reduced rates for developers earning under a certain revenue threshold (currently $1 million per year) Factor these commissions into your subscription pricing to ensure your revenue targets are met after the platform's cut. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#testing-in-app-purchases) Testing in-app purchases Both Apple and Google provide sandbox environments for testing in-app purchases without charging real money. Use these environments to verify that your purchase flows, subscription renewals, and cancellation handling work correctly before submitting your app for review. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#faq-payments-in-mobile-apps) FAQ: Payments in mobile apps ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Why can't I just use Stripe to charge for subscriptions in my mobile app?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#why-cant-i-just-use-stripe-to-charge-for-subscriptions-in-my-mobile-app) Apple and Google require all purchases of digital goods and services, including subscriptions to digital content or features, to go through their own billing systems. Using an external payment processor like Stripe for these purchases will typically result in app store rejection. Can I use Stripe at all in my mobile app?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#can-i-use-stripe-at-all-in-my-mobile-app) Stripe for mobile is not officially supported by Bubble as of now. Technically, you can set up payments with any provider, but only for physical goods and services consumed outside the app. Examples include eCommerce purchases, food delivery, ride bookings, and event tickets. Can I offer the same subscription on web and mobile?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#can-i-offer-the-same-subscription-on-web-and-mobile) Yes, but you'll need to handle each platform's billing system separately. Web subscriptions can use any payment processor, while mobile subscriptions must go through Apple's or Google's billing systems. Most apps maintain a single user account that recognizes subscriptions purchased on either platform. Can I link to my website to let users subscribe there instead?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#can-i-link-to-my-website-to-let-users-subscribe-there-instead) Both Apple and Google have strict rules about steering users to external payment methods. The rules vary by region and have been changing in response to recent legal developments. Refer to the official platform documentation for current guidance. What if my app is rejected for payment-related reasons?[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps#what-if-my-app-is-rejected-for-payment-related-reasons) The most common reasons for rejection are using external payment methods for digital goods, or failing to use the platform's in-app purchase system where required. Review the platform's payment guidelines carefully and update your app to comply before resubmitting. Last updated 22 days ago Was this helpful? --- # Differences in native and web elements | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements.md) . [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#views) Views ------------------------------------------------------------------------------------------------------------------------------------------------------- #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#views-compared-to-pages) Views compared to pages Having built web apps with Bubble, you’re likely familiar with the concept of pages: each page is a distinct entity, and everything you design and deploy is contained within these individual pages, with each loading as a separate resource. Views work a bit differently. While they still act as the top parent element for all nested content, they are not standalone resources that require reloading when switching between them. Instead, views are part of a unified structure within your app, allowing users to navigate between them seamlessly without the need for reloading each time. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#views-compared-to-groups) Views compared to groups Again, if you’re familiar with the Bubble web app tools, especially if you have experience building single-page applications, you’re likely accustomed to setting up groups and showing or hiding them (often by collapsing their height/width) to let users seamlessly navigate different sections within a single page. Views share similarities with this approach, but they are more closely aligned with mobile app development principles. Rather than relying on groups within a single page, views represent distinct sections or screens of your app while still being part of a fluid and cohesive navigation flow. This structure makes views a more natural fit for mobile app patterns like stack navigation, tab navigation, and swipe gestures, offering a smoother and more intuitive user experience on mobile devices. Lastly, collapsible groups are available in the native mobile app editor as well, meaning the two are not in any way mutually exclusive, but used for different purposes. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#navigation-types) Navigation types Views differ from pages and groups in that the action used to navigate to a new view determines how that view behaves. In other words, the settings in the _Go to view_ action influence how the user interacts with and navigates within the view. * **Stack navigation** follows a hierarchy where views are layered on top of one another as the user navigates deeper into the app, much like individual cards being stacked in a deck. Each new view is "pushed" onto the stack, and users can "pop" back to previous views using a back button, either physical or on-screen. This is often used in scenarios where users navigate into more detailed content, such as moving from a list of items to a detailed view of a specific item. The key feature is that stack navigation maintains the history of previous views, allowing for smooth back-and-forth navigation. * **Modal views** are used for temporary, self-contained interactions that are separate from the primary navigation flow. When a modal is opened, it typically slides up from the bottom of the screen or appears over the existing content, blocking interaction with the background until it is dismissed. Modals are commonly used for actions like filling out forms, confirming choices, or displaying brief contextual information. Unlike stack navigation, modals don’t contribute to the app’s main navigation history and are usually dismissed rather than navigated away from. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#sheets) Sheets --------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#sheets-compared-to-floating-groups) Sheets compared to floating groups When building a Bubble web app, you may have used floating groups as a way to place content at the top, bottom or side of the screen, often on top of other elements. Sheets offer similar functionality, but with some key differences: * **Positioning and behavior:** Sheets slide in and out as temporary overlays, while floating groups are static and anchored to a specific part of the screen. * **Use cases:** Sheets are used to display temporary or contextual information in a way that’s anchored to mobile design principles, while floating groups are better suited for persistent elements like navigation menus, headers, or footers that remain in view as the user interacts with the page. * **Interaction:** Sheets usually involve a dynamic transition (e.g., sliding up/down). Floating groups can be set up to imitate this behavior, but their default behavior is to be fixed in place without such transitions ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#sheets-compared-to-popups) Sheets compared to popups Sheets also share some similarities with popups (though popups are not available in the native mobile app editor). However, sheets shouldn’t be viewed as a direct replacement. As mentioned earlier, sheets can cover part or all of the screen and can blur the content underneath, much like popups. In this way, you can think of sheets as a more mobile-optimized version of popups that aligns better with design patterns on iOS and Android. Let’s look at some of the differences between the two: * **Positioning and behavior:** Popups typically appear centered on the screen and overlay the entire page, dimming the background, whereas sheets slide in from the bottom and occupy a portion of the screen while keeping the rest of the content visible. * **Use cases:** Popups are ideal for grabbing the user’s full attention, such as displaying alerts, confirmation dialogs, or forms. Sheets, on the other hand, are better suited for displaying contextual information or options without fully interrupting the user’s flow, staying anchored to the bottom of the screen in a more mobile-friendly way. * **Interaction:** Popups usually fade in or appear with a custom animation, often requiring the user to click outside the popup or press a button to close it. Sheets involve a sliding transition (e.g., sliding up/down) and can often be swiped away by the user, mimicking native mobile app behavior. Sheets are often used for displaying contextual data and actions when you don’t want to change views or block the entire screen. For the user, a sheet appears as a layer on top of the content they’re currently viewing, allowing them to interact with it while keeping the underlying content accessible. The ability to slide the sheet to adjust its size or hide it mimics the feel of a real-world object. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#lists) Lists Lists in the native mobile app editor are a way to show lists or records, comparable to repeating groups in a Bubble web app. Still, the two serve some key differences. * **Element versus property:** In a Bubble web app, lists are typically managed by elements like repeating groups or tables. In the native mobile app editor, however, lists can be a property of an element, such as a view or sheet. This means a single element can hold either a single item or a list, depending on its settings, whereas in the web editor, lists are usually managed by dedicated elements like repeating groups or tables.. Vertical lists can also be added as an element, similarly to setting up a vertically-scrolling repeating group in the web app editor. * **List behavior:** lists can also be automatically divided into groupings. The mechanics differ from using a nested repeating group, and behaves more like like the _Group by_ operator (although the two are not exactly the same). ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#dropdowns) Dropdowns: While dropdowns (select menus) may seem like an obvious choice for presenting multiple options on web apps, they often create a poor user experience on mobile apps. Here's why: 1. **Hidden options:** Dropdowns hide available choices until tapped, making it difficult for users to see all options at a glance. 2. **Multi-step process:** Selecting an option requires multiple actions: tapping to open, scrolling to find the desired option, selecting it, and closing the dropdown. 3. **Scrolling difficulties:** Long lists (e.g., country selectors) can be cumbersome to navigate, especially without keyboard search on mobile. 4. **Small tap targets:** Dropdown areas and individual options can be small, leading to accidental selections. 5. **Lack of context:** Users can't easily compare options or see relationships between choices. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements#recommended-alternatives) Recommended alternatives Instead of dropdowns, consider these more user-friendly UI patterns. Opting for these alternatives can enhance the mobile experience by reducing taps and lowering cognitive load, making navigation more intuitive and efficient for your users. 1. **Switches:** For binary (on/off) choices. 2. **Radio buttons or segmented controls:** For a small number of mutually exclusive options (2-5). 3. **Steppers:** For incrementing/decrementing numeric values. 4. **Sliders:** For selecting from a range of values. 5. **Auto-complete Text Fields:** For large sets of options where users can type to filter (e.g., country selection). 6. **Bottom sheets or action sheets:** For presenting a list of options in a larger, more scannable format. 7. **Buttons:** For a small set of distinct actions. 8. **Prioritized lists:** Show the most common options upfront, with an "Other" option to access less frequent choices. Last updated 22 days ago Was this helpful? --- # In-app purchases | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases.md) . [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#introduction) Introduction ----------------------------------------------------------------------------------------------------------------------------------------------- Bubble’s In-App Purchases (IAP) feature lets you monetize native mobile apps using the billing systems provided by Apple and Google. **Bubble currently supports subscriptions only.** One-time digital purchases, such as consumable tokens or credits, are currently not supported. While Bubble automates and simplifies much of the setup, **in-app purchases are governed by Apple App Store and Google Play policies**. Before submitting an app for review, you should review and follow the guidelines set by each platform to ensure a smooth approval process. [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#what-is-bubbles-in-app-purchases-feature) What is Bubble’s in-app purchases feature? --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Bubble’s IAP feature is a native, cross-platform integration with Apple StoreKit and Google Play Billing. It allows you to offer subscriptions in a Bubble native mobile app using each platform’s in-app purchase system. With this feature, you define your subscription model in Bubble—including subscription groups, subscription tiers, and billing variants, and connect these to corresponding subscription products in the Apple and Google developer consoles. Bubble subscription objects act as a shared layer between Apple’s and Google’s billing systems, allowing you to support cross-platform subscription flows without building separate logic for each platform. While Bubble provides the tooling to create and manage subscription flows, **all transactions are processed by Apple’s and Google’s billing systems**, in the same way that web payments are processed by providers such as Stripe. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#do-i-need-to-use-in-app-purchases) Do I need to use in-app purchases? Apple and Google define when in-app purchases are required and when alternative payment methods are allowed. IAP rules can be complex and may change over time, so the official documentation of each respective platform should always be treated as the source of truth. The [guidelines](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#you-must-use-in-app-purchases-if-you-sell) below provide general direction. Official documentation for Apple and Android[](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#official-documentation-for-apple-and-android) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#apple) Apple Apple's IAP article describes how their in-app purchases work, rules for the platform and best practices. External page: [In-app purchase | Apple Developer Documentation](https://developer.apple.com/design/human-interface-guidelines/in-app-purchase) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#android) Android Android's landing page for IAP explains how their payment system works, along with an extensive FAQ. External page: [Understanding Google Play’s Payments policy | Play Console Help](https://support.google.com/googleplay/android-developer/answer/10281818?hl=en) #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#you-must-use-in-app-purchases-if-you-sell) You must use in-app purchases if you sell * **Digital content consumed within your app**, including premium features, subscriptions, virtual goods, additional content, or app-only functionality * **Digital services delivered through your app**, such as ongoing access to features, cloud storage, or digital tools #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#you-may-use-other-payment-methods-if-you-sell) You may use other payment methods if you sell * **Physical goods or services**, such as shipped products, food orders, ride-sharing services, or hotel bookings * **Real-world services**, including appointments, classes, or professional services performed outside the app * **Digital goods primarily consumed outside the app**, such as content accessed across multiple platforms * **Multi-platform SaaS products**, where the mobile app acts as a companion to a web-based service. See more [below](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#multi-platform-saas-considerations) . ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#multi-platform-saas-considerations) Multi-platform SaaS considerations If you’re building a SaaS product with both web and mobile apps, there are additional considerations: * Users can subscribe through your website using Stripe or another payment processor * The mobile app can provide access to users who already have an active subscription * **Important:** If the mobile app allows users to purchase, upgrade, or manage subscriptions within the app, in-app purchases must be used * **Important:** Mobile apps cannot include links or calls to action that direct users to external payment pages For example, a project management app may allow existing web subscribers to use the mobile app freely, but any new subscription initiated from the mobile app must be purchased through in-app purchases. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#when-in-doubt) When in doubt If you’re selling digital content or features that users primarily access through your mobile app, in-app purchases are typically required. Apps that attempt to bypass Apple or Google’s billing systems for digital goods are likely to be rejected during app review. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#subscription-support) Subscription support Bubble’s in-app purchases feature supports subscriptions only. One-time digital purchases, such as consumable tokens or credits, are not supported by this feature. ### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#scope-of-the-in-app-purchases-feature) Scope of the in-app purchases feature Bubble’s IAP feature includes the components needed to set up a compliant subscription experience in a native mobile app. It can be divided into four main areas. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#initial-setup) Initial setup * A guided setup flow to enable in-app purchases for your app on each app store. * A guided setup flow to connect your app backend to Apple and Google billing server notifications. #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#product-setup) Product setup * A guided setup flow to define your subscription model in Bubble and link it to Apple and Google subscription products. Your subscription model consists of the following concepts: * **Subscription group:** A collection of related subscription tiers * **Subscription tier:** Defines the level of access a user has to app features * **Billing variant:** Defines the billing frequency and price for a subscription tier #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#workflows-and-data-updates) Workflows and data updates * A **Subscription Purchases** data type that acts as the source of truth for a user’s subscription status and is automatically updated when Apple or Google send billing notifications * New operators that help define subscription logic and interfaces, such as checking whether a user is subscribed to a specific tier * Workflow actions for initiating subscription purchases and managing existing plans * Backend workflow events that allow you to define custom behavior when server-side billing notifications are received from Apple or Google #### [](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#testing-in-development) Testing in development Apple and Google provide sandbox environments for testing in-app purchases through TestFlight or platform-specific testing tracks. These environments reflect real billing behavior without actually charging, but typically require a new build or OTA update after changes. Bubble also provides simulated testing tools that allow you to test purchases, upgrades, downgrades, and cancellations in the development database. These simulations trigger the same backend workflow events as real purchases, without making calls to Apple or Google, making it easier to test subscription flows in BubbleGo and Web Preview. Last updated 22 days ago Was this helpful? * [Introduction](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#introduction) * [What is Bubble’s in-app purchases feature?](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#what-is-bubbles-in-app-purchases-feature) * [Do I need to use in-app purchases?](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#do-i-need-to-use-in-app-purchases) * [Multi-platform SaaS considerations](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#multi-platform-saas-considerations) * [When in doubt](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#when-in-doubt) * [Subscription support](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#subscription-support) * [Scope of the in-app purchases feature](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases#scope-of-the-in-app-purchases-feature) Was this helpful? --- # Native mobile app terminology | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-app-terminology.md) . While the Native Mobile App Editor is similar to building a regular Bubble app in many ways, there are some new terms and concepts introduced specifically for mobile development. Some of these terms may be familiar, but we recommend reviewing them to ensure you’re aligned with the exact definitions we’ll be using throughout the documentation. Term Definition App scheme This setting defines a custom identifier for your app, used primarily in scenarios where external services need to redirect users back to the app after completing an action. This is commonly required for callbacks from OAuth providers, payment gateways, or other integrations that require redirection to the app. Bubble web app / web app This is the term we use to describe the “regular” Bubble web app editor, as opposed to this native mobile app editor. Cross-platform Cross platform means a native mobile app that is built once, but works on both iOS and Android devices out of the box. Cross-platform in this context does not include web. Gesture A gesture is similar to a click in web, but includes things like taps, long press, swipes, pans, and pinches. Users use gestures to interact with a mobile app’s UI and trigger workflows. Global component Global component in this doc refers to a component, such as the tab bar, that behaves similar to a reusable element in the sense that it is available on every view, but editing it changes the component across your app. Global components are generally system components offered by Bubble, rather than as something the user builds from scratch. “Mobile friendly” app A mobile friendly, or responsive, app is a web application that is opened in a user’s mobile browser. This type of app has been designed to look and perform well on smaller or larger screen sizes. Native mobile app A native mobile app is an app that can generally only be downloaded from the Google Play or Apple app store and runs native Swift code on Apple devices and Kotlin code on Android devices. This means it has full access to device hardware, software, and gestures. Native mobile app editor This is the term we use to describe the part of the Bubble editor where you edit your native mobile app, as opposed to the above Bubble web app. Progressive web app A progressive web app (PWA) is a responsive web application that has been wrapped in a service that allows it to run on a mobile device from the home screen rather than a user’s browser. While iOS and Android platforms are supporting more functionality these days, they are generally limited in what device hardware and software they have access to as opposed to native mobile apps. Note: Android supports far more functionality on PWAs than Apple does. Section list A section list is like a vertical list, but it groups your list items by some property on your data source. For example, your contacts app is a section list because it groups your contacts by the first letter of the contacts name. Safe area Newer devices have notches, floating islands, curved bezels, etc. which must be accounted for when designing your app. Safe areas are areas on your phone that could be impacted by these device idiosyncrasies. View Similar to a page web. This is the highest level “container” and represents what the user will see on their screen when on a particular view Last updated 22 days ago Was this helpful? Was this helpful? --- # Planning features | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features.md) . Before you start building, you need to decide what kind of features your app needs. Most app ideas start out as a general vision of what the app is supposed to do. You then take that vision and breaks it into the features needed to make that happen. When you've decided on the features you need, you can start planning how those features should work in an actual interface. In this article, we'll cover: * [What a features is](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#what-is-a-feature) * [How to plan what features you want to include in the first version of your app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#planning-features-for-your-mvp) * [Setting up user journeys to decide how a specific feature should work](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#the-user-journey) [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#what-is-a-feature) What is a feature? -------------------------------------------------------------------------------------------------------------------------------------------- A **feature** is essentially a distinct function or capability that an app offers. It's what allows users to perform certain tasks or achieve specific outcomes within an app. They can broadly be categorized into two types: _general features_ and _specific features_. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#general-features) General features These are foundational features commonly found in a majority of apps across different genres. They form the basic infrastructure, facilitating the core user interactions. Typical examples include: * **User sign-up/sign-in**: allow users to create an account and log into the app * **Reset password:** let users reset their password without you as the developer having to intervene * **Notifications**: alert users about updates, messages, or other important information * **Search bar**: let users search for content General features are what makes your app _work_, but they're not what sets it apart. When you plan your app, it's a good idea to list these features as well, to make sure you have the full picture of the project ahead. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#specific-features) Specific features Specific features are unique to the nature and purpose of the app. They are linked closely with the app's core idea. For instance: * For a food delivery app, a specific feature might be the ability for users to explore a restaurant's menu and add items to a cart * In a language learning app, a custom vocabulary quiz tailored to a user's learning history could be a specific feature. * For a budgeting app, a feature that projects future savings based on current spending habits might be included. The specific features are what sets your app apart from other apps: the reason it's being developed in the first place. If your app exists to solve a problem, the app's features are _how_ the problem will be solved. Next, let's look at how you can prioritize features by thinking of your app in _versions_. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#think-in-versions) Think in versions ------------------------------------------------------------------------------------------------------------------------------------------- It's useful to think of your app in versions, so that you know what exactly you are building. It's very easy to come up with new ideas as you work, and get sidetracked from your initial plan. By planning out versions, you can stay focused on delivering a core set of features first, and then progressively enhance and expand your app based on feedback and actual user needs. For example, you could think about your versions as follows: **1\. MVP (Minimum Viable Product):** This is the most basic version of your app, with only the essential features needed to make it functional. The goal here is to get something to market quickly to test the concept, gather feedback, and identify potential improvements and even pivots. **2\. Version 1.0:** Once you've validated the idea with your MVP, it's time to refine. This version will have improved UX/UI, and possibly some new features based on the feedback from your MVP. You'll also address any significant bugs or problems identified during the MVP phase. **3\. Version 2.0 (and beyond):** As your user base grows and you collect more feedback, you'll start to identify more areas for enhancement and expansion. This could involve adding new features, improving existing ones, or expanding into new markets or platforms. Remember, it's tempting to want to add every feature you can think of from the get-go, but restraint can help you get your app to the market on schedule. Every time a good idea comes up, you can of course take note of it, and plan it into a future version. Furthermore, taking a step-by-step approach allows you to adapt and pivot based on real-world feedback, rather than assumptions. Users will often use your app in ways you hadn't anticipated or express needs you hadn't considered. By listening to them and iterating on your product, you increase the chances of your app's success in the long run. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#planning-features-for-your-mvp) Planning features for your MVP --------------------------------------------------------------------------------------------------------------------------------------------------------------------- The first version of an app is often referred to as the Minimum Viable Product (MVP). The goal is to create something functional that effectively addresses the primary need or problem you've identified, without getting bogged down in secondary features or details. Here's how you can approach this: 1. **Identify the core problem:** What primary problem does your app aim to solve? Understanding this will help you prioritize the features that are absolutely necessary for your MVP. 2. **User stories:** Draft user stories to envision how users will interact with your app. For example: "As a user, I want to be able to create new contacts so that I can keep track of my clients." 3. **Prioritize features:** List all the features you envision for your app and then rank them based on their importance to the core problem. Focus on the top priorities for your MVP. 4. **Sketch or wireframe:** Use sketches or wireframes to map out the user journey and interface. This visual aid will help you understand how the features integrate and flow together. 5. **Feedback loop:** Share your prioritized feature list and wireframes with potential users, stakeholders, or teammates. Gather feedback and adjust your plan accordingly. 6. **Avoid** **feature creep****:** It's tempting to add more features as you plan, but stay focused on the primary goal. Additional features can always be added in later versions once the MVP has been tested and validated. 7. **Technical feasibility:** If you are unsure whether Bubble is the right platform for your project, you can get in touch with our [Success team](https://bubble.io/contact) or ask other users in our active [forum](https://forum.bubble.io/) . Describe your idea and you can quickly get feedback on whether it's feasible. 8. **Plan for feedback collection:** As the purpose of the MVP is to test and validate your idea, have mechanisms in place (like feedback forms, analytics tools, etc.) to gather user feedback once it's launched. Even if Bubble is a very efficient tool to build in, don't be afraid to leave out features that are not absolutely needed to get your idea validated. You can always add those in later. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#the-user-journey) The user journey ----------------------------------------------------------------------------------------------------------------------------------------- A user journey represents the series of steps or interactions a user undertakes to achieve a particular goal within your app or website. By mapping out these journeys, you can make sure that you have a plan for how users will reach a specific goal step-by-step. When designing user journeys, start by envisioning a specific persona. _Who_ is the individual embarking on this journey? Understanding this user's characteristics can guide you in tailoring the experience to suit their needs. For instance, while some users might be tech-savvy, others could benefit from more detailed instructions and a prominent call-to-action. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#sign-up-user-journey) Sign-up user journey For example, you could set up a user journey for signing up to your app. This process can be a critical, as it often represents a user's first interaction with your app. 1. **User persona**: * **Name**: Sarah * **Age**: 28 * **Tech-savviness**: Moderate * **Goal**: To sign up for the app quickly and without hassles to explore its features. 2. **Entry point**: Sarah hears about the app in social media and decides to try it out 3. **Opening the app**: Sarah opens the app and is greeted with a welcome screen showcasing the app's main features. 4. **Call to action**: After the intro slides, Sarah sees two prominent buttons: "Sign Up" and "Log In." 5. **Sign up option**: Sarah clicks on "Sign Up" and is presented with options: * "Sign Up with Email," * "Sign Up with Google," * "Sign Up with Facebook." 6. **Choosing sign-up method**: Wanting to keep things simple, Sarah chooses "Sign Up with Google." 7. **Permissions**: A prompt asks Sarah to allow the app to access her Google account info. She confirms. 8. **Additional details**: The app asks Sarah for a few more details to enhance her experience: her interests and preferences related to the app's features. 9. **Confirmation and feedback**: Once she provides the details, Sarah gets a success message: "Thank you for signing up, Sarah! Let's get started." 10. **Profile setup** (optional step): Sarah is then prompted to complete her profile by adding a profile picture and other optional details. 11. **First use experience**: After the onboarding, Sarah is directed to the app's main dashboard or home screen to start exploring. 12. **Follow-up email**: Five minutes later, Sarah receives a welcome email reiterating the app's features and providing resources like FAQ and customer support links. Throughout this journey, keep the following things in mind: * Ensure that each step is intuitive and not overwhelming. * Provide clear instructions and feedback. * If needed, make it easy to ask for help. * Keep the number of steps minimal, asking only for necessary information to ensure a high signup rate While many sign-up processes look very similar, you don't need to see this as a blueprint: you are free to add or remove steps that you think make sense for your app. The idea is to know what the process should look like _before_ you start building. This approach ensures you don't overlook crucial steps, making your development process as efficient as possible. You can set up the user journey in steps, like we did in the example, but you can also use apps like [Miro](https://miro.com/) , [Apple Freeform](https://www.apple.com/newsroom/2022/12/apple-launches-freeform-a-powerful-new-app-designed-for-creative-collaboration/) or [Lucid](https://lucid.app/) to set it up more visually. Sometimes, good old pen and paper works best. In the next section, we'll explore how you can think about the [data that you want to manage in your app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure) . Last updated 22 days ago Was this helpful? * [What is a feature?](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#what-is-a-feature) * [General features](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#general-features) * [Specific features](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#specific-features) * [Think in versions](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#think-in-versions) * [Planning features for your MVP](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#planning-features-for-your-mvp) * [The user journey](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#the-user-journey) * [Sign-up user journey](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features#sign-up-user-journey) Was this helpful? --- # Database structure | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure.md) . Now that you have decided on the features you want in your app, it's time to start thinking about how you structure your data. We won't go into the _technical_ details on how to set that up just yet, but keep focusing on the planning stage. We also have a long list of guides that go into detail on how to plan a database structure for a specific app category (like a project management app, marketplace app or blog). You can use this as inspiration for your project and learn how experienced Bubble developers think: Article series: [Database structure by app type](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type) [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#visualizing-your-data) Visualizing your data ---------------------------------------------------------------------------------------------------------------------------------------------------- When you plan your database structure, you should take notes. There are a range of different ways to do this, and there's really no "best practice". You should use whatever method makes sense to you. For many users, simply noting things down with pen and paper or on a whiteboard is the most efficient way, at least for the first planning stage. You can also consider apps that focus on whiteboarding and diagrams, such as [Miro](https://miro.com/) and [Lucid.app](https://lucid.app/) . ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FvfESatLCZjrge0za0tuf%252Fsketch-of-a-diagram-2022-11-02-17-55-57-utc%25202.jpg%3Falt%3Dmedia%26token%3Dc9ac2f8b-3ce0-47aa-9d61-73e71289b19c&width=768&dpr=3&quality=100&sign=3e777fea&sv=2) Planning your database structure doesn't need fancy tools: use whatever you're comfortable with. Pen and paper works just fine. Don't worry about taking notes in the "right" way: your goal is simply to get an understanding of what kind of data you want to store before you start building. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#the-data-types) The data types -------------------------------------------------------------------------------------------------------------------------------------- Transitioning from SQL Databases? Here's what to know in Bubble.[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#transitioning-from-sql-databases-heres-what-to-know-in-bubble) In traditional databases, relationships between tables are commonly maintained through primary and foreign keys that act as unique identifiers. However, when learning Bubble, you'll notice that it's handled a bit differently. Bubble simplifies database relations with its intuitive design. Rather than juggling keys, Bubble allows for direct linking of data types. This not only streamlines data management but also offers a more user-friendly and visual experience for those who don't have a background in database design. You can read more about this in the article section below. Article section: [How the Bubble database is different from traditional databases](https://manual.bubble.io/help-guides/data/the-database#how-the-bubble-database-is-different-from-traditional-databases) If you are interested in learning more about the underlying technology that powers database, we also have a section that covers this: Article section: [Technical information about the Bubble database](https://manual.bubble.io/help-guides/data/the-database#technical-information-about-the-bubble-database) As you map out your database, you can still think of Bubble as a traditional relational database and plan your data types and relationships accordingly. The data types make up the overarching types of data that you want to store in your app. Let's look at some examples to illustrate: **Social media app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/social-network-apps) ) * Users * Posts * Interests **Project management app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps) ) * Users * Projects * Tasks **eCommerce app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps) ) * Users * Products These are of course not exhaustive lists, but serve as examples to show _what_ a data type is. Think about the vision you have for your app, and try to plan out what kind of data you need to store to make it a helpful tool. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#the-fields) The fields The _fields_ are the data that you store in each data type. Fields can consist of different types of data, such as text, numbers, files, images and dates. Let's repeat the examples from above and add some fields to those data types: **Social media app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/social-network-apps) ) * Users * Name (text) * Date of birth (date) * Profile pic (image) * Posts * Header * Content * Interests * Name **Project management app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps) ) * Users * Name (text) * Profile pic (image) * Projects * Project name (text) * Project description (text) * Tasks * Task name (text) * Task description (text) * Deadline (date) **eCommerce app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps) ) * Users * Name (text) * Address (address) * Products * Header (text) * Description (text) * Image (image) * Price (number) * Shopping cart ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#relationships) Relationships Bubble's database is what's called a _relational database._ Relational simply means that different kinds of data can be _connected_ somehow. For example, in a social media app, a post is _connected_ to a user – that is, it "belongs" to the user that posted it. This method is used in a range of different ways to structure how different types of data are related to each other. Relationships are just another field that's added to the data type. In the social media example, we could add a field to the _Post_ data type, and that field is of type _User_. We can call that field whatever we want, such as _Owner_. A relationship can contain _one_ thing (i.e. a Post is connected to one owner), or a _list of things_ (i.e. a Shopping cart contains a list of Products). Let's again go over the earlier examples and see where it makes sense to connect data. We've marked the relationship fields in green. **Social media app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/social-network-apps) ) * Users * Name (text) * Date of birth (date) * Profile pic (image) * Interests (list of Interests) * Posts * Header * Content * Owner (User) * Interests * Name **Project management app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps) ) * Users * Name (text) * Profile pic (image) * Projects * Project name (text) * Project description (text) * Owner (User) * Tasks (list of Tasks) * Tasks * Task name (text) * Task description (text) * Deadline (date) * Owner (User) * Project (Project) **eCommerce app** (see our detailed guide [here](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps) ) * Users * Name (text) * Address (address) * Products * Header (text) * Description (text) * Image (image) * Price (number) * Shopping cart * Owner (User) * Products (list of Products) Don't worry about the technical side of this just yet – we'll cover that in detail in our [article series about the database](https://manual.bubble.io/help-guides/data/the-database) . Don't see this is a blueprint for setting up your app either – these are just simplified examples to get you into the right mindset: * **Data types** are the overarching types of data in your app, such as users, tasks, products and blog posts * **Fields** contain the actual data stored in these types, such as name, phone number, description and image * Data types can be **connected through relationships**, such as a shopping cart to an owner. These are just another field saved on the data type. Keep in mind we are still in the planning stage. Planning out what kind of data you need your app to store will help you get a better understanding of how you can fulfil the vision that made you want to make an app in the first place. Remember what we said in the first part of this section: most apps consist of a database at the bottom and a user interface on top of it. Now that we've covered the data, let's move on to the [Design and UX](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux) of your app. Last updated 22 days ago Was this helpful? * [Visualizing your data](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#visualizing-your-data) * [The data types](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#the-data-types) * [The fields](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#the-fields) * [Relationships](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure#relationships) Was this helpful? --- # Building your first app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-your-first-app.md) . Starting your journey in app development can feel like learning a new language, especially with the intricate jargon and technical terminologies used in traditional programming. Bubble uses intuitive and self-explanatory terminology like _things_, _workflows_, and _conditions_, to remove the barriers of complex coding languages, allowing you to focus on bringing your ideas to life. In this article series we'll explore the strategy for building your first app, and cover the basic Bubble concepts to get you up to speed quickly. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#what-does-it-mean-to-build-an-app) What does it mean to build an app? ---------------------------------------------------------------------------------------------------------------------------------------------------------- If you are new to app development, it may not be entirely clear what exactly it entails to build an app. That's not strange at all – after all, in traditional programming, an app is built by a _team_ of people where each member specializes in one key discipline such as design, coding and database management. Bubble, on the other hand, is built to make you able to do that all on your own. That doesn't mean that you _can't_ work with a team – you most certainly can – but it means that our tools are designed so that you don't have to. Bubble provides the flexibility and resources for both solo developers and teams to bring their app visions to life. Most apps are about collecting information, and then manipulating and presenting it in a way that's solves problems for its users. While apps can seem extremely different on the outside, they are mostly all the same thing: a useful design on top of a database. * A **social network** collects data about users (name, profile pic, age, interests, posts) and then loads that from the database to show it to other users. A _like_ on Facebook or X may _feel_ social, but it's all simply data that's presented in a social way. * A **CRM** collects data about clients, vendors and contacts, and then lets its users pull that data up whenever needed. Maybe it also crunches some data into statistics. * A **food ordering app** collects data about restaurants, menu items, drivers, customers and orders and uses that data to automate the ordering process. You get the point – while these are all very different categories, they are in essence doing the same thing: at the bottom is a database that users fill up with data, and on top of that is a design that makes the data useful. Many apps simply take real-life things we were already doing, like talking about our interests and ordering food, and automates them. So, to build an app, you need to: * Set up your **database** to store information * Design a **user interface** that intuitively directs users to add, modify, delete, view, and analyze data effectively * Link your design to **workflows**, ensuring that the app responds to user interaction Most applications are built in an incremental way: they are designed to solve a simple problem (like remembering a list of clients), and then its developer progressively new helpful features are added. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#core-terminology) Core terminology ----------------------------------------------------------------------------------------------------------------------- As you embark on your app-building journey, you'll come across some specific terms that will become the building blocks of your Bubble experience. Knowing the terms and phrases that are frequently used will also help you communicate with other Bubble users in the [forum](https://forum.bubble.io/) . For a more complete list of Bubble terminonology, you can also check out our glossary. Article: [Glossary](https://manual.bubble.io/the-glossary) Let's demystify these terms to ensure you have a smooth start. In each of the expandable boxes below, we'll explore one facet of app building and go over the terminology used in each one. Design: how your app looks[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#design-how-your-app-looks) We'll start by exploring **elements**. This is any visual item or component you'll place on your Bubble page. Think buttons, texts, inputs, and so on. It's what makes up your app's interface your app's interface. Elements can have **styles** associated. This lets you set up design attributes (color, border, shadow, font, etc) in one place and apply it to multiple elements. Bubble comes with a lot of built-in elements, but you can also add new types of elements with [plugins](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#plugins-enhancing-bubbles-capabilites) . **Learn more:** * Article series: [Design](https://manual.bubble.io/help-guides/design) * Article: [Design and UX resources](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux) * Page: [Bubble plugins](https://bubble.io/plugins) Workflows: making your app do stuff[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#workflows-making-your-app-do-stuff) As you design, you'll be introducing interactions. Here's where **Workflow** comes into play. Imagine you want something to happen when a button is clicked - that's a workflow. It's a sequence of automated steps or actions initiated by an **event**. The event is the specific trigger for your workflow. A button being clicked, a dropdown being changed, or even a page loading can all be events that kickstart a workflow. Each step in a workflow is known as an **action**. Actions can make changes in the database, navigate to another page, hide/show something on the page and a wide range of other things. **Learn more:** * Article series: [Workflows](https://manual.bubble.io/help-guides/logic/workflows) Conditions: if this, then that[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#conditions-if-this-then-that) Often, you'll want actions to happen only under certain circumstances. Enter **conditions**. This is the "if this, then that" of Bubble. Conditions dictate when specific actions or visual changes should take place based on criteria you set. For example, clicking a button takes you to another page, but _only_ if the current user is logged in. Conditions can also be placed on elements to control their appearance. For example, a button is only visible if the current user is logged in. Conditions are built using **dynamic expressions**. Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. **Learn more:** * Article: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) * Article: [Conditions](https://manual.bubble.io/help-guides/logic/conditions) The database: managing data[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#the-database-managing-data) As you populate your app with data, you'll be dealing with **Things**. A 'Thing' is just an individual piece of data in Bubble. Think of it as an entry or record in the database, such as a specific user. Each Thing belongs to a **Data Type**, which is like its category or table. For instance, if you're building a blogging app, _Blog Post_ could be a data type. If you're building a task management app, both _Task_ and _Project_ can be data types. Within these data types, there are **Fields**, which are attributes or properties. Using the Blog Post example, _Title_ and _Content_ could be fields. To protect your data, you use **privacy rules** to define who can access or modify what data. It's your one-stop control center for data protection. **Learn more:** * Article series: [The database](https://manual.bubble.io/help-guides/data/the-database) * Article: [Protecting data with privacy rules](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules) Previewing: testing your app before users get access[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#previewing-testing-your-app-before-users-get-access) Bubble gives you two distinct environments: Test and Live **Test environment**: This is your sandbox, a safe space where you can experiment, iterate, and make changes without affecting your actual users. Any data you use or create here won't touch the live environment. It's an ideal place for debugging and trying new features. **Live environment**: This is the real deal. The data here is what your actual users will interact with. Once you're satisfied with the changes in your test environment, you can **deploy** them to the live environment, ensuring that your users always experience a polished and tested version of your app. Each environment has its own separate database. This distinction ensures that your test experiments won't accidentally overwrite or corrupt the real user data you've gathered. If you need more advanced branching capabilities to work on features in isolation, you can also use our version control feature. **Learn more:** * Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Reusable elements: avoid repeating work[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#reusable-elements-avoid-repeating-work) As you build, you might create a component that you want to use repeatedly. That's a **Reusable Element**. It could be a navigation bar, footer, or any component you don't want to rebuild from scratch every time. **Learn more:** * Article: [Reusable elements](https://manual.bubble.io/help-guides/design/elements/reusable-elements) Plugins: enhancing Bubble's capabilities[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#plugins-enhancing-bubbles-capabilities) Now, there will be instances when you want to enhance Bubble's capabilities. That's where **Plugins** come in. They're like add-ons, enhancing functionality or allowing integrations. There is a collection of Bubble-built plugins, and a plugin store with thousands of user-created plugins. * Article: [Plugins](https://manual.bubble.io/help-guides/integrations/using-plugins) * Page: [Bubble plugins](https://bubble.io/plugins) API: connecting your app to other apps[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#api-connecting-your-app-to-other-apps) You'll likely come across the term **API**, an acronym for Application Programming Interface. Think of it as a language that allows your app to communicate and exchange information with other applications. This capability unlocks a treasure trove of possibilities: from integrating real-time weather updates, baseball stats, and demographic information, to scheduling events in a user's Google Calendar or posting updates on Twitter. Bubble comes with three different API tools: * The **Bubble API** comes with two tools for handling _inbound_ API calls: * The **Data API** lets you invite other apps to read and write in your app's database * The **Workflow API** lets you invite other apps to run workflows in your app * The **API Connector** is a plugin that lets you connect to external apps and services to make _outbound_ calls **Learn more:** * Article series: [API](https://manual.bubble.io/help-guides/integrations/api) * Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) * Article series: [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) * Article: [Bubble API terminology](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology) That's our whirlwind introduction to Bubble's core terminology! If it feels like a lot to take in at once, don't worry: as you start building, these terms will become second nature. They are consistently used around the editor to familiarize you with them as you go through your learning journey. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#planning-your-first-app) Planning your first app ------------------------------------------------------------------------------------------------------------------------------------- Many users who try out Bubble for the first time already have an idea of what they want to build. If you have never built an app before, the process of planning it out might seem daunting, but Bubble's intuitive design and workflow mechanisms are designed to guide beginners through the creation process seamlessly. Starting with a clear vision is essential. Break down your idea into core functionalities and the interactions you expect users to have with your app. Sketching out a basic wireframe on paper or using a digital tool can help you visualize the layout and user journey. Even if it's just rough boxes and arrows, it'll give you a roadmap to follow. Remember, the key to a successful app isn't just in its functionality, but also in its user experience. Consider the end-user at every stage of development. In the next section, we'll have a look at how you can go about deciding what [features to include in your app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features) . [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#other-ways-to-learn) Other ways to learn ----------------------------------------------------------------------------------------------------------------------------- Video lessons[](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#video-lessons) The playlist below gives an introduction to how Bubble works and how to build your first app: * Playlist: [Build your first Bubble app](https://www.youtube.com/watch?v=SHbY8eoe8Gw&list=PLoNVJrdvQQYlT3e3qur1LDgP8Rcs9msAm&pp=iAQB) Last updated 22 days ago Was this helpful? * [What does it mean to build an app?](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#what-does-it-mean-to-build-an-app) * [Core terminology](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#core-terminology) * [Planning your first app](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#planning-your-first-app) * [Other ways to learn](https://manual.bubble.io/help-guides/getting-started/building-your-first-app#other-ways-to-learn) Was this helpful? --- # Design and UX | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux.md) . Unless you come from a design background, it can be difficult to know where to start. Luckily, there is an abundance of design resources both within the Bubble community and on the web in general. Let's first quickly cover what exactly we _mean_ by design. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#what-is-app-design) What is app design? ------------------------------------------------------------------------------------------------------------------------------------------ The short and easy answer is of course: design is what your app looks like. Let's break that down into some more detail. The design process of an app can be categorized into two main disciplines: ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#ui-and-ux) UI and UX The **user interface** (often called UI) is the overall look of an app, including page layout, colors, typography, icons, images and other elements. Designing a user interface is about making the app look visually pleasing and aligned with the brand identity. **User experience** design focuses on how the user perceives the app. Is it easy to navigate and use? Is it logical in its structure? Does it solve problems efficiently? UX design is rooted in understanding and optimizing the user's journey, ensuring that the interface is intuitive, efficient, and user-friendly. So from this, we can draw up a few points that you can focus on in your design process: * An app should look good and have a consistent design to represent your brand * It should be easy to understand, navigate and use Design is of course a wide and professional discipline. If you don't come from a design background, we recommend studying the work of great designers to get ideas and inspiration for your own work. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#finding-inspiration) Finding inspiration Creating software that is easy to use and useful is both an art and a science. Have you given any thought as to why some apps feel like a natural extension of your brain, while others are frustratingly clunky? Great software feels intuitive, anticipates user needs, and delivers a delightful experience that keeps users coming back. Behind every seamless app or platform is a meticulous combination of design thinking, understanding of user behavior, and technical prowess. Drawing inspiration from these standout pieces of software can guide your own app-building journey. Study them, not just as a user, but as a creator. Dive deep into their user interface (UI), their user experience (UX), and the problems they solve. Ask yourself, why does a particular feature resonate with you? Many app ideas will belong to one or more software categories. For example, if you are writing software to handle internal projects, inventory or HR in your company you can find a lot of inspiration in already existing software doing similar things. Sometimes, great inspiration passes us by because we don't really reflect on _what_ it is that makes it good. You will likely find things in these apps that you really like, and other things that you think could be improved – make it a habit to keep an eye out for clever solutions and good user experiences and ask yourself _why_ it's good. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#design-resources) Design resources ------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#bubble-resources) Bubble resources Bubble has a very active and helpful community that offers plenty of resources to get you started on your app's design. #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#templates) Templates We have a large and growing catalogue of templates in our template store. Templates are not only about design, but often offer fully functioning apps that you can use as a springboard for your own project. Some templates focus on multi-purpose apps, while others serve specific niches, such as eCommerce, task management and landing pages. Page: [Template store](https://bubble.io/templates) #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#component-library) Component library The Component Library is a collection of pre-built User Interface (UI) components that can be dragged and dropped onto your page to help you build beautiful interfaces faster. These UI components are fully responsive and are made up of containers, visual elements, and form inputs that can be individually customized once added to your page. Page: [The Component Library](https://manual.bubble.io/help-guides/design/the-component-library) Video: [Introducing the Component Library](https://www.youtube.com/watch?v=5dgmchu7S6o) #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#showcase) Showcase Bubble hosts millions of apps, and you can easily find inspiration in our [Showcase](https://bubble.io/showcase) . This is where we publish customer success stories. Page: [Bubble showcase](https://bubble.io/showcase) ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#third-party-resources) Third-party resources From pre-designed templates to user interface guidelines, and from color palette generators to typography recommendations, there are tools and platforms dedicated to helping. **1\. Design templates:** Websites like [Dribbble](https://dribbble.com/) , [Envato elements](https://elements.envato.com/) or [Behance](https://www.behance.net/) showcase design works from professionals worldwide. These can serve as inspiration or even a starting point for your app’s interface. Some platforms also offer downloadable UI kits to give you a jumpstart. **2\. Color tools:** Websites like [Colormind](http://colormind.io/) , [Adobe Color](https://color.adobe.com/create/color-wheel) , or [Coolors](https://coolors.co/) can help you generate color schemes that look harmonious and pleasing to the eye. Understand the psychology of colors and pick a palette that aligns with your app's mood and purpose. **3\. Typography:** Tools like [Google Fonts](https://fonts.google.com/) or [FontPair](https://www.fontpair.co/) can help you pick the perfect font combinations for readability and aesthetics. Remember, typography plays a crucial role in user experience, so ensure your text is legible across devices. **4\. Icon libraries:** Need more icons than the built-in ones? Websites like [FontAwesome](https://fontawesome.com/) , [Iconfinder](https://www.iconfinder.com/) offer vast libraries of icons that you can use to enhance your app's design. We also have plugins in the plugin store that offer more icons. **5\. Mockup and prototyping tools:** Platforms such as [Figma](https://www.figma.com/) or [Sketch](https://www.sketch.com/) allow you to create detailed mockups and interactive prototypes of your app. This helps visualize the end product. Bubble has a [tool for importing designs from Figma](https://manual.bubble.io/help-guides/design/importing-from-figma) . **6\. Design guidelines:** For beginners, sticking to guidelines can be helpful. [Material Design](https://m3.material.io/) (by Google) and [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) (by Apple) provide principles and recommendations to create a consistent and intuitive user experience. **7\. Feedback platforms:** Websites like [UserTesting](https://www.usertesting.com/) or [Maze](https://maze.co/) can help you gather feedback on your designs from real users. Feedback at this stage can save countless hours of rework after development. Lastly, remember that design isn’t just about aesthetics. Good design solves problems. It's about creating an intuitive, seamless experience for your users. As you dive deeper into design resources, keep the user's needs and behaviors at the forefront of your decisions. With the right tools and a user-centric mindset, you can craft a design that not only looks good but also feels right to your target audience. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-design-process) The design process ----------------------------------------------------------------------------------------------------------------------------------------- When your ideas are in place and after you've found the inspiration and resources needed to bring it to life, it's time to think about how to transfer that design to the screen. There are various methods to do this, and no right or wrong way. Decide for yourself what you're most comfortable with, and focus on getting to the finish line. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-tools) The tools #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#pen-and-paper-post-its) Pen and paper/post-its Again, there is nothing wrong with using pen and paper during the first part of designing your app. Many users enjoy the freedom of not having to learn any new tools and the speed at which you can draw something directly on the page – and the feeling of throwing away stuff you no longer need. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FbMAlkBA7kpNgsCpTzLsi%252Fux-mobile-application-wireframe-sketch-prototype-2022-12-29-00-49-35-utc-2.jpg%3Falt%3Dmedia%26token%3D20b96599-d5e8-4068-80b6-23a140ceb25e&width=768&dpr=3&quality=100&sign=21b33c0c&sv=2) Planning your app's design doesn't have to start on the screen – a sheet of paper, post-it notes and whiteboards are a great place to start sketching quickly. Pen and paper is great for visualizing different parts of the user journey too. For example, when a user signs up, what fields do you need? How should that form look? How many fields are too many? #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#mockups-prototypes) Mockups/prototypes Another method is to use mockup and prototyping tools (as suggested in point 5 in the above list). These are essentially visual tools that let you draw your ideas on the screen more in the way that you intend for them to look in the final app. Using a mockup tool like Figma can be highly useful as it offers real-time collaboration, cloud storage and the design can be imported directly into Bubble. Your choice between using a prototyping tool or diving straight into Bubble largely hinges on your personal preferences and familiarity with such platforms. If you're wary of adding another layer of software mastery to your plate, you might choose to dive directly into Bubble's design environment instead. #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#designing-in-bubble) Designing in Bubble Bubble comes with a visual WYSIWYG editor that's designed to help you place elements directly on a canvas and see the results immediately, similar to popular prototyping tools. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FyojQBL32U84cYC52PydJ%252Fsignup.jpg%3Falt%3Dmedia%26token%3D65e913c8-4bea-4997-9078-8fa79f6e52f0&width=768&dpr=3&quality=100&sign=14f02c6f&sv=2) Bubble's WYSIWYG editor makes it easy to see results immediately. With the instant [app preview](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app) , you can see exactly what the app will look like to your users. If you choose this approach when you plan your design, we strongly recommend reading through the [Design](https://manual.bubble.io/help-guides/design) section of the manual to learn how Bubble's tools work. From there, we also link to video lessons that can get you quickly into the mindset of designing in Bubble. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-ui-kit) The UI kit To keep your design process efficient, it's often a good idea to think about a UI kit. This is essentially a collection of elements that have consistent style attributes, which can include buttons, icons, form inputs, typography, and other elements. If you want to set up and maintain a consistent design, we recommend going through this process first. Not only does it make it easier to be consistent in your design choices, but it can really speed up the design process overall, since you don't need to spend time on each individual element. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F4sKwUkSnC9P4sXK0JlUI%252Fbubble-ui-kit.png%3Falt%3Dmedia%26token%3Da9426423-9264-48b8-b9d1-0cbe0fb8520c&width=768&dpr=3&quality=100&sign=fde2b431&sv=2) Setting up a UI kit can be as simple as placing and styling a few elements on a page, but it can make your design process a lot more efficient and consistent. The idea is to think about the different elements that you will use in your app, and then set up their design in one place. This can be a page, or a reusable element for example. Whenever you need a specific button, you simply copy/paste it from that page to use it elsewhere. You decide how detailed and advanced you want to be in your UI kit. Below we suggest a few different levels of complexity – if this is your first app, you may choose to only focus on the basics for example. Think about all the design attributes that should consistently apply to an element, such as its color, border, shadow, width, height and font/font size. #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#start-with-the-basics) Start with the basics Focus on the fundamental components first: * **Buttons**: These come in various sizes and states. Design for primary, secondary, and tertiary actions. A "Cancel" button is often less prominent than an "OK" button for example. * **Input Fields**: Think about text fields, dropdowns, checkboxes, radio buttons, and sliders. * **Navigation**: Design navigation bars, sidebars, and tab bars. * **Headers and body text:** text elements that are correctly formatted for headers and paragraphs #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#expand-to-complex-components) Expand to complex components Once you have the basic components, it's time to tackle more complex ones: * **Cards**: Commonly used to display snippets of information in an organized manner (such as the products in an eCommerce store) * **Modals**: Pop-ups that grab the user's attention (alerts, confirmations, etc) * **Tables**: Vital for displaying data. Consider pagination, sorting, and filters. #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#interactivity-and-states) Interactivity and states Users will interact with your interface, so account for various states: * **Hover**: How does an element look when a user hovers over it? * **Active**: What happens when an element is clicked? * **Disabled**: Ensure users can recognize non-clickable or non-interactable components (i.e. a disabled button or input form) #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#save-styles-and-style-variables) Save styles and style variables When you are happy with your UI kit, you can save the styling on the different elements as _styles_. This saves their styling attributes in a style that you can name, and then apply to other elements of the same time. We recommend that you set up styles _after_ you have finished your UI kit, so that you can review your overall design first. Font variables and color variables can also help you keep track of your app's design. #### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#add-more-elements-as-needed) Add more elements as needed Whenever you need a new type of element, make a habit of adding it to your UI kit, so that you keep an updated "catalogue" of elements. If you create your UI kit on a page, remember to remove that page before you deploy your app to live users (or they page will be accessible online). If you want to keep the UI kit without it being available to your end-users, you can place it inside of a reusable element instead. Article: [Reusable elements](https://manual.bubble.io/help-guides/design/elements/reusable-elements) ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#building-the-page) Building the page When you are happy with your UI kit, you can start building your actual pages. Because you have invested some time to set up your initial colors, fonts and elements, you'll have a better feeling of how the app's overall look should be. In the next section of the guide, we'll look into how you [Create and manage apps in Bubbl](https://manual.bubble.io/help-guides/getting-started/creating-and-managing-projects) e, before moving onto covering the [Bubble editor](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor) , its tabs, sections and tools and settings. If you want to read more about how to use Bubble's design tools, you can continue directly to the [Design article series](https://manual.bubble.io/help-guides/design) . Last updated 22 days ago Was this helpful? * [What is app design?](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#what-is-app-design) * [UI and UX](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#ui-and-ux) * [Finding inspiration](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#finding-inspiration) * [Design resources](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#design-resources) * [Bubble resources](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#bubble-resources) * [Third-party resources](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#third-party-resources) * [The design process](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-design-process) * [The tools](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-tools) * [The UI kit](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#the-ui-kit) * [Building the page](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux#building-the-page) Was this helpful? --- # Checkout page | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page.md) . In this article, we'll look into what is often the final step before the user actually pays for one or more products – the checkout page. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#defining-the-checkout-page) Defining the checkout page -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The checkout page often gives your end-users a final look at their purchase before they commit to buying and go ahead with the payment transaction. Its purpose is to provide all the details needed for a user to make an informed purchase decision, and with the added benefit of building trust and confidence in your app, if set up right. Below is an example of what a checkout page may look like. As an internet user, you will likely have seen many of these. While they can differ in design, many of them contain the basic elements needed for the purposes described above, and for the business to stay compliant with relevant requirements, such as the GDPR and CCPA, as well as commerce and tax laws. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FiDHP3XEuhggNGDs2wtEz%252Fbubble-checkout-page-example%25402x.png%3Falt%3Dmedia%26token%3D69370fce-e6ff-43ec-91bd-847a992518f3&width=768&dpr=3&quality=100&sign=13ce9420&sv=2) A checkout page should give customers a well-organized final look at what exactly they are purchasing, what they will be charged and why, and the method by which they will be paying. In some cases, other details are also relevant, such as the delivery address for physical products. Your user interface and user experience both play a very large part in generating revenue, ensuring customer satisfaction, and compliance with regulations. In this section, we’ll go over some of the most important things to keep in mind when you design your checkout experience. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#planning-a-checkout-page) Planning a checkout page ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#transparency) Transparency Whenever any transaction is involved, transparency is important. What this means is that you should set up your app to clearly show what exactly the customers are purchasing and why they are paying a certain amount. From a regulatory perspective, including specific details about any transaction may also be required. This is usually done by listing all the details involved in a transaction, from the user’s perspective. The different records in a purchase transaction are often divided into three categories: Record Description Visible to customers Line items The actual items being purchased, such as a beanie and a book Yes Additional fees Extra costs, such as shipping Yes Cost of sales Payment gateway transaction fee, and operational costs No A good practice is to list the line items and any additional fees separately, while incorporating the cost of sales into the product cost. For instance, it's relevant to show the price of each item in a cart along with the combined shipping cost, as this provides transparency to the customer. However, fees associated with the payment gateway transaction, are typically not relevant to the customer and are often absorbed into the product cost. Therefore, these costs are usually factored into the overall pricing of the product rather than being itemized separately. Displaying your business details, including its legal name, address, phone number, email address, and government organizational ID, is not only a recommended practice but also a requirement in many regions. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#ease-of-use) Ease of use Making a purchase process easy to understand and quick can also help you generate more sales and satisfied customers. When customers find it easy to navigate through the checkout process, they are more likely to complete their purchases and return for future transactions. * **Reducing steps:** reducing the number of steps the customer has to take in order to complete the purchase can increase the conversion rate. Some eCommerce sites, like Amazon.com, have even implemented a one-time checkout process that lets returning customers buy products with a single click, since Amazon already has the information needed to complete it. * **Responsive design:** making your app work well on mobile devices, as well as larger screens, increases the number of potential customers. Using Bubble’s responsive engine, you can make the same page work well on all screen sizes and devices. Keep in mind the differences between different devices: * Font sizes that appear suitable on a laptop screen may appear too small on mobile devices. * Buttons and links that are to small, or placed too closely together, can be challenging for mobile users to click. * Ensure that elements do not overlap in certain scenarios. For instance, an element placed within a floating group that appears well-positioned on a laptop screen may overlap crucial elements on mobile screens. * **Editable cart:** if you are implementing a shopping cart feature that allows the users to add more than one item, they may find it useful to be able to make changes to the cart, such as deleting an item. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#cross-selling-and-upselling) Cross-selling and upselling Cross-selling and upselling are both sales techniques used to increase the value of a purchase, and can be of value to the user as well. * **Cross-selling:** Cross-selling means recommending related or complementary products to the one the customer is already considering or has already purchased. The aim is to encourage customers to add additional items to their cart that enhance or complement their original purchase. For example, suggesting batteries when a customer buys a flashlight or offering a phone case when purchasing a new smartphone. As these examples show, cross-selling can also be useful to customers if you display the right products or services. * **Upselling:** Upselling involves persuading the customer to purchase a higher-end or more expensive version of the product/service they are interested in or have already chosen. For example, encouraging customers to upgrade to a larger size, premium model, or extended warranty when buying a product. ### [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#post-purchase-information) Post-purchase information * **Purchase confirmation:** it’s always a good idea to let the user know the status of the transaction. If it is successful, it’s common to redirect the user to a thank you page or section. Thank you pages are also sometimes used to track sales analytically in platforms like Google Analytics. * **Email confirmation:** many users will also be looking for an email that confirms the purchase and its details. You can use our dedicated Sendgrid plugin to send customized emails. Emails that are used for this purpose are generally known as transactional emails. * **Tracking links:** if you are selling physical products, users may find it useful to be able to track the shipment. Many courier companies have an API that allows you to set up a shipment and get a tracking number in return. You can use the API Connector to set this up. * * * Keep in mind that all of the above suggestions are just that – suggestions. Your final checkout page is yours to design, and this is meant just to inspire. However, keep in mind that keeping your users informed, the process transparent and fast, and the design working on all relevant devices are all good basic tips for setting up. Also, make sure that your checkout page is compliant with any rules and regions that pertain to your sector, type of products/services and geographical region. [](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#transactional-details) Transactional details ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- It's important to emphasize that when we discuss transactional details, we are not referring to cardholder information, such as the card number, expiration date, and security code. These particulars are typically managed by the payment gateway and should not be stored in your app's database. Whenever a customer pays for something, like the items in a shopping cart, a transaction happens. If you're using an online payment gateway such as Stripe, this is an automated process that arranges for money to be moved from the customers bank account to your company's account. Whenever such a transaction takes place, the payment gateway stores details about it, such as the date, time, customer info and amount. This record in their database is given a unique ID that helps you identify it later if needed. For example, a customer might ask for a refund, at which point you'll need to refer to the original payment. It's highly recommended to store some details from the transaction in your Bubble database when a transaction is complete. Structurally, there are some questions worth asking: * Will purchases always be for **one item**, or for a **collection of items** (shopping cart) * This could affect where it makes the most sense to store the transactional details * If your app has a shopping cart feature, it makes sense to save the transaction ID on a data type that represents the full purchase (as opposed to each individual item), such as the data type that represents the shopping cart * Which **details** do I want to store? * Storing the transaction ID normally allows you to get other details such as date, time, and amount from the payment gateway * You can still opt to save other details. For example, you might need them to create and maintain statistical data. The transaction ID is normally returned right after the transaction is finalized. The official Stripe plugin automates this process by giving you access to the ID in the same workflow that initiated the payment. We cover this in the next article in this series: Article: [One-time payments](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/one-time-payments) Last updated 22 days ago Was this helpful? * [Defining the checkout page](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#defining-the-checkout-page) * [Planning a checkout page](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#planning-a-checkout-page) * [Transparency](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#transparency) * [Ease of use](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#ease-of-use) * [Cross-selling and upselling](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#cross-selling-and-upselling) * [Post-purchase information](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#post-purchase-information) * [Transactional details](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page#transactional-details) Was this helpful? --- # Previewing a web app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app.md) . This section describes previewing **web apps**. If you're looking for documentation on previewing **native mobile apps**, see the article below: Article: [Previewing a mobile app](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app) Bubble makes it easy to preview your web app while you build. Previewing lets you test functionality, check design changes, and make sure everything works the way you expect—before deploying your app to live users. This article explains the different ways you can preview your web app from the Bubble editor. [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#preview-modes) Preview modes ------------------------------------------------------------------------------------------------------------------ You can preview your app using the **Preview** button in the top-right corner of the editor. This opens a new browser tab showing your app’s development version. By default, your app loads in **normal preview mode**, but there are also additional safe preview modes available, which can help when debugging or isolating potential issues. ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-1.-preview) 1\. **Preview** This is the standard way to test your app. It loads the full development version, including: * All custom HTML * All installed plugins * All workflows and elements Use this mode for general testing. ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-2.-disable-html) 2\. **Disable HTML** This mode disables any custom HTML elements you've added through the HTML element or the page header. Use this if you're experiencing rendering issues or suspect your custom code might be affecting the app. ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-3.disable-plugins) 3.**Disable plugins** This mode disables all plugins, allowing you to test your app without third-party code. Use this if you think a plugin is causing a problem in your app. ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-4.-safe-preview-disable-html-and-plugins) 4\. **Safe preview – Disable HTML and plugins** This mode disables both plugins and custom HTML. Use this if you're encountering persistent issues and want to isolate whether the problem is being caused by third-party code. [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#how-to-access-safe-preview-modes) How to access safe preview modes -------------------------------------------------------------------------------------------------------------------------------------------------------- 1. Click the **Preview** button dropdown (downward arrow next to Preview). 2. Choose the mode you want to use: * Preview * Disable custom HTML * Disable plugins * Disable HTML & plugins Each mode opens a new tab with the corresponding version of your app. [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#note-on-preview-urls) Note on preview URLs -------------------------------------------------------------------------------------------------------------------------------- All preview modes load your app in the development version. The URL will include `version-test`, like so: This version is separate from your live app and only reflects the latest changes in your editor. Last updated 22 days ago Was this helpful? * [Preview modes](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#preview-modes) * [1\. Preview](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-1.-preview) * [2\. Disable HTML](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-2.-disable-html) * [3.Disable plugins](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-3.disable-plugins) * [4\. Safe preview – Disable HTML and plugins](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#id-4.-safe-preview-disable-html-and-plugins) * [How to access safe preview modes](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#how-to-access-safe-preview-modes) * [Note on preview URLs](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app#note-on-preview-urls) Was this helpful? Copy https://yourapp.bubbleapps.io/version-test --- # Previewing a mobile app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app.md) . This section describes previewing **mobile apps**. If you're looking for documentation on previewing **web apps**, see the article below: Article: [Previewing a web app](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app) Previewing your app functions similarly to the Bubble web app editor, allowing you to instantly see and test changes as you make them. However, keep in mind that some components of the native mobile app editor rely on built-in features of mobile devices, which can vary between iOS and Android. As a result, not all elements may display accurately in the web preview. There are two ways to preview your app: [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#web-preview) Web preview ----------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#differences-from-web-app-preview) Differences from web app preview Web preview works mostly like the preview in the Bubble web app editor, with a few key differences: * There's no update banner in the preview when changes have been made to the app * There's an extended bar for managing how the app will look across different devices (see below) ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#current-web-preview-limitations) Current web preview limitations There are currently a few limitations in web previews: * Native maps element will not render * Native datetime picker will not render * Push notifications cannot be sent to web preview * Camera workflows will not work properly * Permissions request workflows may not work properly * Multi-line inputs in floating groups will not expand to fit height ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#device-emulator-bar) Device emulator bar The bar at the top of the screen lets you emulate how the app will look on different devices, screen sizes and with a specific zoom level. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FQeMNNkZYbOZppyVFNX5S%252Fdevice-emulator-bubble-native-app.png%3Falt%3Dmedia%26token%3Daa7edd26-5f51-444d-8bd6-adf0b6dad25e&width=768&dpr=3&quality=100&sign=33bf1d08&sv=2) 1. **Show device frame**: This lets you show or hide the frame of the selected device (i.e. actually showing the frame, buttons, notch/camera/sensors of the device selected in setting 2. 2. **Select device**: Provides a list of widely used devices to emulate how the app will look and behave on that specific device. 3. **Screen size (px):** The actual screen size of the selected device. Note that this is a locked field and updates according to the device selected in setting 2. 4. **Zoom level**: Allows you to zoom in on the emulator to a specific percentage or to fit the screen height. Keep in mind that this zoom affects the entire emulated device, not just the screen. We recommend testing your app across all devices to ensure it looks great and functions properly everywhere. [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#bubblego) BubbleGo ----------------------------------------------------------------------------------------------------------- BubbleGo is a native mobile app that allows you to load and interact with your mobile app directly on your device. This essentially mimics the experience of having the app installed on your phone, without the need to publish it in the app store. Use BubbleGo to get a feel for how your users will actually use your app, and to test out more advanced interactions/flows/and system connections. ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#accessing-bubblego-for-ios) Accessing BubbleGo for iOS In BubbleGo for iOS, you can refresh your app by shaking your iPhone. 1. Download the TestFlight app from the Apple App store. 2. Click on [this link](https://testflight.apple.com/join/uXuOrE3v) 3. Follow the link to download BubbleGo onto the TestFlight app. 4. Log into BubbleGo using your Bubble account credentials. 5. Select the mobile app you would like to test and Go! ### [](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#accessing-bubblego-for-android) Accessing BubbleGo for Android * Download the app from the Play Store: * [Mobile link](https://play.google.com/store/apps/details?id=com.bubble.BubbleGo1) * [Computer link](https://play.google.com/apps/testing/com.bubble.BubbleGo1) * Log into BubbleGo using your Bubble account credentials. * Select the mobile app you would like to test and Go! Last updated 22 days ago Was this helpful? * [Web preview](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#web-preview) * [Differences from web app preview](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#differences-from-web-app-preview) * [Current web preview limitations](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#current-web-preview-limitations) * [Device emulator bar](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#device-emulator-bar) * [BubbleGo](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#bubblego) * [Accessing BubbleGo for iOS](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#accessing-bubblego-for-ios) * [Accessing BubbleGo for Android](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app#accessing-bubblego-for-android) Was this helpful? --- # Maintenance | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application.md) . In this guide, you will learn about the different concepts and features that let you maintain your application as it scales. This includes backups, bulk operations, collaboration, etc. [Restoring database backups](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups) [Bulk operations](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations) [API workflow scheduler](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler) [Commenting](https://manual.bubble.io/help-guides/maintaining-an-application/commenting) [Collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration) Last updated 2 years ago Was this helpful? Was this helpful? --- # About AI app generation | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation.md) . Bubble’s mission has always been to empower anyone to create, host, and launch their own apps. A core part of this vision is continuously lowering the barrier for new users, enabling them to bring their ideas to life with ease and confidence. With that vision comes a simple fact — an app is many things: a design that users can see and interact with, workflows that respond to the user’s actions, a database and server space to store data and files, all wrapped in a package that meets the security and performance standards that you as the developer decide is right for your user base. Currently in its beta phase, Bubble's AI app generator represents a significant leap forward in simplifying the journey from idea to app. It automates the initial app creation process, delivering a working MVP to the user in minutes. It acts as a designer and developer, taking an idea and doing the hard work of getting your idea from 0 to 1. The tool generates a foundational design and structure for your app, which you can then refine and customize using Bubble’s intuitive no-code tools. As part of the beta, your participation and feedback are crucial in refining this feature and making app development even more accessible to everyone. [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation#the-day-1-and-day-2-dilemma-in-ai-driven-app-development) The Day 1 and Day 2 dilemma in AI-driven app development ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Automatically generating apps with artificial intelligence introduces what we call the Day 1 and Day 2 dilemma: * **Day 1:** The initial creation of an app by AI. This is the exciting, automated process that showcases AI’s ability to generate functioning applications from scratch. * **Day 2:** The challenge of revising, maintaining, further developing, and deploying the app. Other AI app builders output code. They may bring you an exciting demo, but the continued development and revision of that app ultimately still requires an ability to code. Bubble's AI app generator solves the Day 2 challenge in two different ways, ensuring that the final app is aligned with what you intended: * First, Bubble's AI app generator gives you a high-level overview of the app it will build, allowing you to refine it through further prompting the AI for changes * Then, the final generated app integrates seamlessly into Bubble’s already existing visual no-code tools. This means you can manage, iterate, and refine your app entirely within the platform, maintaining full ownership and control of the product from day 1 to day 2 and beyond. You can see our presentation of the Day 1 and Day 2 dilemma in the presentation from BubbleCon 2024 [here](https://www.youtube.com/watch?v=a77Weewfizo) . Youtube: [Bubble AI presentation BubbleCon 2024](https://www.youtube.com/watch?v=a77Weewfizo) [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation#learn-more) Learn more ----------------------------------------------------------------------------------------------------------------------- To learn more about Bubble's AI app generator, check out the articles below: * [**Definitions and concepts:**](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#definitions-and-concepts) the words and phrases we use to describe Bubble's AI features. * [**Using Bubble's AI app generator:**](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator) how to write good prompts, do's and don'ts and the current limitations Last updated 22 days ago Was this helpful? * [The Day 1 and Day 2 dilemma in AI-driven app development](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation#the-day-1-and-day-2-dilemma-in-ai-driven-app-development) * [Learn more](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation#learn-more) Was this helpful? --- # Connect to AI models | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents.md) . [](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#introduction) Introduction ----------------------------------------------------------------------------------------------- This section introduces how to connect your Bubble app to AI agents such as ChatGPT and Claude using the API Connector. The articles explain how these systems receive and return data, how to structure requests correctly, and how to handle different types of responses, including streaming. The goal is to help you set up reliable, efficient AI integrations that work smoothly with your app's existing workflows. [](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#what-can-ai-providers-do-for-my-app) What can AI providers do for my app? ---------------------------------------------------------------------------------------------------------------------------------------------- Integrating AI providers into your Bubble app enables a wide range of functionality that would otherwise require complex logic or human input. These systems process language, generate content, make decisions, and analyze patterns in ways that are difficult to build manually. Depending on the use case, AI can enhance both the user experience and the efficiency of your workflows. Some common examples include: * **Conversational interfaces:** Build chatbots or virtual assistants that can respond to user input in natural language. * **Text generation:** Automate copywriting, summaries, replies, or content suggestions based on input from users or your database. * **Classification and tagging:** Automatically label or organize user-generated content such as reviews, messages, or support requests. * **Search and retrieval:** Use semantic search to find relevant documents or database records based on a user’s query. * **Decision support:** Provide intelligent suggestions or evaluations based on patterns in the input data. These features can be added without changing your database structure or logic—AI acts as a layer that interprets or generates information as needed, often with just a few API calls. [](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#integration-guides) Integration guides ----------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#chatgpt) ChatGPT This guide shows you in detail how you can connect to OpenAI's different ChatGPT models using the API Connector. We'll cover how to authenticate with OpenAI and set up your first calls. Article series: [Connecting to OpenAI using the API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai) #### [](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#streaming-api) Streaming API When connecting to external APIs, most responses follow a standard JSON format: your app sends a request, and the API returns all the data at once. Streaming APIs work differently. Instead of waiting for the full response, data is sent back in chunks as it becomes available. This is useful for situations where content is generated over time—like AI-generated text—allowing your app to start displaying results before the full response is complete. Article: [Using the streaming API feature in the API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api) Last updated 1 year ago Was this helpful? * [Introduction](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#introduction) * [What can AI providers do for my app?](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#what-can-ai-providers-do-for-my-app) * [Integration guides](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#integration-guides) * [ChatGPT](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents#chatgpt) Was this helpful? --- # Support Dept | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept.md) . [Support Dept](https://supportdept.io/) reduced WU consumption by 90% by optimizing a bulk data operation: checking for errors across thousands of records. [](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept#optimization-opportunity) Optimization opportunity ---------------------------------------------------------------------------------------------------------------------------------------------------------- When Support Dept originally built out this process, they used a recursive workflow to check for errors while uploading thousands of records. This workflow consumed up to 50,000 workload units for the various checks. It also took up to 30 minutes for larger uploads (1,000+ records). [](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept#optimizations) Optimizations: ------------------------------------------------------------------------------------------------------------------------------------- * **Use schedule API workflow on a list (SAWOL) for bulk data operations:** After Bubble announced performance improvements to SAWOL, they decided to use that instead. Not only did this change reduce workload by 90%, they also reduced the time this process took by 95% in some cases. Instead of taking minutes, many processes started taking seconds. Last updated 22 days ago Was this helpful? * [Optimization opportunity](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept#optimization-opportunity) * [Optimizations:](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept#optimizations) Was this helpful? --- # Integrations | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations.md) . Among Bubble's most powerful features is the ease with which you can connect to other applications and share data and commands. Not only can you set up connections between Bubble applications, but you can also connect to third-party apps via the **Bubble API** and to SQL databases via the **SQL Database Connector**. This article series dives into the different tools at your disposal and how to use them. API - Set up outgoing and incoming connections to third-party applications[](https://manual.bubble.io/help-guides/integrations#api-set-up-outgoing-and-incoming-connections-to-third-party-applications) An API (Application Programming Interface) connection is a way for different applications to communicate and exchange information with each other. In Bubble, an API connection allows you to extend your app's functionality by integrating with external services. By leveraging API connections, you can access and manipulate data, trigger actions, and access features from other platforms, greatly extending the feature set of your own app. Article series: [API](https://manual.bubble.io/help-guides/integrations/api) Reference category: [API](https://manual.bubble.io/core-resources/api) Plugins - Connect to other apps and databases in easy-to-use plugins[](https://manual.bubble.io/help-guides/integrations#plugins-connect-to-other-apps-and-databases-in-easy-to-use-plugins) Plugins are Bubble- or community-built extensions that you can install in your own application. Some of them offer added features internally in your app, and others let you set up connections with external apps without having to set it up manually. Article series: [Plugins](https://manual.bubble.io/help-guides/integrations/using-plugins) SQL Database Connector - read and change data in external SQL databases[](https://manual.bubble.io/help-guides/integrations#sql-database-connector-read-and-change-data-in-external-sql-databases) The SQL Database Connector Plugin in Bubble lets you connect your app with external SQL databases such as PostgreSQL, MySQL, and Microsoft SQL. The plugin allows you to run SQL queries directly from your Bubble app, giving you the flexibility to access, manipulate, and integrate data from external databases. Article: [The SQL Database Connector](https://manual.bubble.io/help-guides/integrations/sql-database-connector) Reference: [The SQL Database Connector](https://manual.bubble.io/core-resources/bubble-made-plugins/sql-database-connector) Bubble App Connector - Connect to other Bubble apps and share data and workflows[](https://manual.bubble.io/help-guides/integrations#bubble-app-connector-connect-to-other-bubble-apps-and-share-data-and-workflows) The Bubble App Connector plugin allows you to connect your Bubble app to other Bubble apps, enabling exchange of data and workflows. The plugin gives you an easy and visual way of accessing the data and workflow endpoints in a second Bubble app without having to set up API Connections manually. Article: [The Bubble App Connector](https://manual.bubble.io/help-guides/integrations/bubble-app-connector) Reference: [The Bubble App Connector](https://manual.bubble.io/core-resources/bubble-made-plugins/bubble-app-connector) Last updated 22 days ago Was this helpful? Was this helpful? --- # AI | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai.md) . [](https://manual.bubble.io/help-guides/ai#introduction) Introduction -------------------------------------------------------------------------- Bubble has always been at the forefront of making software development more accessible. What started as a no-code platform is now evolving into something even more powerful: AI-powered visual development. With AI, Bubble is transforming the way you design, build, and refine applications — making the development process faster, more intuitive, and more scalable than ever before. Bubble’s AI capabilities are divided into two key areas: * Bubble’s AI features, which integrate AI directly into the platform to enhance app creation, automation, and design. * Connecting your app to AI systems, such as ChatGPT and other external AI services, allowing you to build AI-powered applications that leverage machine learning and natural language processing. By investing in both of these areas, Bubble is ensuring that AI is not just an add-on but a core part of the visual development experience. [](https://manual.bubble.io/help-guides/ai#ai-and-visual-development) AI and visual development ---------------------------------------------------------------------------------------------------- Traditional software development requires writing and maintaining code, while visual development enables you to build applications through an interface-driven approach. Bubble pioneered no-code visual development, allowing you to create complex applications by dragging, dropping, and configuring elements — without needing to write a single line of code. With AI, visual development takes another leap forward. AI-driven tools can assist in structuring applications, generating content, optimizing workflows, and even predicting your needs before they arise. This shifts the development process from manually placing elements and defining logic to a more collaborative and intelligent experience, where AI helps guide, suggest, and automate many of the steps involved. AI visual development does not replace your control — it enhances it. AI acts as a co-pilot, enabling you to create faster, make better decisions, and spend less time on routine tasks while focusing more on innovation and business logic. [](https://manual.bubble.io/help-guides/ai#bubbles-ai-features) Bubble's AI features ----------------------------------------------------------------------------------------- Bubble is integrating AI directly into the platform, starting with two major AI-powered tools: ### [](https://manual.bubble.io/help-guides/ai#ai-app-builder) AI app builder The AI app builder is designed to generate entire applications based on your input. Instead of starting from a blank canvas, you can describe what you want, and AI will generate: * A functional app structure, including pages, elements, and workflows * A database schema, tailored to your app’s intended functionality * Pre-configured logic, such as navigation and common app behaviors This allows you to get started instantly, reducing the time it takes to go from idea to working prototype. The AI-generated app can then be modified, expanded, and refined — enabling full customization while eliminating the need to start from scratch. ### [](https://manual.bubble.io/help-guides/ai#ai-page-builder) AI page builder To help you quickly design individual pages, the AI page builder generates layouts based on your specifications. Instead of manually adding elements and adjusting placement, you can input a request, and Bubble’s AI will create a structured, visually optimized page. **This feature enables:** * Faster UI prototyping, with AI suggesting layouts and element arrangements * Consistency across pages, reducing the need for manual design tweaks * Smarter design decisions, based on best practices and Bubble’s design system [](https://manual.bubble.io/help-guides/ai#connecting-your-app-to-ai-systems) Connecting your app to AI systems -------------------------------------------------------------------------------------------------------------------- Beyond Bubble’s built-in AI tools, you can also integrate external AI services to enhance your applications with AI-powered functionality. ### [](https://manual.bubble.io/help-guides/ai#ai-chat-and-natural-language-processing) AI chat and natural language processing Bubble makes it easy to connect with services like ChatGPT and other AI models to provide features such as: * Chatbots and virtual assistants * AI-generated content * Sentiment analysis and text classification These integrations allow your app to leverage advanced AI without requiring deep technical expertise. By connecting to APIs like OpenAI’s ChatGPT, you can bring real-time conversational AI into your applications. ### [](https://manual.bubble.io/help-guides/ai#ai-powered-automation-and-decision-making) AI-powered automation and decision-making Beyond chat functionality, AI integrations can also be used for: * Predictive analytics, helping your app provide smart recommendations based on user behavior * Image recognition, allowing your app to process and analyze uploaded media Process automation, where AI can handle repetitive decision-making tasks, improving efficiency ### [](https://manual.bubble.io/help-guides/ai#the-future-of-ai-in-bubble) The future of AI in Bubble Bubble’s shift from no-code to AI visual development represents a new era in software creation—one where you can build powerful, scalable applications faster than ever. As AI continues to evolve, Bubble is committed to expanding its AI-powered tools and integrations, ensuring that you have access to the most intuitive and intelligent development experience possible. Whether through built-in AI features or seamless API integrations, Bubble is making AI an essential part of visual development. See Nick from Bubble's development team talk about the future of Bubble and AI in the video below: Last updated 22 days ago Was this helpful? * [Introduction](https://manual.bubble.io/help-guides/ai#introduction) * [AI and visual development](https://manual.bubble.io/help-guides/ai#ai-and-visual-development) * [Bubble's AI features](https://manual.bubble.io/help-guides/ai#bubbles-ai-features) * [AI app builder](https://manual.bubble.io/help-guides/ai#ai-app-builder) * [AI page builder](https://manual.bubble.io/help-guides/ai#ai-page-builder) * [Connecting your app to AI systems](https://manual.bubble.io/help-guides/ai#connecting-your-app-to-ai-systems) * [AI chat and natural language processing](https://manual.bubble.io/help-guides/ai#ai-chat-and-natural-language-processing) * [AI-powered automation and decision-making](https://manual.bubble.io/help-guides/ai#ai-powered-automation-and-decision-making) * [The future of AI in Bubble](https://manual.bubble.io/help-guides/ai#the-future-of-ai-in-bubble) Was this helpful? --- # Neam | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam.md) . [Neam](https://neam.co/) helped a media and entertainment community platform reduce WU consumption by 400%. One of the key optimizations they made was improving the page-load speed by optimizing database searches. [](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam#optimization-opportunity) Optimization opportunity -------------------------------------------------------------------------------------------------------------------------------------------------- When Neam reviewed their client’s app metrics, they found a process that was overly complex, highly repetitive, and ultimately impacting a high volume of data: Whenever the app needed to load data on a page, it was searching through the large database across the server-side and client-side. [](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam#optimizations) Optimizations: ----------------------------------------------------------------------------------------------------------------------------- * **Restructure the relational database so the app had to search through a smaller dataset:** For example, they split a ”project” data table into two separate but linked tables: ”project” and “project detail.” This allowed us to search on the main (project) data type and offload media-heavy data into the related or linked data type (project detail) that wasn’t needed in the initial search results. * **Use option sets for drop-downs:** Rather than relying on database calls, they turned common drop-down categories (e.g., statuses, types of projects) into option sets. < Add server-side filtering: By adding server-side filtering, the app improved search efficiency by offloading some processing away from the front-end. Last updated 21 days ago Was this helpful? * [Optimization opportunity](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam#optimization-opportunity) * [Optimizations:](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam#optimizations) Was this helpful? --- # Commenting | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/commenting.md) . As apps get bigger, it is important to keep track of what the different pages, key actions, styles and data types are about. This will make modifying the app down the line easier, and will help other people collaborate with you on the application simpler. [](https://manual.bubble.io/help-guides/maintaining-an-application/commenting#adding-comments) Adding comments ------------------------------------------------------------------------------------------------------------------- Our Academy quick tip on how to use comments throughout your app Bubble has a way to comment on most objects. Whenever you see a quote icon (in the top bar of the Property Editor), clicking on it will reveal the Comment Panel. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F3d9DGDJiwMAqkPdKfk2k%252Fnotes-comments-bubble%25402x.png%3Falt%3Dmedia%26token%3Dbedd0d2a-e30e-4ae8-8a98-3c59a79e5b71&width=768&dpr=3&quality=100&sign=8bc76d47&sv=2) You can leave a comment every place where you see the chat bubble icon. In this example we're looking at the property inspector of the index page. When the quote icon is filled, that means the element contains a comment. You are able to add comments to: * **Elements** (available in the property inspector as illustrated above * **Data types** (available in the _Data types_ section of the _Data_ tab * **Data type fields** (available on each field where you name them) * **Workflows** (available in the property inspector of the workflow) * **Actions** (available in the property inspector of the action) * **Privacy Rule** (available in each Privacy Rule you set up in the _Privacy_ section of the _Data_ panel) * **Option sets** (available in the Option set editor on each individual option set) * **Option set attributes** (available in the option set editor on each attribute of the selected option set) * **Styles** (available on each individual style in the _Style_ tab) To delete a comment, simply remove its content. [](https://manual.bubble.io/help-guides/maintaining-an-application/commenting#view-all-comments) View all comments ----------------------------------------------------------------------------------------------------------------------- To view all comments, click the _See all_ link in the top right corner of the note editor. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FNT4IsBtoruFdLr5u0HSq%252Flist-of-comments%25402x.png%3Falt%3Dmedia%26token%3Df6b8bbfe-2778-40c9-939c-9fb0edcd5b59&width=768&dpr=3&quality=100&sign=b85ea602&sv=2) Clicking on a note will take you to the object to which it belongs. Last updated 3 years ago Was this helpful? * [Adding comments](https://manual.bubble.io/help-guides/maintaining-an-application/commenting#adding-comments) * [View all comments](https://manual.bubble.io/help-guides/maintaining-an-application/commenting#view-all-comments) Was this helpful? --- # Global native mobile settings | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings.md) . ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#setup-global-mobile-settings-in-your-app) Setup global mobile settings in your app Navigate to _Settings > Mobile settings_, where you'll find all the settings related to native mobile apps, regardless of where you publish, that you must fill out. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FboLVaEHg4Xo0RcJ8Bnuc%252FCleanShot%25202025-07-28%2520at%252010.46.59%25402x.png%3Falt%3Dmedia%26token%3Da0d5ac79-1d44-4bc6-b957-05a022bdbbb3&width=768&dpr=3&quality=100&sign=4d140056&sv=2) To ensure everything will work, fill these out as follows: * **App display name:** This is the name of your app as it will appear to users on their device's home screen. Choose a concise and descriptive name that aligns with your app’s purpose. * **App icon:** The visual representation of your app on users’ devices. This icon should be high quality and adhere to the design guidelines for the platform you are deploying to ([iOS](https://developer.apple.com/design/human-interface-guidelines/app-icons) or [Android](https://developer.android.com/distribute/google-play/resources/icon-design-specifications) ). * **Note:** For your app icon in mobile settings, we recommend using a PNG or SVG file. Some file formats, such as `.avif`, are not supported and may cause your build to fail. * **Splash screen background color:** The background color displayed during the app’s launch while the app initializes. Choose a color that complements your app's branding and creates a seamless transition into the main interface. * **App scheme (optional):** A unique identifier used for deep linking and handling redirections from external services, such as OAuth or payment gateways. See more information below. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#using-the-app-scheme-setting) Using the app scheme setting The App Scheme setting is optional and should only be configured if your app specifically requires a custom scheme (for example, when setting up deep linking). In most cases, Bubble will automatically handle this for you, and you don’t need to provide a value. If you do need to define a custom app scheme: * The format is typically: appname * All characters must be lowercase * Only alphanumeric characters, periods (.), and hyphens (-) are allowed Make sure to follow these formatting rules carefully to ensure compatibility across platforms. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#device-permissions) Device permissions ------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#overview) Overview The Device Permissions section in the Native Mobile Settings tab lets you explicitly control which hardware or system features your app will request access to. This ensures that your app only includes the permissions it actually uses — helping avoid app store review issues. Previously, every permission supported by Bubble was automatically included in the build file, even if your app didn’t use it. This could cause problems during the app review process, especially on Google Play, where unused permissions may lead to rejections or additional scrutiny. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#how-it-works) How it works Permissions are toggled off by default. If your app requires access to a specific device feature, you’ll need to manually toggle that permission on. The available permissions include: * Camera access * Microphone access (required for Camera access) * Photo library access * Location access When you enable a permission, Bubble includes it in the app build so that the relevant app store (Apple or Google) is aware. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#using-workflows-with-permissions) Using workflows with permissions If your app includes a workflow that depends on one of these permissions — for example, using the Open camera action — but the corresponding permission is not enabled, Bubble will display an issue in the issue checker. This helps ensure that your permission settings are always in sync with your app’s functionality. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#updating-your-build) Updating your build Changes to device permissions require a new build submission. If you toggle a permission on or off after your app has been built, you’ll need to rebuild and resubmit your app for the changes to take effect. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#customizing-permission-request-text) Customizing permission request text Each permission request must be accompanied by a user-facing short explanation of why your app needs access. You can update this text in the Languages tab. The settings panel includes a link to that section to help guide you there. Providing clear, accurate language helps improve your chances of passing the app store review and builds trust with your users. Last updated 22 days ago Was this helpful? * [Setup global mobile settings in your app](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#setup-global-mobile-settings-in-your-app) * [Using the app scheme setting](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#using-the-app-scheme-setting) * [Device permissions](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#device-permissions) * [Overview](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#overview) * [How it works](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#how-it-works) * [Using workflows with permissions](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#using-workflows-with-permissions) * [Updating your build](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#updating-your-build) * [Customizing permission request text](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings#customizing-permission-request-text) Was this helpful? --- # Web app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app.md) . Deploying your app means transferring or updating the current version of your application from the Development environment to the Live environment (sometimes called _production)_, making it accessible to end-users. In other words - this is the point where you publish your app to users who are actually going to use it. Deploying an app in Bubble is done with the click of a button. [](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#requirements-for-deploying) Requirements for deploying ------------------------------------------------------------------------------------------------------------------------------------------ While you are mostly free to deploy your app whenever you like, Bubble does require that the issue tracker is not flagging any issues. If the issue tracker is showing any issues, they first need to be resolved in order to deploy. [](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#how-to-deploy) How to deploy ---------------------------------------------------------------------------------------------------------------- When the [Issue Checker](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/the-issue-tracker) is at zero and you are prepared to deploy, you can start the process. Deploying your app is instant for all practical purposes. First, click the version control button in the upper right corner of the Bubble menu bar.. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FyKi5X4fX46CTSbm2ZZWf%252Fdeploy-bubble-app.png%3Falt%3Dmedia%26token%3D96ecee75-6f35-4d8d-802d-4e71f13d5a7b&width=768&dpr=3&quality=100&sign=b48fd844&sv=2) The deploy window will open up. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FKUKXFzHxFhZ1EQPCRBP0%252FDeploy-to-live-bubble.png%3Falt%3Dmedia%26token%3De30e9872-68d8-4892-9d09-08c12626abbf&width=768&dpr=3&quality=100&sign=cf414388&sv=2) You can give a description of the deployment to document the changes you've made. This description will be saved along with the savepoint automatically. This way, if a deployment introduces any issues, you can revert back to an older version if needed. We recommend providing each deployment with a descriptive text, so that you can easily navigate your deployment history later if needed. [](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#multiple-branches-and-version-control) Multiple branches and version control ---------------------------------------------------------------------------------------------------------------------------------------------------------------- If you work with a team or on a particularly complex app, you may be using Bubble's version control system to isolate specific features or projects while they're in development. If this is the case, we recommend getting to know the [version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) system and [best practices](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices) related to it before deploying. [](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#the-user-experience-when-your-app-is-updated) The user experience when your app is updated ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ When you deploy your app, existing, online users will instantly see a notification at the top of the screen that tells them to refresh the tab. Clicking on the tab will refresh the current page. Users who don't have the app open when you deploy will not not notice anything – they will simply have access to the new version of your app the next time they log the page. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F6TV6B7T4gDJYCOEQCJ3d%252Frefresh-app%25402x.png%3Falt%3Dmedia%26token%3D27253de8-5c46-4917-8d00-9b95e8190bce&width=768&dpr=3&quality=100&sign=f307050d&sv=2) Your users will not be able to use the app until they have refreshed the page. As such, the _timing_ of the deployment can matter. If possible, plan your deployments at a time when the usage of the app is low. [](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#other-ways-to-learn) Other ways to learn ---------------------------------------------------------------------------------------------------------------------------- Video lessons[](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#video-lessons) * Playlist: [Using version control](https://www.youtube.com/watch?v=xuKtlZMfXnQ&list=PLoNVJrdvQQYlCsgQJKsprzr0RCqSMPbxK&pp=iAQB) * Video: [Introducing the version control feature](https://www.youtube.com/watch?v=07DkhNbPi6I) * Video: [What is version control?](https://www.youtube.com/watch?v=xuKtlZMfXnQ&t=10s) * Video: [Creating custom branches](https://www.youtube.com/watch?v=rH4a2VqyN_I) * Video: [Deploying your app to Live](https://www.youtube.com/watch?v=mXHF2ott4r0) Related articles[](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#related-articles) * Article series: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Last updated 22 days ago Was this helpful? * [Requirements for deploying](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#requirements-for-deploying) * [How to deploy](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#how-to-deploy) * [Multiple branches and version control](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#multiple-branches-and-version-control) * [The user experience when your app is updated](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#the-user-experience-when-your-app-is-updated) * [Other ways to learn](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app#other-ways-to-learn) Was this helpful? --- # AI page designer | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/ai-page-designer.md) . This beta feature is not yet available on dedicated instances. Welcome to the beta testing program for the AI page designer feature! We’re excited to bring you this first step in how we plan to implement artificial intelligence into the app creation process. Our goal is to help Bubble users develop great-looking, efficient apps using conversational prompts. We believe this is the future of app development and aligns with our core mission of making app development accessible to everyone. Please note that this page design feature is part of a larger body of work still in development so it is not considered complete or final. Your feedback is crucial in helping us refine and improve. Thank you for your participation and support! [](https://manual.bubble.io/help-guides/ai/ai-page-designer#prompt-guide) Prompt guide ------------------------------------------------------------------------------------------- If you have worked with AI tools such as ChatGPT and MidJourney, you will be familiar with the concept of a _prompt_. A prompt is essentially a text that instructs the AI on what you want it to generate, providing important keywords and a framework within which to work. ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#length) Length We recommend a length of about 1-2 sentences. ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#variables) Variables A prompt, in principle, gives you the freedom to type whatever descriptions you want, and our AI will make sense of it to generate the desired output. We recommend working with specific variables that our engine can use to identify the key elements in the prompts. This approach ensures that the AI understands your instructions more clearly and delivers more accurate results. Variables are not set in stone, but we encourage you to adopt a mindset where your prompt gravitates around the most important keywords. The list below is not exhaustive or required but can help you get ideas on how to structure your prompt: * \[Page type\] * \[App type\] * \[Target audience\] * \[Dark mode or no?\] * \[User Goal\] * \[Primary Color\] * \[Emotion\] * \[Image type\] * We recommend starting with photographic images. * See the full list of image types below. * \[Font description\] ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#image-types) Image types #### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#image-types-1) Image types These are examples of image styles that you can call out in your prompt: * 3d-model * Analog-film * Anime * Cinematic * Comic-book * Digital-art * Enhance * Fantasy-art * Isometric * Line-art * Low-poly * Modeling-compound * Neon-punk * Origami * Photographic * Pixel-art * Tile-texture ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#limitations) Limitations * Color schemes that involve more than one color will not work. * The landing page is the most customizable page— other pages such a dashboard, marketplace, and social media feed have less color and photography. * Bubble AI will prevent any prompt generations that violate our content guidelines. * We do not yet have the ability to create any set of features from scratch. Our pages are defined at the page level, not component or feature level. [](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-prompts) Example prompts ------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-1) Example 1 ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-2) Example 2 ### [](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-3) Example 3 Last updated 22 days ago Was this helpful? * [Prompt guide](https://manual.bubble.io/help-guides/ai/ai-page-designer#prompt-guide) * [Length](https://manual.bubble.io/help-guides/ai/ai-page-designer#length) * [Variables](https://manual.bubble.io/help-guides/ai/ai-page-designer#variables) * [Image types](https://manual.bubble.io/help-guides/ai/ai-page-designer#image-types) * [Limitations](https://manual.bubble.io/help-guides/ai/ai-page-designer#limitations) * [Example prompts](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-prompts) * [Example 1](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-1) * [Example 2](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-2) * [Example 3](https://manual.bubble.io/help-guides/ai/ai-page-designer#example-3) Was this helpful? Copy A [landing page] for a [dog walking marketplace] for [college students] who want to [make money and save time for walking their dogs]. The page should be [green], evoke emotions of [friendliness, relaxation, and convenience], use [photographic] images, and a [funky] font. Copy A [dashboard] for a [fitness tracking app] aimed at [busy professionals] who want to [monitor their health efficiently]. The page should be [blue], evoke emotions of [motivation and clarity], use [digital-art] images, and a [modern] font. Copy A [social media feed] for a [travel blog] targeting [adventure enthusiasts] who want to [share and discover new destinations]. The page should be [orange], evoke emotions of [excitement and exploration], use [cinematic] images, and a [bold] font. --- # Security dashboard | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard.md) . Bubble is a full-stack development platform that allows almost limitless flexibility in building applications. This open nature empowers you to design and structure your apps in countless ways, but with that flexibility comes the responsibility to set up your app to be as secure as it needs to be. While Bubble provides powerful tools to secure data, users, API connections, and workflows, it’s up to you to implement and enforce these measures based on your app’s specific needs. You can read more about our [shared security responsibility](https://manual.bubble.io/help-guides/security#our-shared-security-responsibility) in the opening of the Security article series. [](https://manual.bubble.io/help-guides/security/security-dashboard#what-is-the-security-dashboard) What is the security dashboard? ---------------------------------------------------------------------------------------------------------------------------------------- The security dashboard is Bubble’s dedicated security reporting and monitoring tool, designed to help you identify potential vulnerabilities in your app. It streamlines the process of conducting security audits and monitoring, providing automated insights into how various settings and design choices impact your app’s security. With the security dashboard, you can better understand potential risks and take corrective actions to safeguard your app. Article: [Security dashboard overview](https://manual.bubble.io/help-guides/security/security-dashboard/overview) The security dashboard highlights potential vulnerabilities but cannot cover every security concern in Bubble’s diverse apps. Developers remain responsible for reviewing their app’s structure and ensuring it meets their security needs. Use the security dashboard as a complement to your own testing and best practices. If you are new to app security, we strongly recommend reading our dedicated article series on the subject: Article series: [Security](https://manual.bubble.io/help-guides/security) Article section: [Our shared security responsibility](https://manual.bubble.io/help-guides/security#our-shared-security-responsibility) Last updated 22 days ago Was this helpful? Was this helpful? --- # Testing and debugging | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application.md) . A key part of developing your Bubble application is testing and debugging. Bubble has several useful tools that help you identify issues and debug them. [Introduction to testing and debugging](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics) [The debugger](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger) [The server logs](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs) Last updated 22 days ago Was this helpful? Was this helpful? --- # Generate data types from the Data tab | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab.md) . Use the [Bubble AI Agent](https://manual.bubble.io/help-guides/ai/bubble-ai-agent) to create and edit your data types and fields. It understands your existing database structure, so it creates more relevant output and won’t create duplicate fields. The page below describes the generation tool on the Data tab, which is more limited – it can only create new data types and can't modify what you already have. [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#data-type-generation-tool-bubble-ai-agent) Data type generation tool / Bubble AI Agent ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If your app has access to the Bubble AI Agent, _Generate with AI_ now opens the Agent with a pre-filled prompt. Expand that prompt to describe the new data type(s), and send the message to start the process. If you don't have access to the Agent, the feature works as described below. [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#overview) Overview -------------------------------------------------------------------------------------------------------- Bubble AI allows users to generate data types and data fields, with privacy rules included by default for data types containing potentially sensitive information. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FDZhZ3dpruXtP9WqCtfpP%252Fgenerate-data-type-ai-bubble.png%3Falt%3Dmedia%26token%3Da9b130ce-0785-4ccb-8f5f-d781aa9ed72a&width=768&dpr=3&quality=100&sign=9f19449b&sv=2) Simply tell the AI what feature you’re looking to create data types for. From your prompt, AI will generate new types, new fields on those new types, and privacy rules on those new types. The new fields can link to any new data types. Right now, Bubble AI does not support references to existing data types and does not add fields or privacy rules on existing data types. Think of this feature as an instant way to generate new parts of your database, especially when first getting started on refining your app. Your existing data types will be unchanged. For apps with access to Changelog, you can see the changes listed in the log. [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#prompting) Prompting ---------------------------------------------------------------------------------------------------------- Your output will improve the more specific you are. Our AI tools are designed to follow best practices for creating data schemas, but like all AI systems, they can sometimes make mistakes, so be sure to verify privacy rules are consistent with your needs. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FMMW0CIi2kKT5jFVKc2kh%252Fdata-type-ai-builder-prompt-bubble.png%3Falt%3Dmedia%26token%3Dd218ddc7-61a9-4029-bd14-af2043afa9c6&width=768&dpr=3&quality=100&sign=3ed3ad2d&sv=2) Once your prompt is generated, you can choose to View Changelog (if you're on Growth plan or above) or Revert Changes. Revert Changes will hard delete ALL data types, fields, and privacy rules generated by the associated request to the service. ### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#dos-and-donts) Dos and don’ts * **Do** write the prompt in the language you want the data types to be generated in * **Do** include specific data type names or fields that you want * **Do** mention which data types need privacy rules or if you know they are sensitive. * **Don’t** request the prompt for other Bubble components: elements, workflows, etc. * **Don’t** violate Bubble’s [Acceptable Use Policy](https://bubble.io/acceptable-use-policy) ### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#limitations) Limitations * You cannot generate more than 20 data types at a time. * Your prompt must be at most 400 characters in length. * The feature does not support references to existing data types and does not add fields or privacy rules on existing data types. * It will not generate any data in the data tables you are creating. * It will not generate any other Bubble components: option sets, elements, workflows, settings, etc. ### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#example-prompts) Example prompts #### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#example-1) Example 1 #### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#example-2) Example 2 #### [](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#example-3) Example 3 Last updated 15 days ago Was this helpful? * [Data type generation tool / Bubble AI Agent](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#data-type-generation-tool-bubble-ai-agent) * [Overview](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#overview) * [Prompting](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#prompting) * [Dos and don’ts](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#dos-and-donts) * [Limitations](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#limitations) * [Example prompts](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab#example-prompts) Was this helpful? Copy I’m building a travel itinerary app and need to add a feature to look up public transport. It should store information about public transportation like trains and buses. Copy I need to build a way to sensitively store data about employees, shifts, and companies for my payroll app. Employee information is sensitive, in particular.. Copy Generate data types for a dashboard to manage properties for short term rentals, with basic role-based access for tenants and landlords. --- # Previewing your app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/previewing-your-app.md) . Before sharing or publishing your app, it’s important to preview how it looks and behaves. This section covers the different ways to preview your app based on its platform. Whether you're building a web app or a native mobile app, Bubble provides tools to test your design, workflows, and data in a live environment. Choose the relevant link below to learn how to preview your app on web or mobile. [Previewing a web app](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app) [Previewing a mobile app](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app) Last updated 22 days ago Was this helpful? Was this helpful? --- # Capacity Usage (legacy) | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage.md) . This section covers the capacity metric system, which has been replaced with the workload metric. Please see this section for [up-to-date information.](https://manual.bubble.io/account-and-marketplace/account-and-billing/pricing-plans) This section of the editor shows your app's capacity usage and real time metrics. These metrics are useful for pricing purposes and assessing app performance. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#page-load-metrics) Page load metrics --------------------------------------------------------------------------------------------------------------------------------------------------- These charts show metrics about your pages loading time. This data is gathered over the latest page loads by all your users over the last 60 minutes. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#metric-to-display) Metric to display You can see three different kinds of metrics: * **Page load duration: render complete** The time in milliseconds from when the Bubble server first receives a request for a page, to when all elements on the page are finished rendering. This includes the time it takes for the server to process the request, latency between the server and the web browser, the time it takes to load all client-side javascript and css, and the time it takes the browser to draw the elements on the page. * **Page load duration: data loaded:** The time in milliseconds from when the Bubble server first receives a request for a page, to when all the elements on the page are rendered, and all the dynamic data required by above-the-fold elements is fetched and displayed. This is equivalent to the "Page Loaded Above Fold" data source. It includes all the time included "Page load duration: render complete", plus the time to load data (such as Repeating Groups lists). * **Page load: count of data items required:** This is the number of data Things loaded during the period tracked by the "Page load duration: data loaded" metric. It's an estimate of the total data the page requires in order for all the above-fold elements to finish loading. It's useful for investigating the impact that loading data (for instance, in Repeating Groups) is having on page load times. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#percentile) Percentile You can choose to show averages over the best X percents. The best 1% will show the best performance, while 99% will show all situations. Last updated 3 years ago Was this helpful? * [Page load metrics](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#page-load-metrics) * [Metric to display](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#metric-to-display) * [Percentile](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage#percentile) Was this helpful? --- # Copying the database | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/copying-the-database.md) . [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/copying-the-database#copying-across-versions) Copying between the Live and Development databases --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- This option lets you overwrite the entire database, or only a selected data type, from Development to Live and vice versa. Note that the operation can take some time to finish if you have a large database. To start the process, navigate to the _Data_ tab and then click the _Copy and restore database_ link. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FewwYkss0PBSbDIgGyPHL%252Fcopy-and-restore-database-link%25402x.png%3Falt%3Dmedia%26token%3D90550442-65ba-4e78-a849-8bebdc38432a&width=768&dpr=3&quality=100&sign=ca04ae77&sv=2) Bubble will open a popup that shows you the different options. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FMt2b21sqWnYGrGVCTbEm%252Fcopy-and-restore-database%25402x.png%3Falt%3Dmedia%26token%3Ddf2898b6-6d09-4f52-a247-f142066bb8d4&width=768&dpr=3&quality=100&sign=a61dbc3&sv=2) Click the image to enlarge. You will see two buttons: * Copy Live data into the Development database * Copy Development data into the Live database To start the process, click one of the buttons. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FT0eiAbDmsvnzl1p7j3Mx%252Fcopy-from-live-to-development.png%3Falt%3Dmedia%26token%3D17286eb9-7f75-4a7d-af7b-79848be4d938&width=768&dpr=3&quality=100&sign=30eb75cb&sv=2) Click the image to enlarge. 1. In this example, we want to copy data from Live into Development, so we click the left button 2. _Data types to copy_ lets you select _all_ _types_ or select one type\* 3. As an extra security measure to avoid accidental overwriting of data, we ask that you spell out a short sentence to confirm that you want to proceed 4. Finally, you can press the _Confirm_ button to start the operation. For large database where you copy all content, the process can take some time to finish Keep in mind when copying Live data into Development that this can give your _Collaborators_ access to more data than you intended. Always be mindful of the privacy of your users when you copy data. \*Be cautious when you copy only one data type, as it can lead to data inconsistencies if some things are related. Sometimes it's better to still restore all to make sure that no relationships are lost. Last updated 22 days ago Was this helpful? Was this helpful? --- # Restoring database backups | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups.md) . The actions described below can potentially rewrite all the contents of your database. Be careful when using these features, and double-check that your settings are correct before you go ahead. Copying and restoring large databases can take some time to finish. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups#restoring-your-database) Restoring your database ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups#point-in-time-backups) Point-in-time backups Bubble uses a system called _point-in-time backup_, which means that for every change made to the database, a snapshot is saved. This snapshot can then be used later to restore the database to that exact point in time if something should go wrong. This is particularly useful for recovering data in the case of accidental deletion or changes. Bubble backs up all your data types continuously, but you can choose to recover only specific data types. How far back in time you can recover your database depends on the Plan that you are on. Restoring your data is done in the App Data section of the Data tab. First, navigate to the Data tab, and click the _Copy and restore database_ link: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FewwYkss0PBSbDIgGyPHL%252Fcopy-and-restore-database-link%25402x.png%3Falt%3Dmedia%26token%3D90550442-65ba-4e78-a849-8bebdc38432a&width=768&dpr=3&quality=100&sign=ca04ae77&sv=2) Bubble will open a popup that shows you the different options. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FMt2b21sqWnYGrGVCTbEm%252Fcopy-and-restore-database%25402x.png%3Falt%3Dmedia%26token%3Ddf2898b6-6d09-4f52-a247-f142066bb8d4&width=768&dpr=3&quality=100&sign=a61dbc3&sv=2) You first pick the version you want to restore (Development or Live), then a time and confirm. You can choose to restore all data types or only one. Be cautious when you restore only one data type, as it can lead to data inconsistencies if some things are related. Sometimes it's better to still restore all to make sure that no relationships are lost. You can set the time of the restoration down to the second, meaning that if you know the exact time that someting went wrong, you can restore it to just a few seconds before the incident Restore operations can take a few minutes to execute if your database is large. You'll see a progress bar once you have started the process, and can close the popup and keep working on your app. It is safe to refresh the editor or close it once you have kicked off the process. Last updated 22 days ago Was this helpful? * [Restoring your database](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups#restoring-your-database) * [Point-in-time backups](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups#point-in-time-backups) Was this helpful? --- # Supported browsers | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers.md) . [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#run-mode) Run-mode ------------------------------------------------------------------------------------------------------------------------------------ Bubble's framework relies on web technologies that may not be compatible with all older browsers. Consequently, Bubble provides official support for specific browsers and versions. Keep in mind that this applies to apps in run-mode, meaning it affects the end-users of your Bubble app. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#browser-support-summary) Browser support summary * Bubble officially supports **Edge, Firefox, Chrome, Brave and Safari** on web and mobile web * We encourage end-users to upgrade these browsers to the latest version available When an end-user uses an unsupported older browser version, most parts of the app will likely still function. Browser support primarily impacts the visual display of your app, while workflows and database operations are generally unaffected. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#edit-mode) Edit-mode -------------------------------------------------------------------------------------------------------------------------------------- Edit-mode is the interface you, as a Bubble developer, interact with while building and editing your app, i.e. the Bubble editor. Bubble supports the latest version of **Edge, Firefox, Chrome, Brave and Safari** for edit-mode. We highly encourage Bubble users to upgrade these browsers to the latest version available. Last updated 3 years ago Was this helpful? * [Run-mode](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#run-mode) * [Browser support summary](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#browser-support-summary) * [Edit-mode](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers#edit-mode) Was this helpful? --- # Best practices: Version control | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices.md) . [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#use-the-main-branch-as-a-launching-pad) Use the Main branch as a launching pad ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Your Main branch is the only branch you can deploy to Live (except for the hotfix branch) and you should keep this in mind as you organize Main's child branches. What this means is that changes and experimentation should always be completed in full in a child branch and then merged up through the hierarchy until it reaches the Main branch. At that point it should be safe to delete the child branches and there should be no development work done in the Main branch. This means that the Main branch should always be the "polished" last branch of your app that's ready to be deployed. [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#merge-changes-from-parent-to-child-first) Merge changes from parent to child first ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Whenever you want to merge changes from a child branch to a parent branch, we recommend that you first merge changes from the parent branch into the child branch. This is because it's lower risk to test that everything works well in the child branch before you then merge the changes up the hierarchy into the parent branch. The same holds true when you are merging a custom branch into the Main branch. Use the Sync with Main shortcut to add all changes from Main into the custom branch first. In other words: 1. First merge the changes from the parent to the child 2. Do the necessary testing in the child branch 3. Then merge the changes from the child to the parent [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#keep-the-branch-tree-clean-and-organized) Keep the branch tree clean and organized ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Whenever a branch has served its purpose (the development is done and the changes have been merged up the hierarchy) you should delete the branch to keep your branch tree updated. Keeping around unnecessary branches makes the tree disorganized and it's easy to lose sight of why the branch was created in the first place, whether it has been merged upward already and whether it's safe to delete. You can always create a new branch as needed, so there's no need to keep around the old ones. Last updated 3 years ago Was this helpful? * [Use the Main branch as a launching pad](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#use-the-main-branch-as-a-launching-pad) * [Merge changes from parent to child first](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#merge-changes-from-parent-to-child-first) * [Keep the branch tree clean and organized](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices#keep-the-branch-tree-clean-and-organized) Was this helpful? --- # Notes on queries | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries.md) . This page will note any special points around how database queries work. These go into some of the technical details of how databases work, but can help you debug situations where a query in your app doesn't work as expected. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#stop-words) Stop words --------------------------------------------------------------------------------------------------------------------------------------- There are certain special words known as "stop words" - these tend to be short, common words which the database will ignore when you query for them, except in the context of phrases. Some examples are "the", "I", or "do". * In practice, this means that if you have a query for one of these stop words or a query involving some stop words, the results may not be fully what you expect. * ​[Here's](https://github.com/postgres/postgres/blob/master/src/backend/snowball/stopwords/english.stop) a list of stop words affecting Bubble app queries. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#stemming) Stemming ----------------------------------------------------------------------------------------------------------------------------------- "Stemming" is when databases will generalize a search query to look for other words of the same stem. For example, "test" and "testing" have the same stem, so results with the word "testing" will be found when searching for "test". * Stemming matches words with semantically similar meanings, so "temp" and "temps" will match, but "temp" and "tempo" will not because they are not different tenses of the same word; similarly, "test" and "intestine" will not match. (We use PostgreSQL with Snowball) [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#bubble-query-optimization) Bubble query optimization --------------------------------------------------------------------------------------------------------------------------------------------------------------------- When querying the database, we try to apply an optimization on mapping operations, which makes them faster. Consider the following two Searches that both return the same list of comma separated numbers: **Search A** -> "MyTypesList's count" **Search B** -> "MyTypesList's: item 0's count, MyTypesList's: item 1's count, MyTypesList's: item 2's count, MyTypesList's: item 3's count, MyTypesList's: item 4's count, MyTypesList's: item 5's count, MyTypesList's: item 6's count" **Search A** under the hood is a mapped operation and turned into a single database query at its core, which is quite performant. **Search B**, on the other hand, generates 7 distinct database queries that run one after another and combined after the fact. This leads to a significant performance hit and should be avoided whenever possible. Last updated 2 years ago Was this helpful? * [Stop words](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#stop-words) * [Stemming](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#stemming) * [Bubble query optimization](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries#bubble-query-optimization) Was this helpful? --- # Automated tests | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/automated-tests.md) . Settings applied in the _Test settings_ popup also apply to automated tests. Article: [Test settings](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings) Automated tests enable you to run security tests automatically, with two different trigger options: * Automatic test on deploy: this will automatically perform a test whenever your app is deployed to live. * Scheduled tests: this option lets you set up automated tests on a set schedule (such as daily/weekly/monthly). Last updated 22 days ago Was this helpful? Was this helpful? --- # Privacy rules checker | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/privacy-rules-checker.md) . The privacy rules checker runs a thorough analysis of your entire database. Depending on the size of your database, the process can take a few minutes to complete **Note: Privacy rules checks require data** To accurately check whether data is visible, the app must contain entries in the relevant data types. Make sure the data types you're testing include sample data so the visibility check can return meaningful results. This dedicated test reviews all data types within an app (and version) to identify which fields are publicly accessible. It checks each data type for potential information leaks, highlighting any fields that are accessible without restrictions for your review. This allows you to inspect and adjust privacy rules as needed to secure the data. Last updated 22 days ago Was this helpful? Was this helpful? --- # SEO | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/seo.md) . SEO, or Search Engine Optimization, is the effort you put into your website or app to improve its visibility in search engine results. This is a broad field encompassing a lot of different strategies both related to technical stuff (how your page is set up) and what the page offers (the content you have). ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FwHYJAckeIKb4SU1LGE8j%252Fbubble-result%25402x.png%3Falt%3Dmedia%26token%3De9156dce-cbcf-4638-b5da-84586ff020ff&width=768&dpr=3&quality=100&sign=35fc8f7d&sv=2) SEO is how you optimize your app to appear in search results, like in this example with the Bubble homepage. Search engines do two things; they crawl the web, going through millions of websites to try to understand what they're about. Then, as a user searches for something, they try to offer the most relevant results first. Optimizing for search engines is an on-going task that can be hard to predict the outcome of; while Bubble offers the tools to prepare your app for the technical side of SEO, getting search engine traffic still depends on many different factors, like: * high-quality content * relevant keywords * the age of your domain * the number and quality of inbound links * ease of navigation * accessibility * responsiveness This is not an exhaustive list, but serves to illustrate that SEO is a gradual process of continually improving a app's quality and relevance, and while checking off boxes in a list is a _part_ of it, it's not the full picture. All that being said, the road to a site that's well optimized for SEO _starts_ with the technical details, and we'll cover that and some introductory guidelines in this article series. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo#is-this-relevant-for-my-app) Is this relevant for my app? ------------------------------------------------------------------------------------------------------------------------------------- SEO is not relevant for all apps: only those that aim to get search engine traffic. In an app where it _is_ relevant, it's not necessarily relevant for all your pages: only those that are public and again where you want to get search engine traffic. Some of the settings in this guide also play a part in social media sharing. For example, you can add descriptions and images to pages that may appear in social media post where the link to the page is shared. If this is relevant for your app, you may want to read through these articles even if you are not counting on search engine visibility. This guide will introduce you to the key SEO features available in Bubble and help you optimize your application. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-article-series) SEO article series ------------------------------------------------------------------------------------------------------------------ We have separated this series into three articles: ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo#introduction-to-seo) Introduction to SEO This article contains general platform-agnostic advice for your SEO strategy. While it's not directly related to how Bubble works, it contains useful tips that may help you use the settings in the later articles effectively. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-settings-app) SEO settings: App The _app_ section will cover the SEO features that you apply to your entire app. This includes: * The app title, site name and description (used when sharing your app in social media) * The default thumbnail image (also used for social media) * Robots.txt * Sitemaps * Header/body tags * 301 redirects * Hosting files in the root directory [SEO: App](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app) ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-settings-page) SEO settings: Page The _page_ section covers the SEO that you apply to each separate page. Each page is a potential listing in the search engines that you can optimize to deliver results for the topic that page covers, whether it's a static informational page or a dynamic page such as a blog post, product or social media post. A page's SEO settings are contained with the element inspector on the page element itself, and consist of the following: * Page main title (as visible in the browser tab) * The page SEO title (as visible in search results) * The page description (used by search engines to understand the content and sometimes shown in search results) * A custom image for that page (used for social media sharing) Additional on-page SEO tools can also be added in the HTML header of each page, or by placing a HTML element on the page. [SEO: Page](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page) Last updated 3 years ago Was this helpful? * [Is this relevant for my app?](https://manual.bubble.io/help-guides/maintaining-an-application/seo#is-this-relevant-for-my-app) * [SEO article series](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-article-series) * [Introduction to SEO](https://manual.bubble.io/help-guides/maintaining-an-application/seo#introduction-to-seo) * [SEO settings: App](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-settings-app) * [SEO settings: Page](https://manual.bubble.io/help-guides/maintaining-an-application/seo#seo-settings-page) Was this helpful? --- # Security tests | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests.md) . At its core, the security dashboard is a tool for simplifying the security management of your Bubble app. It streamlines the process of identifying and addressing potential vulnerabilities. The majority of the security dashboard's features are centered around its core security test. This test runs a comprehensive analysis across various security checkpoints and returns a list of potential vulnerabilities, each accompanied by recommendations for improvement. These findings can include insights into data privacy settings, user access controls, and exposure risks of specific data fields. By highlighting these areas, the security dashboard helps you take targeted actions to strengthen your app’s security. It’s important to approach the security dashboard with the mindset that these are _potential_ vulnerabilities, meaning that they don’t automatically translate to a threat or bug in your app. You can see it as a map that guides you towards points that are worth reflecting on, but it’s not the purpose of all apps to keep all information strictly secure: as a Bubble developer, it’s still your responsibility to identify what and when page and data should be available to any given user. Similarly, it’s important to remember that due to the vast variety of apps built on Bubble, the security dashboard cannot test for or identify every possible security concern. As a developer, it’s ultimately your responsibility to review your app’s structure and ensure it aligns with your desired level of security. While the security dashboard serves as a powerful tool to highlight potential vulnerabilities, its findings should complement—rather than replace—your own thorough testing and implementation of security best practices. Before running your first security dashboard test, we recommend reading through the Security section in the User Manual. This foundational overview of Bubble’s security mechanics will help you better interpret the test results, equipping you with the context needed to make informed adjustments to your app’s security settings and design decisions. Article series: [Security](https://manual.bubble.io/help-guides/security) [Issue explorer](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer) [Issue details](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-details) Last updated 22 days ago Was this helpful? Was this helpful? --- # Bubble account security | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/bubble-account-security.md) . Your Bubble account is a very important part of security, for several reasons. It's crucial for the protection of your app's data and user information, and for stopping an intruder from creating, editing, deleting, copying or transferring ownership of your app(s). A secure account prevents potential misuse. Keep in mind that all the security measures you add to your app can potentially be circumvented and even removed if someone gains access to your Bubble account. In this article, we'll look into how you keep your account secure. [](https://manual.bubble.io/help-guides/security/bubble-account-security#authentication) Authentication ------------------------------------------------------------------------------------------------------------ For **Enterprise plan** users, we provide single sign-on (SSO) capabilities. See the article below for more information: Article series: [Bubble for enterprise](https://manual.bubble.io/help-guides/bubble-for-enterprise) ### [](https://manual.bubble.io/help-guides/security/bubble-account-security#password) Password Password and any extra authentication is set on the **account level**, and not on an app level. In other words, these settings apply to _all_ your apps. A robust password policy reduces the risk of unauthorized access. To create and maintain a strong password policy, keep these guidelines in mind: 1. **Use unique passwords:** Avoid reusing passwords across multiple accounts 2. **Create complex passwords:** Make sure your passwords are at least 12 characters long and include a mix of uppercase and lowercase letters, numbers, and special symbols. This makes it harder for attackers to crack your password using brute-force methods. 3. **Update passwords regularly:** Change your passwords every 3-6 months to minimize the risk of unauthorized access. Avoid predictable patterns when updating your password. 4. **Use a password manager:** A reliable password manager can help you generate and store complex, unique passwords. This eliminates the need to remember multiple passwords while ensuring they remain secure. ### [](https://manual.bubble.io/help-guides/security/bubble-account-security#two-factor-authentication-2fa) Two-factor authentication (2FA) We **strongly recommend enabling 2FA** to protect your account. It adds a critical layer of security by requiring a second verification step, making unauthorized access much more difficult—even if your password is compromised. While not required, **skipping 2FA** **significantly increases your risk of account takeover**. ### [](https://manual.bubble.io/help-guides/security/bubble-account-security#enabling-two-factor-authentication) Enabling two-factor authentication To enable two-factor authentication, first go your [_Account page_](https://bubble.io/account) (after logging in). 1. From there, navigate to the [security tab](https://bubble.io/account/security) 2. Click _Enable 2FA_ and follow the steps to set it up. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FOe7cendRItd8hHoCyxM9%252Ftwo-factor-authentication%25402x.png%3Falt%3Dmedia%26token%3Deb2477bd-090a-4b02-a60e-c1334449fdb3&width=768&dpr=3&quality=100&sign=ef292c6b&sv=2) ### [](https://manual.bubble.io/help-guides/security/bubble-account-security#google-authenticator-and-authy-compared) Google Authenticator and Authy compared Google Authenticator and Authy are both mobile apps that provide one-time passcodes (TOTP) that you enter when logging into your Bubble account, in addition to your regular password. There are some pros and cons with each solution, and the points below can help you choose the one that's right for you: #### [](https://manual.bubble.io/help-guides/security/bubble-account-security#authy) **Authy:** Authy is developed and maintained by Twilio. Pros: 1. Multi-device support: Authy allows you to use multiple devices simultaneously, making it easier to switch between your phone, tablet, or desktop. 2. Cloud backup: Authy enables encrypted cloud backups, which makes it simpler to recover your account in case you lose your device or need to reinstall the app. Cons: 1. Reliance on a third-party service: Authy's cloud backup feature can be a potential security concern for some users, as it relies on a third-party service for storing your data. #### [](https://manual.bubble.io/help-guides/security/bubble-account-security#google-authenticator) **Google Authenticator** Google Authenticator is developed and maintained by Google. Pros: 1. Developed by a trusted company: As a Google product, it benefits from the company's security expertise and reputation. 2. Local storage: Google Authenticator does not offer a cloud backup feature, which removes a potential security threat. Cons: 1. No multi-device support: Google Authenticator does not support multiple devices simultaneously, which can be inconvenient if you switch devices or lose your phone. 2. No cloud backup: Google Authenticator does not offer a built-in backup feature, making it more challenging to recover your 2FA accounts if you lose your device or need to reinstall the app. We strongly recommend using 2FA for your account, but do not recommend one solution over the other. #### [](https://manual.bubble.io/help-guides/security/bubble-account-security#backup-codes) Backup codes To ensure you don't lose access to your account if you lose access to the code generator, you can generate backup codes. This is a list of one-time-use unique strings that gives you access to the account in the same way as a code generated by Authy or Google Authenticator would. Backup codes should be kept strictly confidential. Password managers sometimes offer a way to store backup codes in an encrypted database to keep it secure. ### [](https://manual.bubble.io/help-guides/security/bubble-account-security#how-bubble-stores-and-checks-password) How Bubble stores and checks password Bubble uses industry-standard security practices to protect account passwords and keep them secure. Here's a brief explanation of how these techniques work: 1. **Hashing**: When you create or update your password, Bubble doesn't store the plaintext version of it. Instead, we use a cryptographic hash function to convert your password into a fixed-size string of characters, which is then stored in the database. What this means in practice is that a potential intruder not only can't see your password string – they can't even determine its length since all the hashed passwords have the same number of characters. Hash functions are designed to be one-way, meaning it's extremely difficult, if not impossible, to reverse-engineer the original password from the hash. When you log in, Bubble hashes the password you provide and compares it with the stored hash. If the hashes match, the password is correct, and you are granted access. In short, even Bubble's engineering team does not have access to your password: only you do. 2. **Salting**: To further enhance the security of hashed passwords, we use a technique called _salting_. A salt is a unique, random string of characters generated for each user. This salt is combined with the user's password before it's hashed. The resulting hash is then stored in the database alongside the salt. Salting makes it much harder for attackers to use precomputed tables of hashes (called rainbow tables) or other brute-force methods to crack passwords, as they would need to compute hashes for each unique salt. Last updated 22 days ago Was this helpful? * [Authentication](https://manual.bubble.io/help-guides/security/bubble-account-security#authentication) * [Password](https://manual.bubble.io/help-guides/security/bubble-account-security#password) * [Two-factor authentication (2FA)](https://manual.bubble.io/help-guides/security/bubble-account-security#two-factor-authentication-2fa) * [Enabling two-factor authentication](https://manual.bubble.io/help-guides/security/bubble-account-security#enabling-two-factor-authentication) * [Google Authenticator and Authy compared](https://manual.bubble.io/help-guides/security/bubble-account-security#google-authenticator-and-authy-compared) * [How Bubble stores and checks password](https://manual.bubble.io/help-guides/security/bubble-account-security#how-bubble-stores-and-checks-password) Was this helpful? --- # Security checklist | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-checklist.md) . Before reading this article, keep in mind that a checklist can’t cover all possible security scenarios or threats. Consider it a useful starting point but remember that your app is a unique project that may warrant additional security measures not covered here. We recommend reading our in-depth guides, continuing to educate yourself on Bubble app security best practices and get in touch with our [Success team](https://bubble.io/contact) if you have any questions. Ensuring the security of your app is ultimately your responsibility, but we will do our best to provide you with the resources you need. In this section we will cover many of the typical points that need to be checked and re-checked as your app goes through the first and continued deployments. [](https://manual.bubble.io/help-guides/security/security-checklist#planning) Planning ------------------------------------------------------------------------------------------- * Plan the different parts of your security structure before you start building: * Data types * Pages * User roles [](https://manual.bubble.io/help-guides/security/security-checklist#bubble-account-security) Bubble account security ------------------------------------------------------------------------------------------------------------------------- * Use a strong password * Enable two-factor authentication (2FA) * Create and maintain a password and 2FA policy for all collaborators [](https://manual.bubble.io/help-guides/security/security-checklist#app-access-security) App access security ----------------------------------------------------------------------------------------------------------------- * Don’t give collaborators more access than they need * Remove collaborators that no longer need access * Maintain a policy for access to the live database [](https://manual.bubble.io/help-guides/security/security-checklist#database) Database ------------------------------------------------------------------------------------------- * Add privacy rules to all private data types * Use _Only when_ conditions to protect data from unauthorized editing in workflows or use auto-binding in combination with privacy rules * Be mindful of who has access if you copy your Live database to Development [](https://manual.bubble.io/help-guides/security/security-checklist#page-security) Page security ----------------------------------------------------------------------------------------------------- * Don’t store sensitive data in page elements and workflows * Be mindful of other details that are visible in Bubble’s Javascript files * Name of pages * Name of data types and default values * Information stored in the [API Connector](https://manual.bubble.io/help-guides/security/security-checklist#user-content-fn-11) * Names and attributes of [Option sets](https://manual.bubble.io/help-guides/security/security-checklist#user-content-fn-12) * Names and strings saved in [application texts](https://manual.bubble.io/help-guides/security/security-checklist#user-content-fn-13) * Use the [App optimizer](https://manual.bubble.io/help-guides/security/security-checklist#user-content-fn-14) to remove deleted data from the code * Don’t store sensitive data in URL parameters [](https://manual.bubble.io/help-guides/security/security-checklist#plugins-and-custom-headers) Plugins and custom headers ------------------------------------------------------------------------------------------------------------------------------- * Plugins and custom headers may affect security – make sure they come from a trusted source Last updated 22 days ago Was this helpful? * [Planning](https://manual.bubble.io/help-guides/security/security-checklist#planning) * [Bubble account security](https://manual.bubble.io/help-guides/security/security-checklist#bubble-account-security) * [App access security](https://manual.bubble.io/help-guides/security/security-checklist#app-access-security) * [Database](https://manual.bubble.io/help-guides/security/security-checklist#database) * [Page security](https://manual.bubble.io/help-guides/security/security-checklist#page-security) * [Plugins and custom headers](https://manual.bubble.io/help-guides/security/security-checklist#plugins-and-custom-headers) Was this helpful? --- # Generate apps with AI | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator.md) . [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#prompt-guide) Prompt guide --------------------------------------------------------------------------------------------------- **Acceptable use:** Don’t submit prompts that violate our [Acceptable Use Policy](https://bubble.io/acceptable-use-policy) . Prompts that are malicious, contain injections, or are too vague will be automatically rejected. Creating mobile apps with the AI App Generator is currently in beta. Bring your app idea to life with a well-written prompt. Here’s how to craft a clear, detailed prompt that helps Bubble AI build what you have in mind. These guidelines apply whether you’re building a web app or a native mobile app. ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-to-include) **What to include** * **App type and purpose** – What kind of app is it, and what problem does it solve? * **Target users** – Who is this app for? * **Core features** – What should users be able to do? * **Visual style** – Any colors, mood, or design references to guide the look and feel **Example structure** Copy "A [app type] for [target users] to [main purpose]. Users can [key features]. Style should be [visual preferences]." [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#effective-prompt-examples) Effective Prompt Examples ----------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#web-good-examples) Web - Good Examples #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#task-management-app) Task Management App #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#local-restaurant-finder) Local Restaurant Finder #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#fitness-tracker) Fitness tracker ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#mobile-good-examples) Mobile - Good Examples #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#lifestyle-app) Lifestyle app #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#productivity-tracker) Productivity tracker #### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#social-media-scheduler) Social Media scheduler * * * [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#tips-for-better-results) ✅ Tips for better results --------------------------------------------------------------------------------------------------------------------------- 1 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#be-specific-about-purpose) Be specific about purpose **Instead of:** "A business app" **Try:** "An invoice management app for freelancers" 2 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#define-your-users-clearly) Define your users clearly **Instead of:** "For everyone" **Try:** "For college students planning events" 3 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#give-visual-directions) Give visual directions **Instead of:** "Make it look good" **Try:** "Professional design with navy blue and gold, inspired by financial apps" 4 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#focus-on-core-features-first) Focus on core features first **Instead of:** "Users can do everything they need" **Try:** "Users can create events, invite friends, and track RSVPs" [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-to-avoid) ❌ What to avoid ------------------------------------------------------------------------------------------------------- 1 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#being-too-vague) Being too vague "Make me a social app that's really cool and modern." 2 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#too-detailed-on-layout) Too detailed on layout "Put the login button in the top right corner, make the sidebar exactly 250px wide, and use Helvetica font for all headers." 3 ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#technical-specifications) Technical specifications "Integrate with Stripe API, use PostgreSQL database, and implement OAuth authentication with Google and Facebook." [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#style-and-design-guidelines) Style and design guidelines --------------------------------------------------------------------------------------------------------------------------------- There is some overlap between color and mood, but make sure you include both in your prompt. ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#color-preferences) Color Preferences * Be specific: "forest green and cream" vs. "green" * Mention themes: "dark mode," "minimalist," "vibrant" * Reference styles: "corporate professional," "playful startup" ### [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#mood-and-feel) Mood and feel * Professional and corporate * Fun and playful * Clean and minimalist * Bold and modern * Warm and friendly [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#limitations) Limitations ------------------------------------------------------------------------------------------------- Please note that the mobile app generator creates UI layouts, dynamic expressions, sample data and data types, but it does _not_ generate workflows yet. [](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#faq) FAQ --------------------------------------------------------------------------------- What is sample data?[](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-is-sample-data) Sample data refers to placeholder information that mimics real data and is used during the app-building process. Bubble AI generates sample data to help you visualize how your app will look and function once it’s populated with actual user information. For example, if your app includes a list of users or a gallery of products, Bubble AI might fill those areas with sample names or descriptions. This temporary data is particularly useful for making sure your app works: testing and refining the design, workflows, and overall user experience before launching your app. Once you’re satisfied with the app’s structure, you can replace the sample data with live information or accept real data coming from your users. By including realistic sample data, Bubble ensures you can clearly see how your app will behave in a real-world scenario. Last updated 2 months ago Was this helpful? * [Prompt guide](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#prompt-guide) * [What to include](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-to-include) * [Effective Prompt Examples](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#effective-prompt-examples) * [Web - Good Examples](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#web-good-examples) * [Mobile - Good Examples](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#mobile-good-examples) * [✅ Tips for better results](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#tips-for-better-results) * [Be specific about purpose](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#be-specific-about-purpose) * [Define your users clearly](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#define-your-users-clearly) * [Give visual directions](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#give-visual-directions) * [Focus on core features first](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#focus-on-core-features-first) * [❌ What to avoid](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#what-to-avoid) * [Being too vague](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#being-too-vague) * [Too detailed on layout](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#too-detailed-on-layout) * [Technical specifications](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#technical-specifications) * [Style and design guidelines](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#style-and-design-guidelines) * [Color Preferences](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#color-preferences) * [Mood and feel](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#mood-and-feel) * [Limitations](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#limitations) * [FAQ](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator#faq) Was this helpful? Copy A productivity app for small teams to track project tasks and deadlines. Team members can create tasks, assign them to colleagues, set due dates, and mark completion. Clean, minimalist design with blue and white colors. Copy A discovery app for food lovers to find nearby restaurants and read reviews. Users can search by cuisine type, view restaurant details, see ratings, and save favorites. Modern design with warm colors and food photography. Copy A wellness app for fitness enthusiasts to log workouts and track progress. Users can record exercises, set goals, view workout history, and share achievements. Energetic design with bright green accents and dark mode support. Copy A meal planning app for busy families to organize weekly menus and discover recipes. Warm design with sage green and cream, food photography emphasis. Copy A time-blocking app for knowledge workers to schedule focused work sessions. Users can create time blocks, set focus timers with breaks, and track daily productivity patterns. Minimalist design with forest green and cream, calm aesthetic. Copy A content scheduling app for creators and small businesses to plan posts across platforms. Modern design with coral and navy blue, influencer-focused style. --- # Publishing your app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/publishing-your-app.md) . **First of all, if you’ve reached the point where you’re ready to publish your app—congratulations! 🎉** Whether you generated your app using AI and refined it in the editor, or built it from scratch on your own, launching to a live audience is an exciting milestone. In this article, we’ll cover some key points to keep in mind as you prepare to welcome real users into your app. [](https://manual.bubble.io/help-guides/publishing-your-app#the-development-and-live-environments) The Development and Live environments --------------------------------------------------------------------------------------------------------------------------------------------- Before publishing your app, it’s important to understand the difference between the Development and Live environments. You’re likely already familiar with the Development environment, where you can preview and test your app privately—away from public users. However, to ensure a smooth launch, we recommend reviewing the checklist below to prepare for the key differences between your app’s test environment and what your users will experience in Live. ✅ **Checklist:** Preparing your app for live users[](https://manual.bubble.io/help-guides/publishing-your-app#checklist-preparing-your-app-for-live-users) #### [](https://manual.bubble.io/help-guides/publishing-your-app#databases) **Databases** **Separate databases:** The Development and Live environments each have their own independent database. Any data you’ve created while testing—such as users, test records, or custom data types—will **not** automatically appear in the Live version. When you publish your app, the Live database will start empty unless you’ve manually added or copied data into it. Make sure to account for this if your app depends on preloaded data. **Copying data:** If your Live app needs access to data you've created in Development, consider using the **Copy and restore database** feature to migrate specific data types from Development to Live. **Erasing test data:** If you've previously added test data to your Live database (manually or through testing), review and delete any information that shouldn’t be visible to end users before launching. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#security) **Security** **Security matters in Live:** In Development, it's easy to overlook security because you're the only one using the app. But once you invite real users to interact with your app, you need to ensure their data is properly protected with privacy rules and secure workflows. **Review the security guide:** The User Manual includes a [full article series on app security](https://manual.bubble.io/help-guides/security) . We recommend reviewing it thoroughly before launch to ensure your app meets best practices. **Set up privacy rules:** [Privacy rules](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules) are the foundation of your app’s data security. Make sure you’ve created clear, effective rules for all data types and fields that may contain sensitive or personal information. **Run a security audit:** Use Bubble’s built-in [security audit tools](https://manual.bubble.io/help-guides/security/security-dashboard) to run an audit of your app. This tool can help uncover common misconfigurations. **Update preview credentials:** Bubble includes [built-in password protection for the Development environment](https://manual.bubble.io/core-resources/application-settings/general#limit-access-to-this-app-with-a-username-and-password) . Before launching, make sure your preview credentials use a secure, unique username and password that only you (or your team) can access. **Set editor access rights:** You can choose whether your app editor is public or private. Before going l[ive, make sure your editor is set to private](https://manual.bubble.io/core-resources/application-settings/general#application-rights) so that only invited collaborators can view and edit the app. **Remove unused collaborators:** If you've invited [collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration) during development who no longer need access, review your app’s collaborator list and remove anyone who shouldn’t have ongoing editing permissions. This helps reduce risk and keeps your workspace organized. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#design-and-responsiveness) **Design and responsiveness** **Preview your app on different screen sizes:** Before going live, test your app on a variety of devices and screen sizes to make sure everything displays correctly. Use Bubble’s responsive engine to adjust layouts as needed. **Check mobile usability:** If your app is intended for mobile users, make sure that buttons, text inputs, and other interactive elements are easy to use on smaller screens. **Test edge cases and empty states:** Ensure your app handles empty or unusual data gracefully—for example, how does it behave when a repeating group has no results? * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#workflows-and-functionality) **Workflows and functionality** **Review workflows for unexpected behavior:** Go through all critical workflows (e.g. sign-up, payments, navigation) to make sure they behave as expected and that there are no missing steps or conditions. **Check conditions and navigation rules:** Test any conditionals that show/hide elements or navigate users to different pages. Make sure users see the right views based on their role, status, or data. **Verify redirects and page protections:** Ensure users can't manually access pages they shouldn't. Use page redirects and conditional logic to prevent unauthorized access. Read more about page security [here](https://manual.bubble.io/help-guides/security/page-security) . * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#performance-and-optimization) **Performance and optimization** **Remove unused elements and plugins:** Clean up elements, styles, workflows, and plugins you’re not using. This helps reduce app load time and clutter. **Test load time and responsiveness:** Open your app on a fresh browser or device and see how quickly it loads. If performance is slow, look into optimizing data searches and page design. **Limit heavy searches or nested elements:** Minimize searches inside repeating groups or conditions that run on every page load. These can impact performance, especially for users with slower connections. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#legal-and-compliance) **Legal and compliance** **Set up a privacy policy and terms of service:** If you’re collecting user data, most regions require a clear privacy policy. Include links to these in your app’s footer or sign-up/login screens. **Comply with data protection regulations:** Ensure your app meets basic requirements for handling personal data securely—especially if serving users in regions with strict regulations (e.g. GDPR, CCPA). * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#final-checks) **Final checks** **Use the issue checker:** Bubble’s issue checker will alert you to common setup problems before going live. Run it and resolve any outstanding issues. **Test sign-up, login, and password reset flows:** Make sure these flows are not only working but also protected with security best practices like rate limiting and proper validations. **Add test users and test all roles:** If your app has different user roles (admin, regular user, etc.), test each one to make sure the experience is correct and secure for all cases. [](https://manual.bubble.io/help-guides/publishing-your-app#web-and-native-mobile-app-publishing) Web and native mobile app publishing ------------------------------------------------------------------------------------------------------------------------------------------- Bubble supports building apps for the web, as well as native mobile apps that can be published to the iOS App Store and Google Play Store. All of this is managed from a single editor, with a shared database and unified workflow logic. You can choose to build and publish your app for the web, iOS, Android—or any combination of the three. Each platform follows its own publishing process. Web apps are deployed directly from the Bubble editor, while publishing to iOS and Android involves additional steps handled through Apple and Google’s respective systems. The guides below provide a step-by-step walkthrough for publishing your app on all supported platforms. Before proceeding, we recommend reviewing the [checklist above](https://manual.bubble.io/help-guides/publishing-your-app#checklist-preparing-your-app-for-live-users) to ensure your app is fully prepared for live users. 💻 Publishing a web app[](https://manual.bubble.io/help-guides/publishing-your-app#publishing-a-web-app) #### [](https://manual.bubble.io/help-guides/publishing-your-app#deploying-your-web-app) [Deploying your web app](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app) Publishing a web app is essentially done with the click of a button, and makes your app available to live users within seconds. 📱 Publishing a native mobile app[](https://manual.bubble.io/help-guides/publishing-your-app#publishing-a-native-mobile-app) Publishing the native mobile version of your app involves a few additional steps compared to web deployment. You’ll first need to configure your app’s general mobile settings, and then follow the platform-specific publishing steps for iOS and Android. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#overview) [**Overview**](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app) This introductory article provides an overview of the process for publishing your app to the various app stores. We recommend starting here before moving on to the detailed step-by-step guides. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#global-native-mobile-settings) [**Global native mobile settings**](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings) Start by reviewing and configuring the general mobile settings for your app. These apply to both iOS and Android and should be completed before moving on to platform-specific steps. * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#ios-app-store) [**iOS App Store**](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/ios-app-store) This guide walks you through the full process of publishing your app to [Apple’s App Store](https://www.apple.com/app-store/) . It includes important steps related to Apple’s ecosystem—such as developer account setup, certificates, and App Store Connect—which may involve additional requirements and fees outside of Bubble’s control. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FX0GV7edTVDJR79VZZbBc%252FCleanShot%25202025-04-25%2520at%252014.32.35.png%3Falt%3Dmedia%26token%3D6861961a-2376-4e09-843a-12994e09b946&width=768&dpr=3&quality=100&sign=371dcb2e&sv=2) * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#google-play-store) [**Google Play Store**](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/google-play-store) This guide covers the steps required to publish your app on the [Google Play Store](https://play.google.com/) . Like iOS, the Android publishing process includes steps managed through Google's platform, some of which may also include external fees and configuration. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FHm4vK0Cd4CLFvRjNoGZ9%252FCleanShot%25202025-04-25%2520at%252014.32.35.png%3Falt%3Dmedia%26token%3D929c2b76-160c-42e6-a300-7aef4202d8d4&width=768&dpr=3&quality=100&sign=33246ef&sv=2) * * * #### [](https://manual.bubble.io/help-guides/publishing-your-app#faq) [**FAQ**](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq) We’ve compiled a set of frequently asked questions to help you navigate the mobile publishing process. If you run into issues or are unsure about a particular step, this resource is a great place to start. Last updated 22 days ago Was this helpful? * [The Development and Live environments](https://manual.bubble.io/help-guides/publishing-your-app#the-development-and-live-environments) * [Web and native mobile app publishing](https://manual.bubble.io/help-guides/publishing-your-app#web-and-native-mobile-app-publishing) Was this helpful? --- # Collaborators | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration.md) . Bubble makes it easy to add more editors to your app to speed up development and work on multiple features at the same time. As the app owner, you can decide who to invite to work on the app and control the level of access they have. This article will explore how to manage your team efficiently while maintaining the security of your app and its data. Collaboration features are available on Bubble's higher-tier plans. **Free** and **Starter** plans do not support collaborators, while the **Growth** plan allows up to two collaborators. **Team** and **Enterprise** plans offer even more flexibility, with the **Enterprise** plan allowing customization of collaborator limits. See and compare the different Bubble plans [here](https://bubble.io/pricing/compare) . Our Academy quick tip on how to add collaborators [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#what-are-collaborators) What are collaborators? ------------------------------------------------------------------------------------------------------------------------------------- Every editor that you add to your app is known as a _collaborator_. They are connected to an app, and not to your account, meaning that if you have multiple Bubble projects, you can choose which one(s) to add one or more collaborators to. The user account that is paying for the Bubble app is known as the app _owner_. Collaborators need to have a registered Bubble account before they are invited. Collaborators with Agency accounts do not count toward the app’s collaborator limit. This exception applies to all plans, including Free and Starter plans. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#inviting-collaborators) Inviting collaborators ------------------------------------------------------------------------------------------------------------------------------------ Adding collaborators is done in a few easy steps\_ 1. First, make sure that the person you are inviting has a Bubble account. If not, they can sign up [here](https://bubble.io/login?mode=signup) . 2. Navigate to _Settings - Collaboration_. 3. Under _Invite a user_, provide their email address and click _Invite._ [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#controlling-access-levels) Controlling access levels ------------------------------------------------------------------------------------------------------------------------------------------ Each user you invite (plus your own account) makes up one row as exemplified below, meaning you set the access level of each individual user. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FB85BBDHGoo0lIcjnfCZs%252Fcollaborator-access-levels%25402x.png%3Falt%3Dmedia%26token%3Da5ec5074-882a-480d-8fe5-4f91fe84d6a9&width=768&dpr=3&quality=100&sign=cf520bbf&sv=2) ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#admin) Admin Selecting the admin checkbox grants the most extensive set of privileges, just below the owner level. Admins can invite and edit the rights of users, and all other privileges will be set to their most generous level. Admins can also change the general settings of your app. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#app) App * View only * View and edit This setting determines whether the collaborator can make edits to your application or just view it. It does not affect the collaborators access to the database. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#data) Data This setting determines the access a user has to your database. * No permission - (cannot see or edit any database data in Development or Live) * View only - (can only view data, but cannot change it in the database editor) * View and run as (can only view data, but can also use the _run as_ feature) * View and edit (can view and freely edit data) ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#logs) Logs * No access * View and query This setting determines the collaborator's access to the _Logs_ section in the Bubble editor. Keep in mind that logs can give access to see data from the database and to scheduled workflows. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#only-development) Only Development If this is checked, the collaborator can only access the app and database of your Development environment. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#removing-a-collaborator) Removing a collaborator -------------------------------------------------------------------------------------------------------------------------------------- To remove a collaborator, simply click _remove_ in the row of the collaborator you want to remove. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#transferring-an-app) Transferring an app ------------------------------------------------------------------------------------------------------------------------------ This will immediately transfer ownership of the app to another Bubble user. Be careful when using - if you are not an admin collaborator on the app, upon transfer, you will not be able to undo the transfer. If you would like to stay on as an Admin Collaborator, you must check the box on the Transfer modal. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#multi-user-editing) Multi-user editing ---------------------------------------------------------------------------------------------------------------------------- If more than one user modifies an app at the same time, you will see the mouse of the other users, which helps prevent two users from modifying the same elements at the same time. You can toggle this setting with the _Show the cursor of other editors when they modify the application_ checkbox at the bottom of the page. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#general-advice-when-working-with-collaborators) General advice when working with collaborators ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The first thing to emphasize about the collaboration feature is that you are potentially granting another Bubble users a very wide access to both your app and its data. While this feature can be very powerful and indeed encourage collaboration, it should be used with care. Keep in mind the following as you start inviting collaborators: * **Don't give broader access than what's needed:** This is advice that applies to computer security: don't give any user access to more than they need to do their job. * **Remove collaborators when their job is done:** If the collaborator is working on the app for a limited amount of time, remove them from the list. Keep in mind, they can be added back any time you need them. * **Consider closing access to the Live app:** granting access to Development is usually enough to develop new features and fix bugs. This also lets you stay in control of what's deployed to Live. * **Consider your user's privacy:** Only give access to the database if it's necessary – especially the Live database. This helps you ensure that your user's data remains secure. if you need to debug with Live data, you can also consider transferring data (all of it or only the needed data) with the _Copy and restore database_ feature. [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#faq-collaborators) FAQ: Collaborators --------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#why-cant-i-add-a-collaborator) Why can't I add a collaborator? There can be a few different reasons why you can't add a collaborator to your app. * **Free or Starter Plan:** These plans do not support collaborators. Upgrade to the Growth plan or higher. * **Growth Plan Limit Reached:** The Growth plan allows only two collaborators (owner + one editor). Remove an existing collaborator or upgrade to a higher plan. * **Agency Account Misconfiguration:** Ensure the collaborator is using their Agency-associated email. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#why-dont-i-see-the-collaboration-tab) Why don't I see the collaboration tab The Collaboration tab is only available on Growth plans or higher. Upgrade your plan to enable this feature. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#can-collaborators-use-the-bubble-ai-agent) Can collaborators use the Bubble AI Agent? Yes. Collaborators can access and prompt the Agent just like the account owner. Any restrictions placed on the collaborator also apply to their use of the Agent. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#can-i-invite-someone-who-doesnt-have-a-bubble-account-yet) Can I invite someone who doesn't have a Bubble account yet? The person needs to have an existing Bubble account that matches the email you enter in the _Add collaborator_ field. Last updated 1 month ago Was this helpful? * [What are collaborators?](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#what-are-collaborators) * [Inviting collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#inviting-collaborators) * [Controlling access levels](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#controlling-access-levels) * [Admin](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#admin) * [App](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#app) * [Data](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#data) * [Logs](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#logs) * [Only Development](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#only-development) * [Removing a collaborator](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#removing-a-collaborator) * [Transferring an app](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#transferring-an-app) * [Multi-user editing](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#multi-user-editing) * [General advice when working with collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#general-advice-when-working-with-collaborators) * [FAQ: Collaborators](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#faq-collaborators) * [Why can't I add a collaborator?](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#why-cant-i-add-a-collaborator) * [Why don't I see the collaboration tab](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#why-dont-i-see-the-collaboration-tab) * [Can collaborators use the Bubble AI Agent?](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#can-collaborators-use-the-bubble-ai-agent) * [Can I invite someone who doesn't have a Bubble account yet?](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration#can-i-invite-someone-who-doesnt-have-a-bubble-account-yet) Was this helpful? --- # API workflow scheduler | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler.md) . A scheduled workflow (known as an API workflow) is a workflow that is scheduled to run on the Bubble server at a specific time. In the _Logs_ tab of your application editor, you can access the scheduler to view all upcoming scheduled workflows. The Live and Development environments in your app have separate schedules. If you don't see workflows that you expected to be in the list, check that you are looking at the right environment. [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#how-scheduled-workflows-are-queued) How scheduled workflows are queued -------------------------------------------------------------------------------------------------------------------------------------------------------- The scheduler is a queue, and can be imagined as a funnel. If a funnel is filled with water faster than the rate at which it drains, it will be congested and it will affect its flow. Similarly, if the scheduler is "filled" with a lot of simultaneous or very shortly spaced workflows, the scheduler can be "congested", leading to delays. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#avoiding-delays) Avoiding delays To avoid delays when working with scheduled workflows, follow the recommendations below: * The more _heavy_ the workload of the workflow, the more server capacity it will use. This is both affected by the number of actions in the workflow, and the complexity of those workflows * Database operations that work on a large volume of data (searches (especially with advanced filters) and actions that work on a list of things are particularly taxing * A high number of actions, and in particular if they depend on each other (such as using _result of step X_) can also slow things down * If you are scheduling a big number of workflows (by use of Schedule API Workflow on a list or recursively), it helps to consider spacing them out with some time in-between each cycle. How much time depends on the complexity of the workflow and how much capacity your app has in general * If the process does not need to finish at the highest possible speed, you can experiment setting a delay time of several seconds to control the capacity. Overall, server-side workflow are a very powerful feature, but you may find that you need to experiment a bit to learn how to build workflows that don't overwhelm the system. [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#navigating-scheduled-workflows) Navigating scheduled workflows ------------------------------------------------------------------------------------------------------------------------------------------------ To search for scheduled workflows, set a time in the datetime input and click _Show_. Bubble will search for all workflows that are scheduled after the time you have specified. Note that the search can take a little bit of time to finish. The columns let you see the details for that specific workflow: **Scheduled time** is the datetime when the workflow is scheduled to run. It will show in the timezone reported by your browser (meaning it may look different to you and the user who scheduled it if you are not in the same timezone). **ID** is the ID of the scheduled workflow. Every workflow that is scheduled has a unique ID used to identify that workflow. **API Event** is the event of the workflow, recognized by the label you have given it in the Workflow editor. **Current user** is the email of the user that scheduled the workflow **Parameters** include any custom parameters that were provided when the workflow was scheduled ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FVYHI4oynjCcwkjEymIWE%252FCleanShot%25202023-03-27%2520at%252014.57.57.png%3Falt%3Dmedia%26token%3Dec8c2149-c6c7-4770-90db-b827508a98bc&width=768&dpr=3&quality=100&sign=f744713c&sv=2) [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#pause-tasks) Pause Tasks ---------------------------------------------------------------------------------------------------------- Be careful when using the _Pause tasks_ feature, as this will stop all API Workflows from running; if you are working in the Live environment and have live users scheduling API workflows, they will not run until _Pause tasks_ has been deactivated. If you are experiencing workflows not running as expected, check this setting.![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FVYHI4oynjCcwkjEymIWE%252FCleanShot%25202023-03-27%2520at%252014.57.57.png%3Falt%3Dmedia%26token%3Dec8c2149-c6c7-4770-90db-b827508a98bc&width=300&dpr=3&quality=100&sign=f744713c&sv=2) Click here to pause upcoming workflows. If they are already on pause, this will read “Resume tasks,” which you can click in order for scheduled workflows to run again. [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#cancel-all) Cancel all -------------------------------------------------------------------------------------------------------- You can delete all past workflows that have not run yet, or scheduled workflows in their entirety. [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#faq-api-workflow-scheduler) FAQ: API Workflow scheduler ----------------------------------------------------------------------------------------------------------------------------------------- #### [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#does-the-scheduler-show-external-api-requests) Does the scheduler show external API requests? No, since workflow API requests that come from an external app are not _scheduled_ but triggered immediately, they will not show up in the scheduler. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#what-happens-if-a-workflow-is-scheduled-in-the-past) What happens if a workflow is scheduled in the past? An API workflow scheduled in the past will trigger immediately, and as such will not show up in the scheduler. Last updated 2 years ago Was this helpful? * [How scheduled workflows are queued](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#how-scheduled-workflows-are-queued) * [Avoiding delays](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#avoiding-delays) * [Navigating scheduled workflows](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#navigating-scheduled-workflows) * [Pause Tasks](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#pause-tasks) * [Cancel all](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#cancel-all) * [FAQ: API Workflow scheduler](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler#faq-api-workflow-scheduler) Was this helpful? --- # Wiping change history | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history.md) . **NOTE:** Wiping your change history is permanent and cannot be undone. This action deletes all database backups, and you will no longer be able to restore your database to any prior state. By proceeding, you acknowledge that you understand the consequences and accept responsibility for this action. Bubble allows you to clear your database change history. This article will delve into the implications of this action and weigh its advantages and drawbacks. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#what-does-it-mean-to-wipe-the-change-history) What does it mean to wipe the change history ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The databases (Development and Live) in your app are both continually backed up for every change that you make (often called real-time backup). This allows you to revert the database to any specific moment in the past, right down to the exact second. The length in time you can go back depends on the plan you are on. The change history represents the records from these backups. By erasing this history, you forfeit the option to restore your database to any previous state. Once wiped, the real-time backups resume, setting your earliest possible restore point to the moment immediately after the wipe. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#why-would-you-want-to-wipe-the-change-history) Why would you want to wipe the change history? ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- In the majority of cases, there is no reason to erase these backups. They are there to make sure that in the case that you have any reason to revert your database to a previous state, you can do so quickly and without having to export or import any data. With that said, there are a few scenarios where you may consider this option: * If you have data that you are completely comfortable erasing; for example, you may have test data in one or both of your databases that you want to erase forever * Clearing the change history might slightly improve your database's performance due to reduced data. However, this potential minor speed boost must be balanced against the significant downside of losing your backup history. Though there might be a marginal benefit for extensive databases, we typically advise against erasing the change history solely for performance gains. * If your app is on the Enterprise plan, clearing database history can save storage space * If you wish to permanently remove data, purging the database history is essential to ensure the data cannot be restored by rolling back to a previous state. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#how-to-wipe-the-database-change-history) How to wipe the database change history --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To wipe the database change history, follow these steps: 1. Go to _Data_ _\- App data_ in the Bubble editor 2. **Make sure** you have the correct database (development/live) selected using the _Switch to live database/Switch to development database_ in the upper right corner of the _App data_ section. 3. Click _Copy and restore database_ 4. In the bottom part of the popup, follow the on-screen instructions and click _Confirm_ 5. Wiping the change history can take a few minutes, depending on the size of your database [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#faq-wiping-the-database-change-history) FAQ: Wiping the database change history -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#will-wiping-change-history-affect-both-databases) Will wiping change history affect both databases? Wiping your database change history will affect the database you are currently viewing in the _App data_ section. See the [instructions above](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#how-to-wipe-the-database-change-history) for how to switch between the two. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#i-accidentally-wiped-the-change-history-is-there-any-way-to-get-it-back) I accidentally wiped the change history – is there any way to get it back? No, this action is permanent and cannot be undone. Before proceeding, confirm that you have the correct database selected and that you understand the consequences. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#does-wiping-the-change-history-disable-the-continuous-backups) Does wiping the change history disable the continuous backups? No. Continuous backups resume immediately after the wipe.You will be able to restore to any point after the wipe, but not before. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#can-i-select-what-data-to-purge-i.e.-only-erase-data-of-a-specific-data-type) Can I select what data to purge? I.e. only erase data of a specific data type? No, wiping the database change history will affect all data types in that database. Last updated 22 days ago Was this helpful? * [What does it mean to wipe the change history](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#what-does-it-mean-to-wipe-the-change-history) * [Why would you want to wipe the change history?](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#why-would-you-want-to-wipe-the-change-history) * [How to wipe the database change history](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#how-to-wipe-the-database-change-history) * [FAQ: Wiping the database change history](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history#faq-wiping-the-database-change-history) Was this helpful? --- # The server logs | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs.md) . While the Debugger lets you to test and debug the current situation, server logs enable you to explore issues in the past. This is useful both to check the results of changes that you made during testing, and for looking at what actually happened when a live user experienced an issue. Keep in mind that the server logs for **Development** and **Live** are separate. If you have created any custom branches using Version control, they are still contained within the Development and Live environments. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#accessing-the-logs) Accessing the logs ------------------------------------------------------------------------------------------------------------------------------------------------------- To access the server logs, do the following: * Click on the _Logs_ tab * Then the _Server logs_ section ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FjnIuwY0YusBT4iOZOXpj%252Fserver-logs%25402x.png%3Falt%3Dmedia%26token%3D7078793b-d622-4575-8cdf-20b7a23c235e&width=768&dpr=3&quality=100&sign=fb7a0e89&sv=2) [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#searching-logs) Searching logs ----------------------------------------------------------------------------------------------------------------------------------------------- The logs let you search for log entries with the following constraints * **Start/end time** lets you enter a time range for the event(s) you are looking for. * **User email** lets you constrain the search by the user who initiated the events. * **Contains** is a freetext field that lets you search for the workflow label to narrow it down further. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#more-filter) More filter In addition to the main filters above, clicking the _Advanced_ button gives you access to an extended list of filters. * Started running workflow * Action condition failed * Autobinding operation * Scheduled task completed * Sending email failed * Event condition passed * Finished running action * Plugin server side output * HTTP request * Event condition not passed * Finished running workflow * Plugin server side error * HTTP response * Running action * Workflow error * Scheduled task to run Combined, these tools create a comprehensive toolset to refining your search and zeroing in on the issue If you are searching through an app with a lot of activity, searching through logs can be time-consuming and potentially time out if the amount of data is too big. If you experience this, we recommend **narrowing down the timeframe** in which to search. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#zooming-in-on-a-workflow) Zooming in on a workflow Each workflow consists of several steps in the log: * one for the event: * one for the condition on the event (even if empty) * one for each action step. Unless you are very specific with your constraint, most log searches will return a long list of results (especially if you are searching in an app with active users). To isolate one workflow and see all the steps logged in that workflow, you can use the _Zoom on this workflow_ feature: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FMpYYrFwqamRcA7SErdvt%252Fzoom-workflow%25402x.png%3Falt%3Dmedia%26token%3D1c88e839-5daf-4774-a94b-3f3073a8b6e8&width=768&dpr=3&quality=100&sign=a05b400&sv=2) _Zoom on this workflow_ lets you isolate a workflow to make it easier to follow all the associated steps. Click image to enlarge. The Server Logs section in the Logs tab allows searches of the log of server-side actions, such as send email or change data, executed when users interacted with the app. Search for a particular user by email or ID, within certain dates, or specific keywords. Note that server logs depend on the version of your app, so you should make sure you are focusing on the version where the issue was reported (Live versus Development). To search logs, you need to define the starting and the ending dates of the search. Searching logs can take some time, and the Editor will display entries as they arrive. When you already see some results and scroll down, the editor will fetch more entries (and the caption of the search button will change according to the situation). **If your app has a lot of traffic, you'll see a lot of logs.** It is useful to narrow down the search by using some search criteria. The most common criteria you can use when searching for logs is picking the type of events you're interested in. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-M5smrJkMfjcu6xQRWw4%252F-M5smwO999JyiJW9wJZf%252FDesktop%25202017-03-17%2520at%25205.51.57%2520PM.png%3Fgeneration%3D1587943318056476%26alt%3Dmedia&width=768&dpr=3&quality=100&sign=5badf7b5&sv=2) * Workflow starts: shows all initiated workflows that run on the server, whether the condition is met and the workflow is executed, or not. * Passed events: shows all workflows that run after the condition evaluated to yes. * Non-passed events: shows all workflows that didn't run after the condition evaluated to no. This is useful as you try to debug something that _didn't_ happen. * Actions: only shows actions, and not the events that led to this action's execution. * Errors: shows server-side errors that happened when executing a workflow. For instance, a credit card failure, or a send email failure. This will be especially useful to diagnose issues. Tip If your app has a lot of activity, chances are it has a _lot_ of logs. If you're searching through the logs and the query is slow or timing out, try narrowing the time window of your search. When you search for logs, if you have more information about the problematic workflows, you can narrow down the search even more by searching for specific users and terms. The first input lets you enter a user's email or a user's unique ID. When this is filled, the search will only return workflows started by this user. The last box lets you type a string that you want to search for. If an action has a property that evaluated to some text and if you search for this text, the workflow will be retrieved. For instance, if you know an email was sent with the text 'Boston' in it, searching for 'Boston' will return the Send Email action. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#looking-at-the-results) Looking at the results --------------------------------------------------------------------------------------------------------------------------------------------------------------- After the results are retrieved, they will appear in descending order, with the most recent ones displayed first. For each entry, you will see the following details: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FTaKuPfxfUmZW0TK8xWqg%252Fzoom-workflow%25402x.png%3Falt%3Dmedia%26token%3D624989c7-e4a7-4d18-ba78-14301810bda8&width=768&dpr=3&quality=100&sign=b9b5d7a8&sv=2) 1. **Action/event name**: this name reflects the label on the action/event of the workflow. 2. **User email:** the email of the user who initiated the workflow. If the user isn't signed up, the field will show _Anonymous user_) 3. **User ID:** the unique ID of the user who initiated the workflow. 4. **Timestamp:** the date and time of the logged event/action 5. **Message/properties**: properties for this event/action, or any error message(s) [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#following-editor-links) Following editor links --------------------------------------------------------------------------------------------------------------------------------------------------------------- Clicking on a step in the Log takes you directly to the workflow editor for the relevant event or action in that log entry: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F0ga02GUcwFvmxM0bx8f0%252Fgo-to-workflow-from-log%25402x.png%3Falt%3Dmedia%26token%3D9be028f7-9e49-4550-9bee-97046633cf2c&width=768&dpr=3&quality=100&sign=94b9535b&sv=2) Clicking on an event or action takes you directly to the relevant entry in the workflow editor. Last updated 2 years ago Was this helpful? * [Accessing the logs](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#accessing-the-logs) * [Searching logs](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#searching-logs) * [More filter](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#more-filter) * [Zooming in on a workflow](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#zooming-in-on-a-workflow) * [Looking at the results](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#looking-at-the-results) * [Following editor links](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs#following-editor-links) Was this helpful? --- # Hard limits | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits.md) . This article focuses on Bubble's **hard limits**. Hard limits are fixed boundaries that cannot be exceeded, such as the number of minutes a workflow will attempt to finish before it's terminated. Some hard limits can be increased by upgrading to higher pricing plans. For soft limits (flexible boundaries that can be exceeded in but may impact performance or stability) check out our [general article on performance and scaling](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling) . Plugins and plugin builders[](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#plugins-and-plugin-builders) The limitations discussed in the article are equally applicable to tasks performed by plugins. If you're developing plugins, you should familiarize yourself with these limits to prevent any issues for your users. Like all development frameworks and server systems, Bubble comes with its own set of capabilities and limitations. While we are working hard to make a platform that is flexible and versatile enough to reliably handle as wide a range of applications as possible, we also want to be as transparent as we can with our developer community as to what kind of limitations you might experience. This article will attempt to highlight known limitations and issues that should be taken into consideration when you are evaluating Bubble for your project. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#understanding-the-system-limits) Understanding the system limits ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- An app reaching Bubble’s hard limits is fairly rare, but as a developer it can still be useful to know about them to be able to recognize and debug them should they occur. They can aid in the planning and development of your app, but it’s worth nothing that understanding and predicting how they can affect your app can be a bit more complicated. The limits offer insight into the system's absolute limits and can be valid in one-off cases, but they will be less accurate in predicting the app's performance under varying conditions and workloads. For instance, if a Do a search for times out after a maximum limit of 10 seconds, it does not imply that a search that takes 3 seconds to complete is always "safe" in all situations. For example, a 3-second search that’s happening simultaneously for a million users will still, in aggregate, become very taxing for your app. At that scale, it would be best to redesign the search to complete faster. While hard limits will kick in in rare situations, it’s also important to keep in mind the combination of everything you’ve built your app to do. Hard limits can clarify why a process has stopped due to reaching a time limit and serve as a reminder that a resource-intensive process will eventually reach its limit. However, this information must be incorporated into an overarching strategy to ensure that the app’s activity remains at sustainable levels that allows your app to scale safely. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#database) Database ------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#number-of-custom-data-types) Number of custom data types Any app can have up to 1,000 custom data types. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#sorted-searches) Sorted searches Searches that have a sorting applied (or with the _:sorted_ operator added to the expression) will return a list of maximum 50,000 things. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#text-fields) Text fields A single text field saved in the database has a hard limit of **10 million characters**. Keep in mind that this includes characters like spaces and BBCode/HTML formatting. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#thing-size) Thing size The total size of data stored in one thing has a hard limit of **20 MB**. This refers to data stored in the thing itself, and not associated data such as files and images. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#deleting-references-to-a-thing) Deleting references to a thing Sometimes when you delete a thing in the database, Bubble needs to update other records to reflect that the thing has been deleted. For example, a _user_ might be connected to other records because they are referenced in the _Created by_ field. This can lead to a seemingly simple operation becoming more complex and resource-demanding. If the number of referenced records exceeds 100,000 records you may start to experience that referenced records are not properly updated, and by 1,000,000 there's a significant chance that the process will lead to unexpected database errors. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#storing-a-list-of-things) Storing a list of things Storing a list of database things on another thing (such as User's Tasks) has a **hard limit of 10,000 records**. Note that long lists can start to affect performance at a lower number, depending on how much data the records are holding and what kind of processing you apply. In many cases, using _Do a search for_ instead of storing long lists will be more efficient. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#csv-upload) CSV Upload CSV files uploaded in the Bubble editor or in your app have a hard file size limit of **5GB.** However, several major browsers do not reliably allow uploads bigger than 2 GB, making this the practical limit for most users. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#file-upload) File Upload Files uploaded in the Bubble editor or in your app have a hard file size limit of **5GB.** However, several major browsers do not reliably allow uploads bigger than 2 GB, making this the practical limit for most users. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#design-and-logic) Design and logic ---------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#workflow-timeout) Workflow timeout Workflows that take more than **300 seconds (5 minutes)** will time out. Note that other processes running simultaneously can lead to Bubble throttling your app to maintain stability if your app comes close to maxing out its capacity. This can sometimes lead to workflows timing out because they are slowed down. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#number-of-elements-and-events-actions-on-a-page) Number of elements and events/actions on a page There's a hard limit of **10,000 combined total of elements, events and actions** on a single page. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#length-of-url) Length of URL Bubble doesn't have a maximum URL lengths, but to ensure browser compatibility you should stay within **2,000 characters**. We generally recommended keeping URLs as short as possible for usability and SEO purposes. URL parameters are included in the character count. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#schedule-api-workflow-on-a-list) Schedule API workflow on a list The maximum number of workflows that can be scheduled using the Schedule API workflow on a list action is as follows: List Limit Unsorted list 100,000 Sorted list 50,000 If you attempt more than this, only the number of workflows up to the limit will be scheduled #### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#enterprise-plan-with-dedicated-instance) Enterprise plan with dedicated instance The Enterprise plan with a dedicated instance doesn't have a hard limit on Schedule API workflow on a list, meaning you can schedule more than the numbers stated above. The actual limit as to how much Bubble can process, and the time it takes to do so, will vary based on the server configuration, general load and the size (in bytes) of the workflow parameters. Please visit our [Support center](https://bubble.io/support) to get in touch with a member of our Support team if you have questions regarding dedicated server instances. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#database-trigger-events) Database trigger events If you have more than 20 database triggers that kick off at once, the remaining triggers will be scheduled to protect your app's infrastructure from consuming too much memory. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#integrations) Integrations -------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#api-connector-responses) API Connector responses There's a hard limit of **50 MB** for responses to an outgoing API call made with the API Connector or a plugin. Exceeding the limit will generate an error in the logs: "response too large". ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#headers-in-api-calls) Headers in API calls The headers in API calls can have a maximum total size of 8,000 characters ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#keys-in-api-calls) Keys in API calls The keys in an API call can have a maximum total size of 20,000 characters. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#bubble-api-requests) Bubble API requests The Data API and Workflow API handle a set number of requests per minute depending on your plan: * Starter: 15 000 * Growth: 25 000 * Team: 35 000 We have additional rate limits enforced to protect our cluster from malicious attacks. These are subject to change and are unlikely to affect legitimate usage. If you have questions please [open a support ticket](https://bubble.io/contact) . #### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#legacy-plans) Legacy plans Note that if you are on Bubble's legacy plan, requests are rate-limited by default to 1,000 requests/minute per application, collectively between Live and Development. A rate-limited request will return an HTTP 429 error. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#recursive-limits-when-using-the-api-connector) Recursive limits when using the API Connector For recursive workflows that are triggered via the [_Schedule API workflow_](https://manual.bubble.io/core-resources/actions/custom#schedule-api-workflow) action, you can apply custom depth limits to avoid infinite recursion. Article: [Infinite recursion protection](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection) When using the API Connector to recursively call a backend workflow, Bubble enforces limits to prevent infinite loops. These limits differ depending on the type of recursion: **Direct API Connector recursion** This occurs when your app calls its own backend workflow through the API Connector. * **Limit:** Maximum depth of 3 **Indirect API Connector recursion** This occurs when your app calls another app’s backend workflow, and that app calls back to yours—creating a loop across apps. * **Limit:** Maximum depth of 10 These recursion limits are internal system constraints and cannot be configured or overridden. Last updated 22 days ago Was this helpful? * [Understanding the system limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#understanding-the-system-limits) * [Database](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#database) * [Number of custom data types](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#number-of-custom-data-types) * [Sorted searches](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#sorted-searches) * [Text fields](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#text-fields) * [Thing size](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#thing-size) * [Deleting references to a thing](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#deleting-references-to-a-thing) * [Storing a list of things](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#storing-a-list-of-things) * [CSV Upload](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#csv-upload) * [File Upload](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#file-upload) * [Design and logic](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#design-and-logic) * [Workflow timeout](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#workflow-timeout) * [Number of elements and events/actions on a page](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#number-of-elements-and-events-actions-on-a-page) * [Length of URL](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#length-of-url) * [Schedule API workflow on a list](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#schedule-api-workflow-on-a-list) * [Database trigger events](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#database-trigger-events) * [Integrations](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#integrations) * [API Connector responses](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#api-connector-responses) * [Headers in API calls](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#headers-in-api-calls) * [Keys in API calls](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#keys-in-api-calls) * [Bubble API requests](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#bubble-api-requests) * [Recursive limits when using the API Connector](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits#recursive-limits-when-using-the-api-connector) Was this helpful? --- # Overview | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/overview.md) . The security dashboard offers a comprehensive suite of tools to audit and monitor your app. In this article, we’ll go over the available features, and link to more in-depth content for each section. [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#security) Security ---------------------------------------------------------------------------------------------------- The security dashboard equips you with two different tools for performing tests on demand. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#issues-explorer) Issues explorer The Issues explorer runs a test across a range of different categories and ranks them by criticality. Each of the categories are explained in-depth in the sub-articles in this series. Article: [The issues explorer](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer) [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#privacy-rules-checker) Privacy rules checker ------------------------------------------------------------------------------------------------------------------------------ The privacy rules checker quickly shows which of your data types are publicly accessible. Article: [The privacy rules checker](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/privacy-rules-checker) [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#automated-tests) Automated tests ------------------------------------------------------------------------------------------------------------------ Automated tests enable you to run security tests automatically. Article: [Automated tests](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/automated-tests) [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#resources) Resources ------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#scheduled-deployments) Scheduled deployments Bubble allows you to schedule deployments in advance, so your app is deployed automatically at a specific date and time. This is useful for coordinating releases or planning updates outside of working hours. **Bubble deployments and issue checker:** Scheduled deployments will proceed even if there are unresolved issues in the editor. This means it's important to review and fix any issues before scheduling a deployment, as they won't block the process or trigger a warning automatically. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/overview#alerting) Alerting The **alerting** feature allows you to notify collaborators when key events occur in your app. You can send alerts via email or trigger a custom webhook when your app is deployed to the live environment Use this feature to keep your team informed during deployment or when working across multiple . Last updated 22 days ago Was this helpful? * [Security](https://manual.bubble.io/help-guides/security/security-dashboard/overview#security) * [Issues explorer](https://manual.bubble.io/help-guides/security/security-dashboard/overview#issues-explorer) * [Privacy rules checker](https://manual.bubble.io/help-guides/security/security-dashboard/overview#privacy-rules-checker) * [Automated tests](https://manual.bubble.io/help-guides/security/security-dashboard/overview#automated-tests) * [Resources](https://manual.bubble.io/help-guides/security/security-dashboard/overview#resources) * [Scheduled deployments](https://manual.bubble.io/help-guides/security/security-dashboard/overview#scheduled-deployments) * [Alerting](https://manual.bubble.io/help-guides/security/security-dashboard/overview#alerting) Was this helpful? --- # Terminology: Version control | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology.md) . This page contains short descriptions of the version control terminology. For a more comprehensive guide on version control works or the core reference of all the available features, see the links below: Article: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Reference: [Version control](https://manual.bubble.io/core-resources/bubbles-interface/version-control-deployment) The terminology used by Bubble's version control system may not be immediately apparent or easy to grasp at first. This article contains a list of the different terms used and may be helpful as you get to know how the system works. At the bottom of the page you will find [terminology that has changed](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#legacy-terminology-and-replacements) from the legacy system. [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#terminology) Terminology ---------------------------------------------------------------------------------------------------------------------------- Term Definition base branch The branch that you want to merge changes into branch tree The visualization that shows you where a branch came from and how it relates to other branches child branch A branch that has a parent branch; a child branch can also be a parent branch conflict Conflicts arise during the merge process when the base branch and the source branch each changed the same thing (in different ways) since the last time the two branches were in sync conflict resolution Conflict resolution is the process of resolving conflicts. The conflict resolution window organizes conflicts by page and gives you the option to resolve all conflicts in favor of one branch on a page-by-page basis. custom branch Apps on the [higher plans](https://bubble.io/pricing/compare) can have one or more custom branches deploy, deployment To deploy a branch is to push changes to Live. Only the Main branch and the hotfix branches can be deployed to Live. Development environment The development environment contains Main, any custom branches, and hotfix branch environment Environments contain branches. There are two environments: live and development. The environment is defined by the database that it uses (i.e., the live environment uses the live database, while the development environment uses the development database). hotfix branch The hotfix branch is the only branch that can branch off of Live. Only one hotfix branch can exist at a time. While a hotfix branch exists, Main cannot be deployed to Live. Hotfix is available on [higher plans](https://bubble.io/pricing/compare) . in sync When two branches are in sync, there are no conflicts that would be generated from merging the two branches Live Live is the version of your app that lives on the internet for users to interact with Live environment The live environment contains Live Main branch All apps have a Main branch. Main is the only branch that can be deployed to Live (aside from hotfix). Main sits at the very top of the branch tree hierarchy. merge, merging The process of integrating changes from the source branch into the base branch parent branch A branch that has child branches branching off of it; a parent branch can also be a child branch resolve conflicts To resolve conflicts that arise during the merge process, you must select which change to favor restore To restore is to return to a past version of a branch by using the savepoint feature or by entering a custom date/time savepoint Savepoints are automatically created in the base branch when you deploy to Live, start a merge, finish a merge, cancel a merge, or right before you restore your branch. Custom savepoints are savepoints that you can manually create at any time. savepoint retention window An app’s savepoint retention window dictates how far back you can restore any one of your branches source branch Refers to the branch that is the source of changes that you want to merge into the base branch sync To sync two branches is to merge them for the purposes of bringing changes in Live or Main into the base branch to branch, branching To create a branch off of another branch version control The system for tracking and managing changes to your app. [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#legacy-terminology-and-replacements) Legacy terminology and replacements ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you have been using Bubble for some time you may be familiar with the existing terminology that surrounded the previous version control. The following terms have been removed or replaced Term Definition Adding changes from one version to another Now "merging" Development Now "Main branch" live version Now "Live" custom version Now "custom branch" Last updated 10 months ago Was this helpful? * [Terminology](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#terminology) * [Legacy terminology and replacements](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#legacy-terminology-and-replacements) Was this helpful? --- # Transitioning from the legacy version control | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning.md) . The new version control system introduces new terminology. We have compiled a list of the terminology of the new system, as well as the terms that are no longer used: Article: [Version control terminology](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology) The transition process described below is only relevant to existing apps with multiple development versions. If version-test is your only development version, your app will automatically be upgraded to the new version control system, and version-test will become the Main branch The legacy version control system had a linear approach to managing application changes, allowing separate versions to be created and worked on in isolation. However, this method had its limitations, especially when it came to collaboration and managing the development of major new features. The new branch-based system offers a more flexible, powerful, and collaborative approach to managing app development. This article guide will give you an overview of how to transition from the old Bubble version control system to the new system. Throughout the guide, we will discuss key concepts, such as branches, merging, and managing conflicts, and provide step-by-step instructions to help you get started with the new system. [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#upgrading-to-the-new-version-control) Upgrading to the new version control -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you have at least one custom version in the legacy version control system, you will be asked to opt-in to the new system. **Note:** The upgrade to the new version control system is permanent and cannot be undone. You will find the button to upgrade when you click the current version control menu bar link in the upper right corner of the Bubble editor: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FPFiiWLTAiDV0LVxzOgJ9%252Fupgrade-to-new-version-control.png%3Falt%3Dmedia%26token%3Daa7fe064-2e23-4956-89fb-9a149d29b909&width=768&dpr=3&quality=100&sign=fdfecdd1&sv=2) [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#general-advice) General advice ------------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#versions-are-now-branches) Versions are now _branches_ A key aspect of the new version control system is that what used to be called _versions_ are now called _branches_. This new terminology better describes how the system works, as we have moved away from the linear systems of separate versions into a parent-child based "tree" of branches that can be added and removed as needed. This helps you work not only on new features, but it allows you to further separate development on those features into child branches that can later be merged upwards into the parent. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#no-data-or-ongoing-work-will-be-deleted-when-you-make-the-transition) No data or ongoing work will be deleted when you make the transition Before we dive into the process of transitioning to the new branch-based system, it's important to clarify that the new system is compatible with any existing versions you have. In other words, you will not lose your versions when you choose to activate the new version control system. It may still be useful to clean out your versions ahead of upgrading and to get to know our [recommended best practices](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices) . This helps you get a clean start and set up a structure that makes sense for your team. [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#transition-scenarios) Transition scenarios ------------------------------------------------------------------------------------------------------------------------------------------------ We’ll now cover two different scenarios that require slightly different steps to getting up and running smoothly. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#scenario-1-your-app-is-on-an-agency-plan-professional-plan-production-plan-or-dedicated-plan-and-you) Scenario 1: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and your last deploy to Live was made from _version-test_ When you turn on new version control, you’ll notice the brand new UX and that version-test is now the Main branch. * Any custom versions you created previously will show up below the Main branch. * Any in-progress work remains undisturbed * The new **Main branch** (formerly the _development version_ or _version-test_) is the only branch that can be deployed to Live. The hotfix branch can also be deployed, but they are meant for quick bug only fixes in the Live environment and block other development work until the hotfix is deployed or deleted. If your last deploy to Live was made in the **development version** (a.k.a. version-test), and no changes were made in development since that deploy, you should be able to proceed as usual as your Main branch is up to date with Live. If your last deploy to Live was made in version-test, and there is in-progress work since the last deploy that you want to save, create a new branch off of Main. This new branch will be a mirror image of the old development version. You can then reset your Main branch to match Live by using the “Reset to Live” feature in the _More actions_ dropdown in the top right of the version control panel. This will ensure that Main is a carbon copy of the Live branch so that any future deploys will proceed smoothly. Then, when you are ready, you can merge any changes into Main and deploy those changes to Live. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#scenario-2-your-app-is-on-an-agency-plan-professional-plan-production-plan-or-dedicated-plan-and-you) Scenario 2: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and Your last deploy to Live was made from a _custom version_ When you turn on new version control, you’ll notice the brand new UX and your development version will automatically turn into the Main branch. Any custom versions you created previously will show up as branches below the Main branch. * Any in progress work remains undisturbed * The **Main branch** is the only branch that can be deployed to Live. Hotfix branches can also be deployed, but they are meant for quick bug fixes in the Live environment and block other development work until the hotfix is deployed or deleted If your last deploy was made in a **custom version**, there is a good chance that version-test does not have the same changes that Live has - which will be required to deploy anything to Live in the future. Since version-test is now Main, and Main is the only branch that can be deployed to Live, you’ll want to move some things around to adjust to this new flow. * If there is any in-progress work in version-test (now Main) that you want to save, create a new branch off of Main. This new branch will be a mirror image of the old development version. * Navigate to the Main branch and reset the Main branch to match Live by using the “Reset to Live” feature in the More actions dropdown in the top right of the version control panel. This will ensure that Main is a carbon copy of the Live branch so that any future deploys will proceed smoothly. * For any work in a custom branch that is ready to be deployed, first sync that custom branch with Main (using the button in that branch’s version control panel) to make sure that branch is up to date with Main/Live and then merge that branch into Main. When the branch has been merged, you can deploy Main to Live. * For any new work, create a custom branch off of Main and use that new branch for any development work. When you are ready to merge that work and deploy to live, sync that custom branch with Main (using the button in that branch’s version control panel) to make sure that branch is up to date with Main/Live and then merge that branch into Main. When the branch has been merged, you can deploy Main to Live. Good luck with the transition! To further get to know the new version control system, we recommend reading our introductory article and study the new terminology. Article: [Version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control) Article: [Version control terminology](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology) (direct link: [legacy terms that have been updated](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology#legacy-terminology-and-replacements) ) Article: Legacy version control documentation Last updated 3 years ago Was this helpful? * [Upgrading to the new version control](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#upgrading-to-the-new-version-control) * [General advice](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#general-advice) * [Versions are now branches](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#versions-are-now-branches) * [No data or ongoing work will be deleted when you make the transition](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#no-data-or-ongoing-work-will-be-deleted-when-you-make-the-transition) * [Transition scenarios](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#transition-scenarios) * [Scenario 1: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and your last deploy to Live was made from version-test](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#scenario-1-your-app-is-on-an-agency-plan-professional-plan-production-plan-or-dedicated-plan-and-you) * [Scenario 2: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and Your last deploy to Live was made from a custom version](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning#scenario-2-your-app-is-on-an-agency-plan-professional-plan-production-plan-or-dedicated-plan-and-you) Was this helpful? --- # Native mobile app | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app.md) . [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#getting-started-with-mobile-app-publishing) Getting Started with Mobile App Publishing ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Publishing a native mobile app is a bit different than publishing a web app. Deploying a web app through Bubble means clicking the Deploy button, while releasing a native mobile app requires additional steps involving third-party platforms: the Apple App Store and Google Play Store. Each store has its own setup processes, requirements, and guidelines that must be fulfilled independently of Bubble. This guide covers each step you'll need to follow to successfully publish your native mobile app, including understanding essential terminology and navigating the approval processes for both the Apple App Store and Google Play Store. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#overview-of-the-publishing-process) Overview of the publishing process --------------------------------------------------------------------------------------------------------------------------------------------------------- Turning your Bubble app into a native mobile experience involves several key steps, from building your app with Mobile views, to the initial setup for the App Store and Google Play Store, testing and finally submitting for approval. To begin, we will get familiar with the differences between distributing on the web vs mobile, and how mobile publishing works step by step. You will be going back and forth between your app, and your store(s) of choice throughout this process, so keep your tabs organized as you begin. First, with Mobile development, it’s important to recognize that _publishing_ is **different** from deploying. Publishing your app involves several steps: 1. Preparing necessary assets like icons, descriptions, screenshots, privacy policy, etc. 2. Configuring your Bubble app for mobile deployment 3. Registering developer accounts with Apple and or Google 4. Deploying to the app stores 5. Testing your build 6. Submitting your app for review 7. Publishing and making it available for users [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#understanding-deployment-for-mobile) Understanding deployment for Mobile ----------------------------------------------------------------------------------------------------------------------------------------------------------- Deploying and publishing are often used interchangeably, but they have distinct meanings. Traditionally, deploying in a web context means pushing updates live from your main branch, making them instantly available to users. In mobile, this concept applies less directly because updates often require a new build. A **build** is a packaged version of your app that is required for submission to the App Store or Google Play Store that we will learn more about soon. Over-the-Air (OTA) updates allow you to make some changes without a **full** app store resubmission, though most updates still require a new build file that must be published to the App Store or Google Play. In short, deployment in mobile development is preparing your app for release. True availability happens only after it’s published. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#ios-vs.-android-key-differences-in-submission-and-approval) iOS vs. Android: Key Differences in Submission and Approval ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When publishing a mobile app, it's important to be aware of the costs and differences between iOS and Android, especially regarding approval processes, developer accounts, and compliance requirements. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#developer-account-requirements) Developer account requirements To publish an app, you must sign up for a developer account for each platform: * **Apple Developer Program:** Requires an annual fee of $99 and identity verification. * **Google Play Console:** Requires a one-time registration fee of $25. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#approval-process-apple-vs.-google) Approval process: Apple vs. Google Once signed up, and ready to submit, Apple and Google have distinct review and approval workflows: * **Apple App Store:** Stricter guidelines with a manual review process, leading to longer approval times (typically 1–3 days, but may take longer if revisions are required). * **Google Play Store:** Generally more lenient on design quality and content restrictions. Review includes both automated and manual steps, with approval timelines that are often similar to Apple’s. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#key-compliance-requirements) Key compliance requirements Both platforms enforce specific policies to ensure apps meet security and content guidelines: * **Privacy Policy**: A publicly accessible page detailing how user data is collected and used. * **Permissions**: Apps must justify the use of sensitive data (e.g., location, camera, contacts). * **Content Guidelines**: Apps must not include misleading content, harmful functionality, or policy violations. By preparing for these requirements in advance, you can avoid common rejections, reduce delays, and ensure a smoother submission process. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#understanding-builds-ota-updates-and-live-versions-for-deployment) Understanding Builds, OTA Updates, and Live Versions for deployment ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Here’s a key glossary of concepts to understand before signing up for a developer account. Familiarizing yourself with these will give you a solid foundation in mobile development and help you navigate the publishing process when you're ready to launch your app on the app store. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#what-is-a-build) What is a Build? A build is a packaged version of your app that is required for submission to the App Store or Google Play Store. Each build is assigned a version number, following a semantic format (e.g., 1.0.0 → 1.1.0 → 1.2.1). Version Type Example Purpose Requires App Store / Play Store Resubmission? Major 1.0.0 → 2.0.0 Significant updates, breaking changes, or major new features Yes Minor 1.0.0 → 1.1.0 Smaller feature additions or improvements that maintain compatibility Yes Patch 1.0.0 → 1.0.1 Bug fixes, security updates, or minor tweaks Yes Key facts about builds: * Necessary for first-time app submission and for major updates. * Each build requires App Store & Play Store approval before going live. * Users must download a new build from the store to receive updates. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#how-ota-over-the-air-updates-work) How OTA (Over-the-Air) updates work OTA updates allow you to deliver changes to the latest live version of your app without submitting a new build to the app store. These updates function similarly to web app deployments—users will see the changes the next time they open the app. To reiterate OTA updates only are sent to the latest built version, even if that built version is not in the app store. Key facts about OTA updates: * Instant update: Users on the latest version get the update without needing to download anything and without the developer needing to submit a new version of the app. * Note: OTA updates, don’t have version numbers. * Great for bug fixes and content changes that don’t require new native functionality. * Unlimited OTA updates can be applied to the latest build. * No resubmission needed to the App Store or Google Play. ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#differences-between-ota-updates-and-builds) Differences between OTA updates and Builds Feature OTA Updates Builds Approval Needed Typically deploys within 5-10 minutes Yes (App Store / Play Store) User Download Required No Yes Use Case Bug fixes, content tweaks, minor UI improvements Major updates, new features, important security updates Deprecation Not automatically discontinued when multiple live versions are supported; must be deprecated manually Older builds remain unless removed ### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#what-is-a-live-version) What is a Live version? A live version refers to the version of your app that users are currently running on their devices. Each live version is tied to a specific build (what’s installed from the App Store, Play Store, or distributed via testing tools like TestFlight), and is connected to a version of your app’s backend (the server-side logic and data). **Key things to know:** * A live version is always tied to a specific build of your app. * OTA updates apply only to the latest built version, even if it hasn’t been submitted to the app store. * Bubble checks if the user's app is on a supported live version on app load. * Users on older builds will not receive OTA updates unless they update to the latest build. * When a user installs the app for the first time, or updates to a new build that includes an OTA, the OTA is applied immediately. This can add a small amount of time to the initial load (usually around one second), but it ensures that the user’s first experience with that build is seamless and doesn’t show the update screen. * If a user is already running a build and an OTA update becomes available, the update downloads in the background when the app is opened and is applied the next time the user re-opens the app. If the live build has been deprecated, the user will see the update screen, prompting them to apply the OTA on the next re-open. * Bubble supports multiple live builds running simultaneously, which means users on older builds can continue using your app without breaking — but you’ll need to manually manage and deprecate older versions over time. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#managing-version-support-and-deprecation) Managing version support & deprecation Supporting multiple versions ensures a smooth user experience, as not all users update their apps immediately. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#why-support-multiple-builds) Why support multiple builds? Supporting multiple builds ensures a smoother experience for your users — especially since not everyone updates their app right away. Bubble allows multiple live builds to run in parallel, giving you more flexibility and control over how and when users receive updates. * Users don’t update immediately: some users may stay on older builds for weeks (or longer), so it’s important that those builds continue to work correctly. * Testing before release: you may want to roll out and test a new build (via TestFlight or internal testing) before making it widely available in the App Store or Play Store. * OTA updates are build-specific: OTA updates only apply to the latest built version. If a user is on an older build, they won’t receive the update—so keeping older builds functional is essential. * Smoother user experience: requiring users to download a new version for every update can cause friction. Supporting multiple builds lets you avoid that for minor updates or bug fixes. App store delays: since store reviews can take time, keeping older builds live ensures your app remains usable while newer builds wait for approval. Deprecation tip: While Bubble supports multiple live builds, older versions are not deprecated automatically. You’ll need to manually deprecate any versions you no longer want users to access. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#bubbles-live-version-limits) Bubble’s Live version limits Bubble limits the number of concurrent live versions you can support, meaning you must manage updates carefully. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#best-practices-for-deprecating-old-builds) Best practices for deprecating old builds * Encourage updates: Use in-app messaging or push notifications to inform users of new builds. * Gradually phase out older versions rather than forcing instant updates. By understanding builds, OTA updates, and live version management, you can maintain a smooth deployment process and keep your app updated efficiently. Now that you have a better understanding around Mobile publishing and deployment, it’s time to learn how to publish step by step to iOS and Android. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#operating-system-compatibility) Operating system compatibility ------------------------------------------------------------------------------------------------------------------------------------------------- Our current version of React Native will support: * iOS devices running version 15.1 and later * Android devices running version 12 and later. Devices running unsupported OS versions are not guaranteed to work as expected. Please be aware that certain native features may only be supported by later OS versions as well. The oldest supported version will be noted per feature in the documentation. As we stay up to date with the latest versions, these versions are bound to change. Last updated 22 days ago Was this helpful? * [Getting Started with Mobile App Publishing](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#getting-started-with-mobile-app-publishing) * [Overview of the publishing process](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#overview-of-the-publishing-process) * [Understanding deployment for Mobile](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#understanding-deployment-for-mobile) * [iOS vs. Android: Key Differences in Submission and Approval](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#ios-vs.-android-key-differences-in-submission-and-approval) * [Developer account requirements](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#developer-account-requirements) * [Approval process: Apple vs. Google](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#approval-process-apple-vs.-google) * [Key compliance requirements](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#key-compliance-requirements) * [Understanding Builds, OTA Updates, and Live Versions for deployment](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#understanding-builds-ota-updates-and-live-versions-for-deployment) * [What is a Build?](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#what-is-a-build) * [How OTA (Over-the-Air) updates work](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#how-ota-over-the-air-updates-work) * [Differences between OTA updates and Builds](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#differences-between-ota-updates-and-builds) * [What is a Live version?](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#what-is-a-live-version) * [Operating system compatibility](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app#operating-system-compatibility) Was this helpful? --- # Publishing FAQ | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq.md) . [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#ios-apple-app-store-faq) iOS (Apple App Store) FAQ ---------------------------------------------------------------------------------------------------------------------------------------------------- How do I get started with submitting my Bubble Mobile app to the App Store?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#how-do-i-get-started-with-submitting-my-bubble-mobile-app-to-the-app-store) Start by reading the Bubble Mobile documentation. You’ll need an active Apple Developer account and to upload the required certificate and provisioning files through the Bubble interface. Bubble handles the rest of the build process for you. How do I generate the certificates required for iOS submission?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#how-do-i-generate-the-certificates-required-for-ios-submission) Use your Apple Developer account to generate the .p8 key. Follow Bubble's documentation to upload them correctly. How long does it take to publish to the App Store once everything is set up?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#how-long-does-it-take-to-publish-to-the-app-store-once-everything-is-set-up) Once your files are uploaded and settings are configured, it can take about 45 minutes to generate the build, upload it to TestFlight, and submit it for review. Can I update my iOS app without resubmitting it to the App Store every time?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#can-i-update-my-ios-app-without-resubmitting-it-to-the-app-store-every-time) Yes. If you're only changing content inside your Bubble app (text, workflows, UI), those updates happen instantly and don’t require a rebuild. You only need to resubmit if you're changing the native shell—such as the app icon, splash screen, or plugins. What are common issues users face when submitting to iOS?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#what-are-common-issues-users-face-when-submitting-to-ios) Several users have run into challenges during their iOS submission process. Here are the most common ones: #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#app-metadata-errors) App metadata errors: Apple has strict requirements for what needs to be included in your App Store listing. Users have encountered rejections due to: * Missing or improperly sized screenshots. * Incomplete descriptions or keywords. * Mismatched app names or bundle identifiers. * Choosing an incorrect app category or age rating. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#certificate-and-key-setup-confusion) Certificate and key setup confusion: While Bubble streamlines most of the native build process, you still need to manually generate and upload: * A `.p8` key from Apple (App Store Connect API key). * Associated App ID and bundle identifier. * Apple Developer Team ID. Users often get stuck if any of these values are incorrect or missing during the setup. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#misunderstanding-the-update-process) Misunderstanding the Update Process: It's common to assume that any change to your Bubble app requires a new app submission. However: * **Web-based changes** (like UI edits or logic updates inside Bubble) do not require resubmission. * **Native changes** (like splash screen, icons, or plugin settings) do require generating a new build and re-submitting through App Store Connect. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#waiting-for-apple-review) Waiting for Apple Review: After submission, there is often a 1–3 day waiting period for Apple to approve your app (or longer if it’s your first submission). Users sometimes mistake this delay for a technical issue. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#unexpected-rejections) Unexpected Rejections: Apple may reject your app for reasons that aren’t clearly explained. Common rejection reasons include: #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#privacy-policy-issues) Privacy policy issues. * Unsupported content. * Incomplete functionality (e.g., submitting a shell without full content). * * * [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#android-google-play-store-faq) Android (Google Play Store) FAQ ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Is Android publishing supported by Bubble Mobile?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#is-android-publishing-supported-by-bubble-mobile) Yes, you can publish directly to the Google Play Store. Bubble handles the build generation and provides an AAB (Android App Bundle) file that you can upload to Google Play. Can I submit to other Android stores (like the Amazon Appstore)?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#can-i-submit-to-other-android-stores-like-the-amazon-appstore) Not officially. Right now, Bubble only supports publishing to the Google Play Store. What steps are involved in submitting to Google Play?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#what-steps-are-involved-in-submitting-to-google-play) 1. Set up a [Google Play Developer account](https://play.google.com/console/about/). 2. Use Bubble to generate the Android build and download the `.aab` file. 3. Upload your build to the Google Play Console. 4. Complete the store listing (title, description, screenshots, privacy policy, etc.). 5. Submit for review. Do I need to resubmit the Android app for every Bubble change?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#do-i-need-to-resubmit-the-android-app-for-every-bubble-change) No. Just like iOS, if your updates are within the Bubble editor (like text, logic, or layout changes), you don’t need to rebuild. Only changes to the native build require a new submission. What are common issues users face when submitting to Google Play?[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#what-are-common-issues-users-face-when-submitting-to-google-play) While Android submissions tend to be more forgiving than iOS, there are still several common pitfalls Bubble users have run into: #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#incorrect-keystore-setup) Incorrect Keystore Setup: When generating the app build in Bubble, you need to download and securely store your keystore file. Common issues include: * Misplacing the keystore or password (you can't update the app without it). * Uploading a build signed with a different keystore (Google will reject it). * Confusion around which signing method to choose (Bubble signs it, but you may opt into Google Play App Signing). * Java is not installed #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#store-listing-rejections) Store Listing Rejections: Google requires a full store listing before publishing, and apps can be rejected or delayed if anything is missing or unclear. Frequent issues include: * No privacy policy listed (especially for apps with data input or login). * Missing or inappropriate screenshots. * Generic or incomplete app descriptions. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#permissions-disclosure-problems) Permissions Disclosure Problems: If your app uses sensitive permissions (like location, camera, or file access), Google Play requires clear justification and explanation in the store listing. Apps without this are often rejected. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#policy-violations) Policy Violations: Google has strict policies around content, ads, and functionality. Users have run into issues where: * Placeholder content or "coming soon" pages trigger rejection. * Your app links to websites that aren't mobile-friendly or that violate Google’s policies. * Apps require login but don’t offer a test account for reviewers. #### [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#apk-vs-aab-confusion) APK vs AAB Confusion: Bubble exports your app as an AAB (Android App Bundle) — the current required format for Google Play. Some users mistakenly expect an APK and run into trouble trying to upload it. Misunderstanding the Update Process: * Like with iOS, many assume any Bubble change means a new app submission. In reality: * Web-based changes inside Bubble (design, workflows, content) update instantly without needing a new app build. * Native build changes (icons, splash screen, plugin updates) do require generating a new build and uploading to Google Play again. [](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#common-publishing-setup-errors) Common Publishing Setup Errors ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Developer account setup[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#developer-account-setup) To publish your app to the Apple App Store or Google Play Store, you need to set up developer accounts outside of Bubble: **Apple App Store** Enroll in the Apple Developer Program. This requires identity verification and an annual membership fee. Ensure that your Apple account has the appropriate permissions—_Administrator_ or _Account Holder_—as this may be required for key-based authentication to work correctly. **Google Play Store** Create a Google Play Console account. You'll use this to manage your app’s presence on the Play Store. **Permissions and access tips** * Double-check that your **Key ID** and **Private Key** are connected to the correct Apple account and have the right permissions. * _Note_: Using a key tied to a user with only developer permissions (instead of admin) can cause build issues Common configuration issues in the Bubble editor[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#common-configuration-issues-in-the-bubble-editor) Even small formatting issues in your mobile settings can cause build failures. Here are some of the most common ones to check: * **App Scheme** Make sure the App Scheme is defined and doesn’t end with `://`. This value should be lowercase and alphanumeric (plus hyphens and periods if needed). * **Whitespace issues** Extra spaces in your app’s mobile settings can lead to build errors. Double-check all fields for trailing or unintended spaces. * **Keystore alias (Android)** This must be written in all lowercase letters. * **Bundle ID** Your Bundle ID must follow reverse domain format: `com.yourcompany.yourappname`. * **Device-specific settings** Ensure all required fields for iOS and Android builds are properly filled out—especially any that relate to native permissions or identifiers. * **iOS Private Key** When pasting your private key into the editor, include the full key contents, including the headers and footers. For example: External issues outside Bubble[](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#external-issues-outside-bubble) Some issues may relate to your external configuration or app history: * You're attempting to deploy to an **existing app** on the App Store that previously included support for iPads or used a custom wrapper. * You've **deleted a required distribution certificate or key** from your Apple Developer account. If so, a new certificate will need to be created and uploaded in the Bubble editor. Last updated 22 days ago Was this helpful? * [iOS (Apple App Store) FAQ](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#ios-apple-app-store-faq) * [Android (Google Play Store) FAQ](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#android-google-play-store-faq) * [Common Publishing Setup Errors](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq#common-publishing-setup-errors) Was this helpful? Copy -----BEGIN PRIVATE KEY----- [key content] -----END PRIVATE KEY----- --- # Issue explorer | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer.md) . The Issues Explorer scans for various types of issues. Refer to the article below to see which security checks are included with each plan. Article: [Security dashboard plan features](https://manual.bubble.io/help-guides/security/security-dashboard/security-dashboard-plan-features) The Issues Explorer is the security dashboard's generated security report, displaying potential vulnerabilities in a detailed, line-by-line format. The report is organized in a table format with the following columns: * **Type:** This column categorizes the type of vulnerability each row addresses, helping you quickly identify the nature of the issue. * **Item:** This column specifies the exact part of your app to which the vulnerability applies, such as a particular data type or an app setting. * **Severity:** This shows the security dashboard’s assessment of the vulnerability’s importance, rating each as low, medium, or high. This rating helps prioritize which vulnerabilities may require the most immediate attention. * **Affected branches:** This shows the app branch(es) to which the issue applies. * **Assigned:** This optional setting lets you designate a specific team member to investigate and address the issue. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#filtering-issues) Filtering issues At the top of the issue explorer, you’ll find different filters to help you narrow down specific issues that you’d want to focus on. The following filters can be applied: * **Location:** This lets you specify where in your app a category of issues occurs. For example, you can choose to show only issues related to APIs or the Database. * **Branch:** This lets you filter issues by a specific branch * **Assigned:** This lets you show only issues assigned to a specific user. * **Filters:** This lets you assign more complex filters, such as whether or not an issue is resolved, its type, or its severity. Note that changing the filters on this top row doesn’t change or resolve any issues, but only filters which are displayed in the list. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#revealing-issue-details) Revealing issue details Clicking on each row of the issues explorer reveals more information about that specific issue. This provides the following additional information: **Actions**: * **Ignore for 2 days:** this lets you exclude the issue from the current scan and scans within the next two days. * **Ignore for 7 days:** this lets you exclude the issue from the current scan and scans within the next week. * **Ignore forever:** this lets you exclude the issue from all future scans. * **Issue description**: The issue description gives you a more in-depth explanation of what exactly the issue is about, and can point you towards a recommended fix See also [Issue details](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-details) . * **History**: The history tab gives you a timeframe of when the issue was first revealed, what actions have been taken on it, and when it’s been resolved or reappeared. [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#test-settings) Test settings ----------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#privacy-ratings) Privacy ratings You can rate the privacy level of pages and data types to help the security dashboard identify which parts of your app—both pages and database content—should be treated as sensitive. * Article: [Pages](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#pages) * Article: [Data types](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#data-types) ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#configure-versions) Configure versions The Configure Versions setting controls which branches are included in security tests. By default, only the Live and Main branches are tested. To include other branches, make sure to update this setting. Article: [Configure versions](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#configure-versions) [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#issues) Issues --------------------------------------------------------------------------------------------------------------------- The Security Dashboard highlights a variety of issues related to your app’s security. For a detailed explanation of each issue—including what it means, what triggers it, and how to resolve it—refer to the [Issue details article](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-details) . To learn which security checks are available with each Bubble plan, see the [Security Dashboard Plan Features article](https://manual.bubble.io/help-guides/security/security-dashboard/security-dashboard-plan-features) . Last updated 22 days ago Was this helpful? * [Filtering issues](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#filtering-issues) * [Revealing issue details](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#revealing-issue-details) * [Test settings](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#test-settings) * [Privacy ratings](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#privacy-ratings) * [Configure versions](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#configure-versions) * [Issues](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer#issues) Was this helpful? --- # Test settings | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings.md) . **Running your first test:** if you are accessing the security dashboard for a specific app for the first time, you may need to run an initial test before you have access to all settings. The security dashboard allows you to specify which parts of your app you want to focus on. The settings are divided into three fundamental components in Bubble: branches, pages, and data types. [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#accessing-security-dashboard-test-settings) Accessing security dashboard test settings -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To access the settings, click the gear icon in the upper right corner of the security dashboard. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FEOKWeBIwx9BTwPMTmuIS%252Fchange-test-settings-security-dashboard-bubble%25402x.png%3Falt%3Dmedia%26token%3D7e39c410-51e5-41bf-967e-65fe013bec1f&width=768&dpr=3&quality=100&sign=17441611&sv=2) [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#test-settings) Test settings ---------------------------------------------------------------------------------------------------------------------------------- Settings applied in the _Test settings_ popup also apply to automated tests. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#selected-branches) Selected branches If you work across multiple branches, you can choose which branch or branches the tests should run on. Running a security test on just one branch helps you focus on the version of your app that actually matters right now—typically the branch that’s about to be merged or released. It reduces noise from in-progress work on other branches, makes results easier to interpret, and saves time and resources by scanning only branch or branches that are relevant for your next deployment. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FyWL8VIVXvhL5avJz01v5%252Ftest-settings%25402x.png%3Falt%3Dmedia%26token%3D994d9f48-c260-4ff9-b2ad-8c20e09587f2&width=768&dpr=3&quality=100&sign=f0252edc&sv=2) In the example above, the security test will only run on the main branch, and not on Live. To add or remove a branch, simply check or uncheck the box next to its name. ### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#selected-pages-and-data-types) Selected pages and data types You can also select which page(s) and data type(s) are included in the test. If a page or data type is intentionally public, or doesn’t handle sensitive data, you can exclude it from the scan. This keeps the results meaningful, reduces false positives, and helps you concentrate on the areas that truly require protection. #### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#pages) Pages To decide whether a page should be included in a security check, it helps to think in terms of public and private pages. Public pages—like a home page, a password-reset page, or a 404 page—are meant to be accessible without logging in, so scanning them for restricted access isn’t usually necessary. Private pages, such as dashboards or any area that requires a login, should not be accessible to anyone who isn’t authorized. These are the pages that benefit most from security testing. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FOwK7gwOTVXw0bft7NhJV%252FCleanShot%25202025-11-27%2520at%252013.11.25%25402x.png%3Falt%3Dmedia%26token%3D7b4d6fa3-d439-4fd4-9648-043463369631&width=768&dpr=3&quality=100&sign=782ab157&sv=2) In this example, only the private pages will be checked. Bubble’s AI has determined that the index, reset\_pw, and 404 pages don’t need to be included, but you can override this by checking additional boxes if needed. To keep scans efficient and reduce false positives, you can uncheck pages that are intentionally public. #### [](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#data-types) Data types To decide which data types to include in a security check, consider whether they store information that should remain private or restricted. Data types containing sensitive or user-specific information—such as profiles, orders, messages, or internal records—should be treated as private. These are the types that benefit most from permission checks and secure privacy rules. Some data types, however, are meant to be publicly accessible. For example, items displayed on a public landing page—such as blog posts, product listings, or marketing content—may not require strict privacy rules if they’re intended for anyone to view. To keep your scan focused and avoid unnecessary warnings, you can exclude data types that are intentionally public. This helps the test concentrate on the data that truly requires protection. Last updated 22 days ago Was this helpful? * [Accessing security dashboard test settings](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#accessing-security-dashboard-test-settings) * [Test settings](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#test-settings) * [Selected branches](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#selected-branches) * [Selected pages and data types](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings#selected-pages-and-data-types) Was this helpful? --- # The Workflow API | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) . [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#what-is-the-workflow-api) **What is the Workflow API?** ----------------------------------------------------------------------------------------------------------------------------------------------------- The Workflow API is the part of Bubble's built-in API that lets you set up workflows that can be triggered from an external application or system by sending an API request or by scheduling an API workflow in your app. By constructing API Workflows just like you construct regular workflows on a page, you can make Bubble perform any kind of action or sequence of actions based on a request that can include parameters. For example, let's imagine you have a customer contact form on a website that's not part of your Bubble application. By sending an API request from that platform that includes parameters like name, email and phone number, you can use an API Workflow to create a new lead or register a new user in your Bubble app. API Workflows also lets your app respond to webhooks in other systems. For example, whenever a payment is made successfully in Stripe, you can set up a webhook in Stripe to trigger a workflow in your Bubble app so that any needed action can be taken immediately. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#whats-the-difference-between-api-workflows-and-backend-workflows) What's the difference between API Workflows and Backend Workflows? As you start working in the Backend Workflow section of Bubble you may find the two terms used in different contexts. While they are certainly related, they don't carry the exact same meaning: * **Backend Workflows** encompass all the different events that you can add in the Backend Workflow editor: * API Workflows * Backend Triggers * Recurring Events * Custom Events * **API Workflows** refer specifically to the Workflows that you add by using the _New API Workflow_ command in the editor. They are referred to as API Workflows whether they are public or not. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F41GtHrybmGkkfa48Kk8f%252Fbackend-workflows.png%3Falt%3Dmedia%26token%3Dd48a14e2-6864-4d81-9c91-3602d7d6d431&width=768&dpr=3&quality=100&sign=dba941ea&sv=2) Backend Workflows is a collective term for all the different events you can create in the Backend Editor. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#activating-the-workflow-api) **Activating the Workflow API** ---------------------------------------------------------------------------------------------------------------------------------------------------------- To activate API Workflows, go to Settings - API and check the _Enable Workflow API and Backend Workflow_. This exposes all workflows that have _Expose as a public workflow_ checked. This also reveals your application's Workflow API root URL. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FfHlMmESlz4YRLlVllWiM%252Fenable-workflow-api-bubble.png%3Falt%3Dmedia%26token%3D5f0db313-e018-4234-bf11-d4321ea6aded&width=768&dpr=3&quality=100&sign=746ea85&sv=2) [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#accessing-the-backend-workflow-editor) **Accessing the backend workflow editor** ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ When the Workflow API has been enabled in your application’s settings, you can navigate to the virtual page _Backend workflows_ by clicking the icon in the left-hand menu bar. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F2aY325Q5cUGuhvdDkdvG%252Fnavigate-backend-workflows-bubble.png%3Falt%3Dmedia%26token%3De1a09bdd-f99c-442d-8783-3367f39c473c&width=768&dpr=3&quality=100&sign=647514ef&sv=2) [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#access-level) Access level ------------------------------------------------------------------------------------------------------------------------ In addition to user-based authentication, API workflows can also be restricted to _admin-only access_. This gives you more precise control over who is allowed to trigger sensitive workflows, such as administrative actions or data management operations. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F94Dq55rLKRxdu3xohyiv%252Fapi-workflow-access-level.png%3Falt%3Dmedia%26token%3D54b51870-2414-4e15-97d8-fe1a5b0ec7d6&width=768&dpr=3&quality=100&sign=f5f25dde&sv=2) API workflow authentication is configured using the _Authentication_ setting in the property editor. This setting determines what level of access is required to run the workflow and replaces the previous _This workflow can be run without authentication_ checkbox with a clearer set of options: * **None required** The workflow can be triggered without authentication. This option is typically used for signup, login, or other public-facing workflows. * **User and admin** Any authenticated user can trigger the workflow. If access should be limited to specific users, this must be enforced using conditions, logic, or privacy rules within the workflow itself. * **Admin only** Only requests authenticated with an admin-level API key can trigger the workflow. Regular user authentication is not sufficient. Existing API workflows continue to behave as before unless their authentication setting is changed. Using the _Admin only_ option is recommended for workflows that perform sensitive operations or should be accessible only to trusted systems or users with elevated permissions. This helps prevent unintended access and ensures tighter control over how and when critical workflows are executed. You can find the authentication setting by selecting an API workflow and reviewing its properties in the editor. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#continue-reading) Continue reading -------------------------------------------------------------------------------------------------------------------------------- [API workflows](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows) [Workflow API privacy rules](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules) [Workflow API endpoints](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-endpoints) Last updated 22 days ago Was this helpful? * [What is the Workflow API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#what-is-the-workflow-api) * [What's the difference between API Workflows and Backend Workflows?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#whats-the-difference-between-api-workflows-and-backend-workflows) * [Activating the Workflow API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#activating-the-workflow-api) * [Accessing the backend workflow editor](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#accessing-the-backend-workflow-editor) * [Access level](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#access-level) * [Continue reading](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#continue-reading) Was this helpful? --- # Database maintenance | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance.md) . This section covers different ways in which you can maintain your database to keep it running efficiently. If you want to learn more about the database in general and how it works, you can check out our dedicated article series below. Article series: [The database](https://manual.bubble.io/help-guides/data/the-database) The database is the filing cabinet of your application, where all data is archived for storage. Just like a regular archive, it makes sense to keep it clean and up-to-date. This is a good idea for a few reasons: * **Performance:** The more unnecessary data you keep around, the bigger your database becomes. This means more data for Bubble to search through and overall can affect your performance * **Privacy:** Removing unneeded data is good from a privacy perspective * **Data integrity:** As you scale and grow your app, a clean database can help you with decision making, since you can confidently make decisions based on reliable data This article series goes over a few different concepts that helps you maintain your database properly. Copying the database[](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance#copying-the-database) Copying the database means to clone the content of the development database into the live database or vice versa. This is a simple, automated operation in Bubble. Article: Copying the database Restoring database backups[](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance#restoring-database-backups) Bubble keeps automated point-in-time backups that can be restored back to that state with a simple operation. Article: [Restoring database backups](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups) Running bulk operations[](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance#running-bulk-operations) Bulk operations means to run a workflow on multiple things in your database in sequence. This helps you perform tasks that would be tedious to do manually, such as deleting and making changes to things. Article: [Bulk operations](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations) Related articles[](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance#related-articles) * Article series: [The database](https://manual.bubble.io/help-guides/data/the-database) * Article series: [Hosting and scaling](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling) Last updated 22 days ago Was this helpful? Was this helpful? --- # The native mobile debugger | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger.md) . [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#overview) Overview -------------------------------------------------------------------------------------------------------------------------------------------- The Mobile Debugger lets you inspect and debug your mobile app directly in Web Preview. It includes tools for checking workflows, viewing element properties, identifying runtime issues, and testing your layout across different device sizes. The debugger appears as a persistent panel on the right side of the preview and stays visible as you interact with your app. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#features) Features -------------------------------------------------------------------------------------------------------------------------------------------- #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#workflow-debugging) Workflow debugging Run workflows in Normal, Step-by-Step, or Slow mode to see how actions execute in real time. You can trace each step, monitor values, and catch unexpected behavior. You can also add breakpoints in the workflow editor to pause execution at a specific action and inspect it at the moment it runs. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#inspector-mode) Inspector mode Hover over elements in your mobile app to see their properties, conditional states, and dynamic values. This makes it easy to identify why something is or isn’t displaying as expected. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#error-and-warning-monitoring) Error and warning monitoring A floating panel in the debugger displays runtime errors, resource limits, and other relevant warnings. This helps you quickly spot and resolve issues during development. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#device-preview-toggle) Device preview toggle Switch between common mobile screen sizes to test how your app appears across different devices. This is helpful for identifying layout issues and testing responsive behavior. Persistent debugger panel The debugger stays docked to the right side of the screen during Web Preview, so you can inspect and interact with your app at the same time. It updates automatically as you navigate or trigger events. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#how-to-use-it) How to use it 1. Open your mobile app in Web Preview from the Bubble editor. 2. Click the debugger symbol in the upper left corner of the web preview, ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FJPUJPI4zbXPmzkdettlV%252Fdebugerinspect.png%3Falt%3Dmedia%26token%3D817affa3-9910-4c84-b966-d20b55943d4a&width=768&dpr=3&quality=100&sign=ae37295f&sv=2) 3. The debugger panel appears on the right-hand side. 4. Interact with your app and use the debugger controls to inspect elements, run workflows, and monitor errors. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fx9MzLHzI3MjkDxhzVnEH%252FCleanShot%25202025-06-18%2520at%252018.17.21.png%3Falt%3Dmedia%26token%3D8298bf11-7908-421f-96c0-41c2a46376c8&width=768&dpr=3&quality=100&sign=6d20187&sv=2) **Debugging workflows** allows you to inspect actions as they are triggered in your app. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FuWSHhCfsIDBrQ9nU0Vch%252FCleanShot%25202025-06-18%2520at%252018.21.15.png%3Falt%3Dmedia%26token%3D6e7fc344-e617-491e-a0df-8af55d2a33fd&width=768&dpr=3&quality=100&sign=77475df7&sv=2) **Inspecting elements** lets you view the details of individual elements in your app. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#notes) Notes -------------------------------------------------------------------------------------------------------------------------------------- * The Mobile Debugger is only available for apps built using the mobile editor. * It functions only in Web Preview and is not currently available in live mobile environments. The Disable Zooming property is enabled by default to prevent unintended pinch-to-zoom behavior during debugging. This can be turned off in the element’s settings if needed. Last updated 22 days ago Was this helpful? * [Overview](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#overview) * [Features](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#features) * [How to use it](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#how-to-use-it) * [Notes](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger#notes) Was this helpful? --- # API | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api.md) . The [Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) , including both the Data API and Workflow API, is only available on **paid plans**. See the [pricing page](https://bubble.io/pricing) for more information about our plans. The [API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) is available on all plans. One of Bubble's most powerful features is its ability to connect to other applications on the web. By using what's called an API connection, your application can fetch data and execute commands in external software systems and vice versa. ![Bubble API connections illustration](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FJzorEUG9KLQ82JSkKrph%252Fbubble-api.jpg%3Falt%3Dmedia%26token%3D47fda6c0-ff65-4d0b-abbb-ec5f52319079&width=768&dpr=3&quality=100&sign=5de2190e&sv=2) APIs let you connect to other applications and vice versa. [](https://manual.bubble.io/help-guides/integrations/api#introduction-to-apis) Introduction to APIs -------------------------------------------------------------------------------------------------------- In [this section](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) we'll cover how APIs work in general. This is a fairly technical section that takes an in-depth look at the underlying structure and mechanics of a RESTful API call. The information in this section is not needed for you to set up incoming and outgoing API requests in Bubble, but by knowing the basics you may find it easier to understand external API documentation and Bubble's settings. Bubble is a highly flexible platform. This means that while we offer robust API security features, we don't enforce their utilization. It is essential to possess an understanding of the fundamental principles of API management, such as authentication and authorization, in order to effectively secure one's implementation of the platform. Throughout reading this guide you may find it useful to check our [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) if there are terms and definitions you are unsure about. [](https://manual.bubble.io/help-guides/integrations/api#getting-started) Getting started ---------------------------------------------------------------------------------------------- If you are unfamiliar with how APIs work, we recommend starting with our introductory articles. The rest of the manual and reference entries will be easier to follow with an understanding of the basic principles: While there are an abundance of different services you can connect to via an API, most of the follow the same basic architecture called **REST**. [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) [](https://manual.bubble.io/help-guides/integrations/api#undefined) ----------------------------------------------------------------------- [](https://manual.bubble.io/help-guides/integrations/api#the-bubble-api-manual) The Bubble API manual ---------------------------------------------------------------------------------------------------------- In [this section](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) we cover the different API tools that Bubble offers. An API is either **incoming** or **outgoing**. An **incoming** **request** means that an external system is initiating a connection with your Bubble application to read/manipulate data or start a workflow. This is handled by the Bubble API. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FbBqX4oftQlHMemfhf6oH%252Fincoming-api-calls.webp%3Falt%3Dmedia%26token%3Dbdd8c1c5-e55f-4add-985a-cbf2c90a7c96&width=768&dpr=3&quality=100&sign=e93150a2&sv=2) An **outgoing request** means that your application initiates a connection with an external system to work with data or execute an action. This is handled by the API Connector. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fa4uqiDqJuz4vjLjfPW5B%252Foutgoing-api-call.jpeg%3Falt%3Dmedia%26token%3Db715ebac-1632-4dc1-bbe9-e46597584246&width=768&dpr=3&quality=100&sign=92daf4bd&sv=2) Incoming Connections (The Data API and API Workflows)[](https://manual.bubble.io/help-guides/integrations/api#incoming-connections-the-data-api-and-api-workflows) Incoming requests are calls that are initiated by an external system, such as another app. They are split into two different tools: * **The Data API** allows other applications to connect to your app's database to read, create, edit and delete data Article: [The Data API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api) * **API Workflows** allow other applications to execute workflows in your application remotely Article: [API Workflows](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api) Outgoing Connections (The API Connector and plugins)[](https://manual.bubble.io/help-guides/integrations/api#outgoing-connections-the-api-connector-and-plugins) Outgoing connections mean that your Bubble application initiates a connection with an external system to work with data or execeute an action. This is handled by two different tools in Bubble: * **The API Connector** allows you to establish an API Connection with any third-party app or system that adheres to the [RESTful](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) architecture. Article: [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) * **Plugins** are extensions that can be installed in your Bubble application to serve different functions. Many plugins allow you to easily connect to different well-known APIs without having to set it up in the API Connector. Article: [Plugins that connect to APIs](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis) API technical reference[](https://manual.bubble.io/help-guides/integrations/api#api-technical-reference) If you are already familiar with how APIs work and want to see our technical reference, go here. Section: [API reference docs](https://manual.bubble.io/core-resources/api) [](https://manual.bubble.io/help-guides/integrations/api#other-ways-to-learn) Other ways to learn: ------------------------------------------------------------------------------------------------------- Video lessons[](https://manual.bubble.io/help-guides/integrations/api#video-lessons) Tutorials * [Intro to APIs and the API Connector](https://www.youtube.com/watch?v=nO8PSqeJaWk&t=745s) * [Setting up Google API keys](https://www.youtube.com/watch?v=ouGT55o68ho) Webinars: * [Bubble Webinar 2 - The API Connector](https://www.youtube.com/watch?v=DXsL4FjAhd8) * [Bubble Webinar 4 - API Workflows](https://www.youtube.com/watch?v=zoPCX34Y8Io&t=63s) Last updated 22 days ago Was this helpful? * [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api#introduction-to-apis) * [Getting started](https://manual.bubble.io/help-guides/integrations/api#getting-started) * [](https://manual.bubble.io/help-guides/integrations/api#undefined) * [The Bubble API manual](https://manual.bubble.io/help-guides/integrations/api#the-bubble-api-manual) * [Other ways to learn:](https://manual.bubble.io/help-guides/integrations/api#other-ways-to-learn) Was this helpful? --- # Introduction to SEO | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo.md) . [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-important-is-seo-for-my-app) How important is SEO for my app? ----------------------------------------------------------------------------------------------------------------------------------------------------------------- Bubble is a flexible platform that lets you build a wide range of different applications. As such, each application's need for search engine optimization can vary greatly: for some it can be a crucial source of revenue, while for others it is irrelevant. In the first part of this article we'll go over three different categories of apps to help you determine whether SEO is relevant for your project. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#closed-apps) Closed apps If your app is designed to be used primarily by a closed group of users, such as a project management tool for your team or an inventory management system for your warehouse, you may not need to focus on SEO at all. Since your users are already aware of your web app and will likely access it through a direct link or bookmark, you don't need to worry about attracting new users through search engines. In some cases, you may even take active steps to hide the app from search engines. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#public-apps) Public apps if your app is designed to be used by a wider audience, such as a social media platform or a marketplace, SEO should be a top priority. When users search for keywords related to your web app on search engines like Google and Bing, you want your web app to appear at the top of the search results. If this describes your app, keep reading this article series to see how to work with Bubble's SEO tools. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#mixed-apps) Mixed apps A common solution is the mixed app, where some parts are closed (such as a project management dashboard), and others are public (such as the front page that recruits new users to the software). In this case, SEO can also be an important part of your marketing strategy, but one or more your app's pages will still be hidden to search engines (which usually means they require users to be logged in to access them). [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#seo-basics) SEO basics ---------------------------------------------------------------------------------------------------------------------- in essence, SEO is a way to make sure that your website is visible and accessible to the people who are looking for it. Imagine yourself performing a search in one of the major search engines: in most cases you will find what you're looking for among the first few results. SEO is the effort to try to be one of those pages. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-search-works) How search works #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#personalized-and-contextualized-searches) Personalized and contextualized searches Search algorithms have become incredibly complex since they were first invented. One of the major things to grasp with most modern search engines is that a page's position in the search ranking is not static or even the same for all users. **Personalized** means that the search engine may build a profile of your search habits and preferences and tailor the results accordingly. The degree to which a search is personalized depends on factors such as whether the user is logged in to their account with the search provider, their profile settings and their cookie settings. **Contextualized** means that they may also take into account different kinds of _current_ data about you, such as the device you are using, the operating system, the geographical location of your IP address, and other pieces of information. Again, this depends on the user profile, browser- and cookie settings of the user performing the search. The reason these two points are important to keep in mind, is that they suggest a key fact in SEO: top rankings are statistical probabilities, not static positions. In other words, your SEO efforts are a mission to increase the _likelihood_ of being the number one result, not a linear race to a top position where everyone will see you. That's why searching for your own pages does not necessarily give you any meaningful indication as to how the page is doing: Google might simply deduce that you have a high interest in it and increase its ranking for you alone, since they likely have a history of you interacting with it in the past. > Top rankings are statistical probabilities, not static positions. This is why tools like [Google Search Console](https://search.google.com/search-console/welcome) are useful and important, since they can give you an indication as to where the traffic to your pages comes from across potentially thousands of users, normalizing statistical outliers. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#title-and-description) Title and description In addition to personalizing the order of search results, search engines like Google are increasingly using their own algorithms to determine the most appropriate title and description for each search result. While Bubble provides dedicated fields for elements such as the page title and OpenGraph title, search engines may choose to pull a title and description from any of these fields or even generate their own based on the content of the page. This can include text from the page itself, such as headers or body content. However, this doesn’t mean that these fields aren’t important—on the contrary, they provide valuable context for search engines. It simply means that the exact title or description you “suggest” may not always appear verbatim in search results. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#content-and-keywords) Content and keywords Google has released an excellent guide on **how to create high-quality, people-first content**. If your app depends on organic traffic, we strongly recommend reviewing this guide: External page: Google: [Creating helpful, reliable, people-first content](https://developers.google.com/search/docs/fundamentals/creating-helpful-content) Search is based on _keywords_ or search terms. What this means is that any user who searches for something will provide a search term like "How to make pancakes", and the search engine will go through its index looking for pages that are relevant to that term. In the early days of search engines, they simply looked for a match: "How to make pancakes" would match "How to make pancakes", and the page named "Top 10 pancake recipes" would suffer. Today, search engines are smart enough to process queries linguistically and rephrase the question, take synonyms into account and understand the _value_ of the content on the pages it crawls through. > It used to be important to simply stuff your page with keywords, but now search engines are looking for quality content which gives users what they're looking for. This doesn't mean you should disregard keywords – they are still the bread and butter of a good SEO strategy – but you should write your content for humans to enjoy, not for bots to index. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#general-seo-advice) General SEO advice -------------------------------------------------------------------------------------------------------------------------------------- Now, let's look at some general advice on how to optimize your app and pages for SEO. Keep in mind that SEO is a wide field that's constantly evolving, so in this article we will only be able to cover the basics: still, adhering to these rules of thumb will set you off to a good start on your SEO journey: 1. **First and foremost, focus on creating quality content** Search engine algorithms are constantly evolving, but one thing that remains consistent is the importance of valuable, informative content. Write articles, make videos, and create other content that is interesting and engaging to your target audience. 2. **Use keywords strategically** When choosing them, make sure they are relevant to your content and that you use them in a natural way. Overusing keywords, also known as keyword stuffing, can hurt your rankings. 3. **Make sure your app is mobile-friendly** Make sure that your app is easy to navigate on mobile devices. Google even favors mobile-friendly websites in their rankings. This even includes details like font size, contrast and download size. We recommend getting to know the responsive engine to build pages that work on all screen sizes 4. **Use meta descriptions and title tags** Meta descriptions and title tags are snippets of text that may appear in search results. They should accurately describe the content of the page and entice people to click through to your app. You edit meta description and title tags in your [page's SEO settings](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page) . 5. **Build high-quality backlinks** Backlinks are links from other websites that point to your website. Google views backlinks as a sign of authority and relevance. However, not all backlinks are created equal. It’s important to focus on building quality backlinks from reputable websites in your industry. 6. **Monitor your app's analytics** Tools like Google Analytics can give you valuable insight into how people are finding and using your website. Google Analytics can be implemented using our dedicated [plugin](https://bubble.io/plugins) or by adding a tag in your page header, and there are many other useful tools that can collect and aggregate data in different ways. 7. **Make your app easy to navigate** Web crawlers do two things: they crawl content, and they follow links. Make sure to link pages to each other when it makes sense, and link to your most important content from your index page – search engines consider those links important. They also use the labels of your links to understand the content it leads to. You can read more about different ways of setting up links in our [navigation guide](https://manual.bubble.io/help-guides/logic/navigation) . Remember, SEO is a long-term game. It takes time to see results, so don't get discouraged if you don't see immediate improvements. The advice above is not a complete roadmap to SEO results, but keeping these points in mind while you develop your app can help you make informed decisions about your pages [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#opengraph) OpenGraph -------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#what-is-opengraph) What is OpenGraph? OpenGraph is a set of rules created by Facebook (now Meta) that helps you control how your web pages look when shared on social media. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FEHhDpMsNdOcOSMUk63mZ%252Ffacebook-opengraph-card-exxample-bubble.png%3Falt%3Dmedia%26token%3Df1c69045-3bd5-4462-8ecd-6cbb8e5c9bb1&width=768&dpr=3&quality=100&sign=6857061&sv=2) OpenGraph lets you define the data that is displayed when the page is shared on social media. This example is from Facebook. By using specific meta tags in the HTML of a page, developers can control how their content is presented when shared on social media platforms. This includes specifying the title, description, image (and sometimes more), ensuring that the content appears as intended when shared across various social networks. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#who-developed-opengraph) Who Developed OpenGraph? OpenGraph was developed by Facebook (now Meta) in 2010. The protocol was designed to enhance the user experience on social media platforms by enabling richer and more engaging content previews. Since its introduction, OpenGraph has become a standard in web development for controlling how web pages are represented on social networks. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-does-opengraph-affect-seo) How Does OpenGraph Affect SEO? OpenGraph metadata can play an important role in SEO by influencing how your page appears in search engine results and on social media. Key OpenGraph tags, such as og:title and og:description, can directly affect the title and description displayed in search engine results pages (SERPs). These tags help search engines understand the content of your page, improving its visibility and relevance. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#what-do-opengraph-tags-look-like) What do OpenGraph tags look like? OpenGraph tags are written in HTML code in the header section of your page. Bubble automatically generates the title, description and image tags and includes it in the HTML code of the page. The code looks like this: ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-do-i-use-opengraph-in-bubble) How do I use OpenGraph in Bubble Integrating OpenGraph metadata allows you to optimize how your pages are presented when shared on social media, and can have an effect on how the page is presented in the results of a search page (such as Google). OpenGraph fields are set in one of two ways (often both): #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#page-level) Page level Metadata included on the page element should contain information about that specific page. If this field is left empty, the app level metadata will be used instead. Article: [SEO: Page](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page) #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#app-level) App level App-level metadata will be applied whenever the metadata for a specific page is left blank. In other words, if metadata fields are filled at the page level, they will override the app-level metadata for that page. Article: [SEO: App](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app) Last updated 22 days ago Was this helpful? * [How important is SEO for my app?](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-important-is-seo-for-my-app) * [Closed apps](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#closed-apps) * [Public apps](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#public-apps) * [Mixed apps](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#mixed-apps) * [SEO basics](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#seo-basics) * [How search works](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-search-works) * [General SEO advice](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#general-seo-advice) * [OpenGraph](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#opengraph) * [What is OpenGraph?](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#what-is-opengraph) * [Who Developed OpenGraph?](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#who-developed-opengraph) * [How Does OpenGraph Affect SEO?](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-does-opengraph-affect-seo) * [What do OpenGraph tags look like?](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#what-do-opengraph-tags-look-like) * [How do I use OpenGraph in Bubble](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo#how-do-i-use-opengraph-in-bubble) Was this helpful? Copy --- # Plugins that connect to APIs | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis.md) . To connect to an external API, you will in many cases use the API Connector to set up the authentication and the different calls. There are many plugins however, that already have the authentication method and calls set up, that can save you some time. Before deciding to use the API Connector you may want to explore the plugin store to see if there's already a plugin that handles the calls you need. [](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#finding-api-plugins) Finding API plugins ----------------------------------------------------------------------------------------------------------------------------------- There are two simple ways to search for plugins that connect to an API: ### [](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#searching-for-the-api-provider) Searching for the API provider: To **search** for relevant plugins: 1. Navigate to the _Plugins_ section of the Bubble editor and click _Add plugin_. 2. Search for the API you want to connect to (i.e. Stripe) 3. Click the _Install_ button ### [](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#filter-by-plugin-type) Filter by plugin type Plugins in the plugin store are categorized into **types**, and you can use these to filter out the plugins by whether they are related to an API or not: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FCNwBKarZBx43Os5JIPLf%252Fplugin-types.png%3Falt%3Dmedia%26token%3Df0ea40d9-e76f-409b-9e54-77fcb7d013f9&width=768&dpr=3&quality=100&sign=5c655471&sv=2) By selecting the **API** plugin type you can filter the search results for plugins that are related to different API services. * Navigate to the _Plugins_ section of the Bubble editor and click _Add plugin_. * Under _Types_ on the left-hand side menu, click _deselect all_ * Select the _API_ type * You can further filter results by checking relevant boxes under _Category_ or use the search function Last updated 22 days ago Was this helpful? * [Finding API plugins](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#finding-api-plugins) * [Searching for the API provider:](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#searching-for-the-api-provider) * [Filter by plugin type](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis#filter-by-plugin-type) Was this helpful? --- # Authentication | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication.md) . **Authentication** is the process of identifying **who** a client is in order to determine what resources they have access to your your application. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication#introduction) Introduction ---------------------------------------------------------------------------------------------------------------------- Both the Data API and the Workflow API can be set up to require the client to authenticate themselves in order for your app to determine what resources they are allowed to access. In simpler words, you can require all external systems that want to access your database and workflows to log in using a secret password. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FRuxi0Oh5kFl4JzgmVGEY%252Fauthentication-bubble.jpeg%3Falt%3Dmedia%26token%3D2108a28a-f76c-42aa-87f8-6c0018441c88&width=768&dpr=3&quality=100&sign=ef5bb99f&sv=2) The article in the link below explains how the _bearer token_ is used to authenticate a client, regardless of the method you choose (except if you use no authentication). [How to authenticate](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/how-to-authenticate) [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication#authentication-methods) Authentication methods ------------------------------------------------------------------------------------------------------------------------------------------ You can set the access level for an **API workflow** using the **Authentication** setting. This determines whether the workflow can be accessible to everyone, to authenticated users and admins, or to admins only. Article section: [API workflow access level](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api#access-level) There are three different levels of authentication that you can set up in Bubble, each with their own pros/cons and security ramifications. You can use the settings described [above](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication#access-level) to maintain precise control over which users or systems are allowed to access each workflow. The articles below outline the three different authentication methods you can use: [No authentication](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/no-authentication) [As a user](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/as-a-user) [As an admin](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/as-an-admin) Last updated 22 days ago Was this helpful? * [Introduction](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication#introduction) * [Authentication methods](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication#authentication-methods) Was this helpful? --- # API guides | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides.md) . In this article series, you'll find step-by-step guides to connecting to popular API services through the API Connector. Use the left-hand navigation to find the article you are looking for. The resources below may help you get started if you are unfamiliar with APIs. API Connector API glossary The API Connector is the plugin we'll use to authenticate and sell requests to ChatGPT. You can find our documentation for the API Connector plugin below. Article: [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) Article series: [APIs](https://manual.bubble.io/help-guides/integrations/api) Video: [Bubble Academy](https://bubble.io/academy) | [Intro to APIs & The API Connector](https://bubble.io/video/intro-to-apis--the-api-connector) This article series includes several terms and expressions that are common in the broader tech field, particularly those used by API providers, which are not unique to Bubble. To understand these terms better, we recommend referring to our dedicated API glossary, which provides clear explanations for many of these technical concepts. Article: [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) Last updated 22 days ago Was this helpful? Was this helpful? --- # What is a RESTful API? | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) . Help us improve this article[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#help-us-improve-this-article) This article is part of a significant update to the Bubble manual and your feedback is critical to our efforts to continuously enhance our written documentation. We would greatly appreciate if you could take a moment to let us know your thoughts on the quality of it. Thank you for your support! [Give feedback on this article](https://docs.google.com/forms/d/e/1FAIpQLSfe7eaYVxkqTa_nn3QE6VObCxWB1hgh6sHUQGQ0Eit8JlAS7g/viewform?usp=pp_url&entry.619913899=https://manual.bubble.io/help-guides/apis-connect-to-other-apps/introduction-to-apis/what-is-a-restful-api&entry.80834677=What+is+a+RESTful+API?) This section covers a fairly technical topic on how the RESTful API architecture works. You may find it useful to learn more about the underlying mechanics, but if you want to skip directly to how API calls work in Bubble, follow the links below: Accepting incoming API Connections with the [Data API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api) and [Workflow API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api) Setting up outgoing API requests with the [API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) and [plugins](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis) . While reading about APIs you may also find our [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) useful. RESTful APIs use the HTTP protocol to initiate a connection with a server and get a response. What is the HTTP protocol?[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-http-protocol) Most internet users are familiar with the HTTP protocol. You see it as part of the URL of every website you visit. But what is it exactly? HTTP, or Hypertext Transfer Protocol, is a protocol: a set of rules that governs how data is shared between two systems to make sure both parties understand it. It would be difficult for two systems to communicate if they had no idea how to format the data: the HTTP protocol makes sure that they do. Whenever you open up a website, your browser is actually making an API call to the web server that hosts the page, and the server responds by sending back the needed files (such as HTML and CSS). Here's how the HTTP protocol works and the call is made: 1. A client (such as your web browser) sends a request to a server. The request contains information about what kind of action the client wants to take (such as requesting a webpage or sending data to be stored in a database) and it may also contain relevant information (such as the actual data you want to store). 2. The server receives the request and checks what kind of action the client wants to take and proceeds to process it. This might involve sending back a html file, looking for something in a database or running a workflow. 3. The server sends a response back to the client. The response usually includes a status code that indicates whether the request was successful or not, and it may also include additional data (such as the webpage the client requested). So HTTP ensures that a client and a server are able to communicate with each other in a standardized way. While the protocol in itself is pretty simple, it makes up the foundation of the entire web. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-a-restful-api) What is a RESTful API? ------------------------------------------------------------------------------------------------------------------------------------------------------ REST, or Representational State Transfer, is not actually a protocol, but more of a set of guidelines that define how a client and server should interact with each other. In other words, a developer can technically build an API to follow any kind of structure they want, but REST is a widely adopted style of architecting APIs that’s flexible, scalable and easy to understand. This makes it easy for different systems to talk to each other as their developers prepare it to follow the same method of communicating. The RESTful style follows a few key principles: * The client-servers are completely independent of each other and only communicate using the REST API. * It’s stateless: this means that the server does not store any information about the client between requests. As such, each request is completely isolated and contains all the information needed for the request to be processed. * It’s often cacheable, meaning that the client uses a cached response if the user requests the same data multiple times. This speeds up the client application and lightens the load on the server. Bubble automatically caches data instead of repeating a request, unless it needs to. * RESTful API’s are often described as layered since the client doesn’t necessarily have direct access to the server, but can be separated by intermediaries such as a proxy to ensure the stability and security of the server This may all sound very technical, but don’t worry: most of this is automatically taken care of and simply works. Bubble automatically generates an interface in your app that adheres to the RESTful principles, making sure that both incoming and outgoing connections are compatible with thousands of external systems. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-a-restful-api-call-looks-like) What a RESTful API call looks like ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- As we’ve seen, an API request based on REST principles allows two software systems to communicate with each other in a way that both systems understand. Each request/response is made in complete isolation from each other, and the server receives all the information it needs to process the request in that request. But what does the call actually look like? What kind of information is being transmitted? A good thing about the RESTful architecture is that the data being transmitted in both directions is designed to be readable both by computers and humans. Each call consists of recognizable parts that each serve a specific purpose. The call is made using the HTTP protocol. ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-url) The URL You have probably heard the abbreviation URL, but you may not have thought much about what it means. In the context of APIs the abbreviation makes sense: **Universal Resource Locator**. In the earlier section, we talked about how a resource is a specific piece of data or functionality that can be accessed through the API. It follows that the URL is the way to find that resource. In other words, the URL points the client’s request towards the right resource on the server. In Bubble’s Data API, endpoint URLs are automatically generated for each Data Type and API workflow you choose to expose. `https://myapp.bubbleapps.io/version-test/api/1.1/obj/datatypename` `https://myapp.bubbleapps.io/version-test/api/1.1/wf/workflowname` This is the first part of a RESTful API request. This too makes sense: in order for the server to authenticate a client and check the client’s authorization to reach a specific resource, we need to know which resource they are trying to access. ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#http-method) HTTP method Now that we know which resource the client wants to access, we need to know what kind of action they want to perform. Remember that we discussed HTTP being a protocol: that means we have a set list of possible actions that we can ask of a server that is prepared to receive HTTP requests. The list of possible HTTP methods is longer than this, but the most common actions you’ll see are: Action Description GET Retrieve data POST Create data PUT Replace data (empty values overwrite existing fields) PATCH Partially update data (empty values do not overwrite existing fields) DELETE Delete data When your browser contacts a server such as [www.bubble.io](http://www.bubble.io/) in order to load the webpage, it’s sending a GET request to the root URL of the domain. The bubble.io server has been set up to respond to such a request by responding with the necessary data to render the page in the browser, such as a HTML and CSS file. In GET requests, the URL can sometimes contain parameters, such as the constraints for a search whereas in POST/PUT/PATCH/DELETE requests parameters are usually contained within the [body](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-body) . ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fslf4zkrA73bOeM57v0KQ%252Fget-http-method-api-connector.png%3Falt%3Dmedia%26token%3Df7b5d2c8-02d3-493c-bb70-4bcca1284cec&width=768&dpr=3&quality=100&sign=a2769924&sv=2) The GET HTTP Method is used to retrieve some data. Here illustrated as the HTTP method would be specified in Bubble's API Connector. As you may have guessed by now, the same thing happens with the other actions: your browser sends POST, PUT and DELETE actions to the Bubble server to tell it to create, modify and delete things in your database. Now it’s starting to make sense why HTTP requests make up the foundation of the web: since every web browser and server speaks the language of HTTP actions to view, create, edit and delete data. ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-header) The header Every API request and response contains a header. This is where you’ll find what’s called _metadata_ or information about the data being exchanged between the API and its clients. A lot of different data points can be included in the header, but the most common ones you’ll come across working with Bubble are content–type and authorization. The Content-type is used to specify the media type of the data being transmitted so that it can be properly interpreted and processed. > For example, if a client is sending data to a server in the form of a JSON object, it might include a Content-Type header with a value of ‘application/json’ to indicate that the data is in JSON format. In our earlier example of fetching the bubble.io web page, the Content-type would have a value of ‘text/html’ to indicate that the client is expecting an HTML document in response to the request. The authorization contains the information needed to authenticate the client sending the request. In the case of Bubble’s API, Bubble accepts what’s called a Bearer token. In an HTTP header, that line would look like this: `Authorization: Bearer ` Bearer simply means that the client is a bearer of the given token. The token is a kind of password that the client has to authenticate themselves, often referred to as an API key. An API call doesn’t have to include authorization: it’s only needed when the API is not public. ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-body) The body The body can contain additional data, such as the data being sent in a POST, PATCH or PUT request (GET requests also sometimes contain parameters in the body). After all, if you want to create or modify something in the database, you need to include the information that you want to store, such as a user’s email and name. The body is better suited than the URL to hold complex or larger volumes of data. Here's an example of what the body of a POST call might look like. In this example we're creating a rentalunit with three parameters: a name, a number and an isRented boolean: The information you see in this example is formatted in the JSON format. What is the JSON format?[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-json-format) Bubble is built around the JSON format. This is a text-based format that is both easy for humans to read and write, and easy for machines to parse and generate. For example, let’s say we want to create a new user, we could include the following JSON-formatted text in the body: As you can see, JSON is easy to understand, but even so, Bubble will mostly generate it for you. But working with APIs you may find it useful to look at the body of the request and response to learn more about what is being transmitted. What other formats can be used in the body?[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-other-formats-can-be-used-in-the-body) The format of the body is not always in JSON. Remember that in our header we can specify what the format of the body should be, so it follows that it can be other formats as well. What kind of format a server expects depends on how the server is set up. In the list below are some common formats. The most widely used format is JSON and you usually don’t need to specify any other format unless the external API documentation specifically instructs you to: **Form data:** is often used when submitting HTML forms. Form data is usually sent as key-value pairs, with the keys being the names of the form fields and the values being the data entered into the fields. **XML (Extensible Markup Language)** is a markup language that is often used to transmit structured data. **Multipart form data** is a format that is used to send large amounts of binary data, such as file uploads. **Plain text:** The body of an HTTP request can also be plain text, which is useful for transmitting simple data or messages. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-full-request) The full request ------------------------------------------------------------------------------------------------------------------------------------------- Let’s imagine we’re building a system for keeping track of rental units, and we need to send an API call to the app to create a new rental unit. Putting together all the parts we’ve gone over the request may look something like this: In this example, the URL contains the resource we want to access (rentalunit), the HTTP method is POST, the headers include Content-Type and Authorization, and the body contains the data being sent to create a new rentalunit. In the next sections we'll cover how you can set up incoming and outgoing requests with Bubble's different API tools. [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) Last updated 22 days ago Was this helpful? * [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-a-restful-api) * [What a RESTful API call looks like](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-a-restful-api-call-looks-like) * [The URL](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-url) * [HTTP method](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#http-method) * [The header](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-header) * [The body](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-body) * [The full request](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#the-full-request) Was this helpful? Copy { "unitname": "Unit A", "unitnumber": 3, "isRented": true } Copy { "name": "John Doe", "age": 30, "isAdmin": true, } Copy POST https://appname.bubbleapps.io/api/1.1/obj/rentalunit Content-Type: application/json Authorization: Bearer { "unitname": "Unit A", "unitnumber": 3, "isRented": true } --- # Streaming API | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api.md) . [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-is-a-streaming-api) What is a streaming API? ----------------------------------------------------------------------------------------------------------------------------------------------- Streaming API is a method of transmitting data from a server to a client in real time, as the data becomes available, rather than waiting for the entire response to be prepared before sending it all at once. This approach contrasts with traditional request-response APIs, where the client sends a request and waits for the full response to be delivered in a single package. See Bubble Ambassador and User Manual writer Petter Amlie present the Streaming API feature. With streaming, data is sent in small chunks (called data frames) over a persistent connection. This allows the client to start processing information immediately, improving perceived speed and responsiveness ### [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-does-selecting-stream-mean-in-an-api-call) What does selecting stream mean in an API call? When you select Stream from the list of data types in the API Connector in Bubble, you're telling Bubble how to handle the response it gets back from the API. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcLpk2iSxNhJ0CAnYNHP7ED9juc9UDAa8vBJqFv-yJxiTONUZ9Q8DfNCWdxGuq__CW82AIcNEaCCi9UQ0zZ9OMHZJT4GH-5ON1YPzF-d6Kin7aNfcPBOAdRfpMVR8lJEh128fbPFA%3Fkey%3DgbhkkPdaBXb9vIjQ6281DQIh&width=768&dpr=3&quality=100&sign=be7895e3&sv=2) From a technical perspective, you're not choosing a different protocol (it’s still typically HTTPS), but you're defining how Bubble should handle the response. * Most APIs return a complete response all at once—typically in formats like JSON or XML. There's a request, and then a single response that ends the connection. * A streaming API works differently. It sends back a single response that remains open, allowing the server to deliver data gradually in chunks as it becomes available. Once all data has been sent, the server closes the connection to signal completion. [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-is-a-streaming-api-used-for) What is a streaming API used for ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Streaming APIs are used in scenarios where it's useful or necessary to keep a connection open and receive data gradually over time, rather than all at once. For Bubble developers, one of the most common use cases involves integrating with large language models (LLMs) like OpenAI's ChatGPT. With a traditional API response—such as one using JSON—the entire response is generated on the server and then sent to the client in a single package. This means the user doesn't see anything until the full message is ready, which can result in noticeable delays for complex or long responses. Streaming changes that behavior. When streaming is enabled, the server starts sending parts of the response as soon as they’re ready. For example, with tools like ChatGPT or Claude, you might see the reply appear word by word or sentence by sentence, allowing users to follow along in real time as the model generates its output. This approach improves perceived responsiveness and creates a more interactive user experience. While LLMs are a common use case today, streaming APIs are also widely used in other areas—such as financial market tickers, real-time analytics dashboards, and messaging bots—where timely, incremental data updates are essential. [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#setting-up-a-streaming-api) Setting up a streaming API ---------------------------------------------------------------------------------------------------------------------------------------------------- Before setting up a streaming API, make sure of the following: * Ensure that the API service you are connecting to (such as ChatGPT) supports a streaming API response * Install the API Connector plugin * Set up the relevant API authentication for the service you want to connect to * Add your first API call ### [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#enabling-a-streaming-api-response) Enabling a streaming API response To instruct Bubble that the streaming API response will be streamed, set the data type to Stream: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcLpk2iSxNhJ0CAnYNHP7ED9juc9UDAa8vBJqFv-yJxiTONUZ9Q8DfNCWdxGuq__CW82AIcNEaCCi9UQ0zZ9OMHZJT4GH-5ON1YPzF-d6Kin7aNfcPBOAdRfpMVR8lJEh128fbPFA%3Fkey%3DgbhkkPdaBXb9vIjQ6281DQIh&width=768&dpr=3&quality=100&sign=be7895e3&sv=2) It’s important to note that many API services require an explicit instruction to enable streaming. For example, OpenAI’s ChatGPT API will return a regular JSON response by default unless you include a specific parameter (such as "stream": true) in your request. This means that for streaming to work correctly, both sides need to be configured appropriately: your Bubble app must be set up to handle a stream, and the external service must be told to send the streaming API response. If either side is not properly configured, the streaming API initialization process may fail. In the example below, we’re sending a few parameters to ChatGPT to instruct it to return a streaming API response in the right way: model messages stream stream\_options This specifies which version of the language model you want to use (e.g. gpt-4, gpt-3.5-turbo). This is the core of the request and represents the conversation history. It’s formatted as a list of message objects, where each object has two required fields: * role: The [role](https://platform.openai.com/docs/guides/text?api-mode=responses#message-roles-and-instruction-following) of the message sender. Can be user, assistant, or system. * content: The [message](https://platform.openai.com/docs/guides/text?api-mode=responses#message-formatting-with-markdown-and-xml) text itself. #### [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#example) Example: This field tells the model what the user has said and, optionally, includes prior conversation history for context. This boolean parameter enables streaming if set to true. When streaming is enabled: * The response is returned as a series of partial chunks, rather than one complete response. * This allows your app to display content in real time as the model generates it, improving perceived performance and user experience. If stream is set to false or omitted, the model responds in a traditional, full-response format (JSON). This is an optional object that lets you modify the behavior of streaming API responses. Currently, one available option is: * include\_usage (boolean): If set to true, the final chunk in the stream will include token usage information, such as how many input and output tokens were consumed. This is useful for logging, usage tracking, or billing logic. #### [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#example-1) Example **Note**: This parameter only applies when stream: true is set. [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#setting-response-fields) Setting response fields ---------------------------------------------------------------------------------------------------------------------------------------------- When you initialize an API call that returns a streaming API response, you'll receive a series of events known as chunks. Each chunk contains one or more fields, with each field representing a key-value pair of data returned from the stream. To use this data effectively, you need to define how your app should handle each of these fields. #### [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#setting-up-streaming-api-response-fields) Setting up streaming API response fields When initializing a streaming API call, the full response must be received before the initialization process can complete. As a result, initialization may take longer than with a standard (non-streaming) API call. After initializing the call, the first step is to create a unique response field for every field you want to reference in your app. This allows you to access and work with the incoming data as it arrives in real time. Let’s continue the scenario of working with ChatGPT, and assume that you want to reference the following data: **Important:** The text stream is where Bubble receives the incremental content generated by the model. For models like ChatGPT, this appears under `response.output.event.delta` when the call is initiated. Set this response to **Push as text stream** to map the incremental response correctly. * Text stream - the incremental content generated by the model. When using streaming, this field updates continuously as each new token or word is returned by the model in real time. * Input tokens - the number of tokens used in the request payload. * Output tokens - The number of tokens generated in the response. This includes all tokens streamed or returned in the final output and helps you understand usage and billing impact. To create new response field, follow these steps: 1. Initialize the call and wait for the Returned values popup to appear 2. Scroll down to Response fields 3. Click Add new field + 4. Give the response field a name, and select a data type ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcRvaifYF2bgyBDFe24bGmz7gqCZN52F7k0u1fU9UBWPTFzDPr7CW9hSAcZQZ18eYPWDitOT0mYOE9726W37HCneY8EnyBgJs4pX4SDIvSWMfHYfwOSkAcupjZ1bonckfgTSfHI%3Fkey%3DgbhkkPdaBXb9vIjQ6281DQIh&width=768&dpr=3&quality=100&sign=36de9f04&sv=2) Response fields support the following types: Field name Description Streamed Text stream Incremental text content (e.g. the content being streamed) Yes Text A regular text value No Number A regular numerical value No Yes/no A true/false value No [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#using-streaming-apis-in-workflows) Using streaming APIs in workflows ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Just like regular JSON API calls, streaming APIs can be used both as a data source and within workflows. However, due to the continuous nature of streaming APIs, there is an important difference in how data is referenced within workflows, especially when using the Result of step X data source. When initiating a streaming API request within a workflow, Bubble behaves slightly differently on the client side versus the server side: * **Client-side behavior:** The workflow action will appear as "finished" as soon as it begins receiving streamed data from the external API. This allows the workflow to move forward and execute subsequent actions immediately, provided these actions do not rely on the final, non-streamed values from the API request. * **Server-side behavior:** On the server, the workflow action will remain active (blocking) until the streaming API has fully completed and the connection is closed. For example, if you have a workflow set up like this: * **Step 1:** Send request to ChatGPT (streaming) * **Step 2:** Save the chat message (final text stream) in the database (result of step 1) The following implications apply: * Client-side actions that don't depend on the final API results can proceed without waiting for the stream to fully complete. * If an action references the final non-streamed result of the streamed request, the workflow will pause until the streaming has fully completed. * Server-side actions will always wait until the streamed API has fully completed, potentially delaying subsequent server-side operations. Common use case: * A frequent scenario is initiating a streamed API call (like ChatGPT), then immediately displaying the incoming streamed data to the user through Bubble's Display data action. This provides users a seamless and responsive experience as the streamed content arrives gradually. [](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#streaming-api-data-sources) Streaming API data sources ---------------------------------------------------------------------------------------------------------------------------------------------------- Each response field you configure in the API initialization popup automatically becomes a data source in your app. If you use the field type Text stream, Bubble also creates a few additional underlying data sources to support the streaming functionality: Text stream text so far Text The text that has been generated so far. This value updates in real time as new data is received from the stream. full text Text The full text. This value is only available after the streaming is done. Is done Yes/no Returns a yes if the stream is done. Is waiting Yes/no Returns a yes if Bubble is awaiting a response. Is streaming Yes/no Returns a yes if the stream is ongoing. Last updated 22 days ago Was this helpful? * [What is a streaming API?](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-is-a-streaming-api) * [What does selecting stream mean in an API call?](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-does-selecting-stream-mean-in-an-api-call) * [What is a streaming API used for](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#what-is-a-streaming-api-used-for) * [Setting up a streaming API](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#setting-up-a-streaming-api) * [Enabling a streaming API response](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#enabling-a-streaming-api-response) * [Setting response fields](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#setting-response-fields) * [Using streaming APIs in workflows](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#using-streaming-apis-in-workflows) * [Streaming API data sources](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api#streaming-api-data-sources) Was this helpful? Copy { "messages": [\ { "role": "user", "content": "Please write me a medium-length poem." }\ ] } Copy { "stream_options": { "include_usage": true } } --- # Introduction to testing and debugging | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics.md) . First, let's spend some time to define the different terms included as you prepare your app for live users: **Testing** is the process of trying out the different steps of your application to check that it works as expected. It doesn't have to mean something wrong, but if there is, testing is meant to uncover it. **Debugging** is done when you've observed a non-expected behavior. It's the process of understanding the root cause of the issue so that you can rectify it. This introductory guide will give you some general advice on how to test and debug your app, before we move on to the tools that Bubble offers. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#the-development-environment-and-live-environment) The Development environment and Live environment Every Bubble app consists of two environments: Development and Live. Development is a fully functioning version of your app that you (and your team) can work in together to see exactly what the finished app will look live. Live is the app that your users see. The two environments have database that operate completely independently of each other. In other words, in the Development environments you can make changes to your database that have no effect on your live app, making it a completely safe environment to experiment in whichever way you need to. You should always aim to fully complete testing and debugging before deploying your app to Live. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#testing) Testing -------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#plan-your-testing-and-break-it-into-pieces) Plan your testing and break it into pieces Testing is all about using your app as your users would, and working systematically through all pages and features to identify issues. While this guide will not outline what a systematic approach should look like (everyone works differently), we will still encourage you to be mindful of how you organize your testing. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#keep-notes) Keep notes If you are testing something and see an issue elsewhere, take a note for later and stay focused on the task at hand. Letting your focus drift from place to place is an easy way to miss things, so remember to stick to the plan, but note down anything else you see. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#add-test-data) Add test data An app with no data in it and an app with lots of data can behave very differently. Adding test data can help you identify issues related to design, performance and security. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#test-on-different-screen-resolutions-and-devices) Test on different screen resolutions and devices If your app is going to be used on different screens and devices, it's a good practice to test it on different resolutions and maybe even throttling the connection speed and CPU. Chrome Developer tools offers a highly useful Device Mode that lets you do all of these things. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#test-as-different-users) Test as different users As you introduce privacy rules and conditions, your users will start to experience the app differently. Some users may have access to specific parts of your database and app, while others don't. In these cases it's useful to make a habit of testing your app as different users. For example, if you have two user types, _user_ and _admin_, it's likely that one has a different access level than the other, and you may miss issues or inconsistencies if you only test as one of them. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#how-to-test-the-app-as-another-user) How to test the app as another user To use your app as a specific user, simply search for that user in the built-in database editor and click _Run as_. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fzd155zfxcQBf5IxdrSa4%252Frun-as%25402x.png%3Falt%3Dmedia%26token%3D9e7b3e6d-631b-48b9-bf88-99b64da0112f&width=768&dpr=3&quality=100&sign=8041079c&sv=2) Using the _Run as_ feature lets you easily test your app as another user without having to know their credentials. [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#debugging) Debugging ------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#make-sure-you-can-reproduce-it) Make sure you can reproduce it As you keep testing your app, you will uncover the occasional issue – don't worry, it happens even to the most experienced developers! When beginning to debug an issue, the key initial step is to establish a consistent and predictable method for reproducing it. In practice, this involves retracing your steps and running multiple tests to confirm that the issue consistently appears every time, and with the same characteristics. This lets you get a firm grasp of the problem before you spend time tackling it. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#stay-systematic-and-break-it-down) Stay systematic and break it down Each issue you find may have more than one cause. As you identify it or them, stay focused on one at a time. It can be useful to find ways to test that the cause you're currently working on is fixed before moving on to the next. Again, keep notes to make sure you don't miss anything. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#remember-privacy-rules) Remember privacy rules Many issues are related to data being unavailable because of privacy rules. Keep in mind that they apply everywhere (elements, workflows and conditions), so it's often a good idea to check the rules for the relevant data type. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#collect-information) Collect information If the error has been reported by one of your users, you should try to collect as much information as you can about the circumstances that produced the error. * Which user is it? * What kind of device and browser are they using? * Are they using ad blockers or script blockers of any kind? * What were the exact steps they took to produce the issue? * Can it be reliably reproduced, or could it be because of a poor connection or other external reason? ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#reach-out-to-the-community) Reach out to the community Bubble has an incredibly welcoming and helpful community. If you ever find yourself stuck on an issue, don't hesitate to seek help! Share your problem on the [Bubble forum](https://forum.bubble.io/) , reach out to our [Success Team](https://bubble.io/contact) , or hire one of our [expert coaches](https://bubble.io/coaching) to assist you in resolving it. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#take-a-break) Take a break! Sometime issues are best solved on a walk outside, in the shower or lying on the couch. Other times you simply need some time to refresh your mind before returning to the screen and continuing the search. Your brain is a muscle – it too needs rest between the sessions! [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#testing-and-debugging-tools) Testing and debugging tools ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Bubble offers two ways to debug issues, each serving a specific purpose: The debugger (checking errors on elements and in workflows as they happen)[](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#the-debugger-checking-errors-on-elements-and-in-workflows-as-they-happen) The debugger is a small panel at the bottom of the screen when you are running your app in Development. Using the debugger, you can: * **Run workflows action-by-action** and check data (such as the result of a search) related to each step * **Inspect the elements on the page** to check their attributes, conditions and associated data Article: [The Debugger](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger) The Server Logs (diagnosing past issues)[](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#the-server-logs-diagnosing-past-issues) The second tool for diagnosing past issues is the Server Logs. This feature allows you to retrospectively examine what occurred in your workflows and check any unexpected behavior or errors. Article: [The Server Logs](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs) [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#using-safe-modes) Using safe modes -------------------------------------------------------------------------------------------------------------------------------------------- Our Academy quick tip on how to preview your app in safe mode Safe modes is a way to preview your app, but disabling certain parts for debugging purposes: * HTML - this disables on-page HTML elements * Community plugins - this disables community-made plugins If the issue resolves itself in Safe mode, you'll know it is due to something introduced by a plugin or custom code. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#how-to-enable-safe-mode) How to enable Safe mode You enable Safe mode by holding the mouse button on the _Preview_ button for one second. A dropdown will show you the list of options. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FIYiJfiXyDoT11RVlsct0%252Fsafe-mode%25402x.png%3Falt%3Dmedia%26token%3Dd1360ab2-36fa-4133-ad31-56f685cf35d2&width=768&dpr=3&quality=100&sign=e0443afd&sv=2) What if you think it's a Bubble bug?[](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#what-if-you-think-its-a-bubble-bug) The Bubble development team extensively tests features and uses automated testing to minimize bugs. However, if you believe you've encountered an issue that is not caused by the way your app and workflows are built but rather an unexpected behavior in a Bubble core feature, please reach out, and we will investigate. This does not apply to plugins that aren’t built by the Bubble team. For those, we recommend reaching out to the plugin author directly. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#how-to-report-bugs) How to Report Bugs To report a bug, please use the **Bubble AI chatbot**. _Note: You must be logged into your Bubble account to report a bug._ #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#before-you-submit-a-bug-report) Before You Submit a Bug Report To ensure that your issue is indeed a bug, please take the following steps before submitting a report: * Verify that your internet connection is stable and that you are using the latest version of your browser. * Test the issue in _Incognito mode_ (or Private Browsing) to rule out interference from browser extensions or ad blockers. * Remove any _custom code_ you have added in HTML elements, headers, or other custom script sections. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#while-submitting-a-bug-report) While Submitting a Bug Report To help us investigate and resolve your issue as quickly as possible, please keep the following in mind: * **Be as specific as possible** when describing the issue: ❌ _It doesn’t work, I think it’s a bug_ ✅ _Based on this condition, this element should be red, but instead, I see it as green._ * If possible, **reproduce the issue on a blank test page** outside of your app’s core design and workflows. The more isolated the issue, the faster we can investigate. * Provide **clear instructions** that someone unfamiliar with your app can follow. A step-by-step guide like _“Click on button A,” “Type XX in the input,” “Click on button B,” “See the problem”_ is the most effective. * **Include screenshots** to illustrate the issue when prompted in the chatbot. * **Videos can be helpful** but should not replace written descriptions. They should serve as a complement if necessary. We understand that bugs can be frustrating and slow down development. By providing clear and detailed reports, you help us identify and resolve issues faster—benefiting not only you but the entire Bubble community. Last updated 1 year ago Was this helpful? * [The Development environment and Live environment](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#the-development-environment-and-live-environment) * [Testing](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#testing) * [Plan your testing and break it into pieces](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#plan-your-testing-and-break-it-into-pieces) * [Keep notes](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#keep-notes) * [Add test data](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#add-test-data) * [Test on different screen resolutions and devices](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#test-on-different-screen-resolutions-and-devices) * [Test as different users](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#test-as-different-users) * [Debugging](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#debugging) * [Make sure you can reproduce it](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#make-sure-you-can-reproduce-it) * [Stay systematic and break it down](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#stay-systematic-and-break-it-down) * [Remember privacy rules](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#remember-privacy-rules) * [Collect information](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#collect-information) * [Reach out to the community](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#reach-out-to-the-community) * [Take a break!](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#take-a-break) * [Testing and debugging tools](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#testing-and-debugging-tools) * [Using safe modes](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics#using-safe-modes) Was this helpful? --- # The Data API | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api.md) . The Data API is Bubble’s automated way of providing external systems access to your app’s database. It allows one-click creation of a RESTful interface to some or all of your application's data. You can let a client read, modify, and delete individual data items, search for data using a flexible query language, and create and bulk upload new things You can grant full admin access to the database and allow another system to be able to freely make changes (even in bulk) or you can exert exact control over what data types they can access and what kind of actions they can take. Since the Data API in theory can give any external system complete control over your database, it’s important to learn how to set it up in a secure way. Remember that Bubble offers strong security, but we don’t enforce it – because we want to allow flexibility you are free to set up your Data API to be as open or closed as you prefer. This is why it’s important to learn how different decisions affect security so you can make informed decisions that suit your project. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api#activating-the-data-api) **Activating the Data API** ---------------------------------------------------------------------------------------------------------------------------------------------- You’ll find the Data API by navigating to Settings - API. To make sure that no one can access your database unless you want them to, the Data API is disabled by default. To enable it, check the Enable Data API checkbox. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FvYr0YmnkuI8Wfm1iWTwa%252Factivate-data-api.png%3Falt%3Dmedia%26token%3D02543942-91ef-46d2-9146-059c70891fb7&width=768&dpr=3&quality=100&sign=2a04eec&sv=2) As soon as you have the Data API enabled, you’ll see a list of all your data types along with a second checkbox: this is where you select which data types to expose in the API Only activate the Data Types that you want to expose in the Data API. Keep in mind the following: * Unchecked data types are **not** available in the Data API regardless of how the user authenticates * Checked data types are exposed, but adhere to the privacy rules in combination with the client’s authentication [Data API Privacy Rules](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules) [Data API endpoints](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-endpoints) [Data API requests](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-requests) Data API security checklist[](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api#data-api-security-checklist) This section covers Data API security in a short checklist, allowing you to plan and set up secure connections with external clients. Article: [Data API security](https://manual.bubble.io/help-guides/security/api-security/data-api-security) Core reference entries about the Data API[](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api#core-reference-entries-about-the-data-api) Our core reference section contains short-form technical instructions that you may find useful when you're working with the Data API: Reference: [The Data API](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api) Reference: [List of Data API requests](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests) Reference: [Constructing the Data API endpoints](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-endpoints) Last updated 22 days ago Was this helpful? Was this helpful? --- # Bulk operation methods compared | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared.md) . In this article, we’ll explore the two most common methods for scheduling bulk database operations in your app. The two methods are somewhat similar, but from a technical perspective they behave differently, and have different use cases. This article focuses on performing bulk operations **in your app**, as opposed to in the Bubble editor. If you want to perform bulk operations from the Bubble database editor, check the article below: Article: [The bulk operations feature](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations#the-bulk-operation-feature) [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#introduction) Introduction ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Before we go into the details of each method, we’ll start by defining what we mean by a bulk operation in this context, and give a quick overview of what the two methods are. Throughout this article, we'll sometimes refer to the _Schedule API workflow on a list_ method as _**SAWOL**_. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#what-do-we-mean-by-bulk-operations) What do we mean by bulk operations? In the context of this article, a bulk operation refers to executing a workflow for each item in a list. For instance, if you have a list of 5,000 users and need to update a specific field in the user data type for all of them, you'd run the workflow 5,000 times, once for each user, to apply the necessary change. The purpose is to automate repetitive tasks across a large number of records. > Both methods will be scheduled and executed **server-side** **as** API workflows. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#the-two-methods-in-short) The two methods in short ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#schedule-api-workflow-on-a-list) Schedule API workflow on a list The Schedule API workflow on a list action is a single action that instructs Bubble to run a given API workflow once for each thing in a list. If you use this method to schedule an API workflow on 5,000 things, Bubble will schedule the workflow as 5,000 separate API workflows that run independently of each other. One workflow does not wait for another to finish. Bubble will work its way through the list as fast as it can. If you set a delay in-between each workflow, Bubble will still schedule all the workflows in one operation, but add the specified delay to the schedule time. For example, let’s assume the following scenario: * The current time is exactly 12:00:00 am * You use Schedule API workflow on a list of 5,000 users * The first API workflow should run immediately * You define a delay of 1 second * The actual workflow takes 0.2 seconds to finish Bubble will do the following: * Schedule the first workflow at 12:00:00 * Schedule the second workflow at 12:00:01 * Schedule the third workflow at 12:00:02 * And so forth Regardless of how long the first workflow takes to complete, the second workflow will start at the assigned time. As such, the workflows are not looping, but scheduled for a definite time in the future. Furthermore, in cases where your app is rate-limiting the number of workflows running at any given time (e.g. you have many backend workflows scheduled for the same time), workflows may not run until there are resources available, in which case it will start after its scheduled time. So even with an interval, there is no guarantee that the workflows will run one at a time, or in order. As such, this method should be used only in cases where the workflows are independent. See the sections below for more details. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#recursive-workflows) Recursive workflows Using recursive workflows can potentially lead to infinite recursion, resulting in significant workload unit (WU) consumption. Starting on **July 1st, 2024**, Bubble will apply a default setting to terminate recursive workflow chains at 10 iterations for all new apps. This means you need to either disable this feature or set a higher limit (recommended) if you plan to use recursion, or else any **recursive workflow chain will be terminated after 10 iterations.** Article: [Infinite recursion protection](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection) Recursive workflows behave a bit differently. Instead of scheduling a list of workflows, you are technically scheduling just one workflow on one thing, and this workflow contains an action that re-schedules the workflow. Let’s assume the same scenario as above: * The current time is exactly 12:00:00 am * You use Schedule API workflow, and include a list parameter of 5,000 users * The first API workflow should run immediately * You define a delay of 1 second in the rescheduling action * The actual workflow takes 0.2 seconds to finish * The Schedule API workflow action takes 0.1 second to finish Bubble will do the following: * Schedule the first workflow at 12:00:00 * Schedule the next workflow 1 second after the first workflow has finished: 12:00:01:03 * Schedule the second workflow 1 second after the second workflow has finished: 12:00:02:06 As you can see, the time each workflow takes to finish, and the time it takes to schedule a new iteration, is added to the total time of the bulk operation. In other words, recursive workflows are slower, but you can ensure that no workflow runs before the prior workflow is done. The short difference between the two, then, is that Schedule API workflow on a list runs in parallel, while recursive workflows run sequentially. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#comparison-table) Comparison table SAWOL Recursive workflow **Processing** Runs in parallel Can run sequentially **Workload** Spends less workload Spends more workload **Performance** Faster Slower **Actions needed to run** One Same number as items in the processed list **Reliability** Will always attempt to run all workflows May stop if an error is hit **Runaway loops** Do not happen Can happen **Iteration timing** Static Dynamic [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#which-method-should-i-use) Which method should I use? -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Now that we know the basic difference between the two methods, let’s dig deeper into which method you should use. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#workload-and-performance) Workload and performance First, we’ll have a look at how the two methods differ from the perspective of: * **Workload**: how much workload is needed to finish * **Performance**: how long the process takes to finish An informal benchmark test using Schedule API Workflow on a List to execute 100K workflows compared to scheduling them recursively, gave the results below: Task SAWOL Recursive workflow Delete 100K things 20–25 min 6–7 hrs Copy 100K things 60 min 10 hrs Modify 100K things 75 min 12 hrs WU for scheduling 100K workflows ~12,000 (~0.12 per workflow) 70,000 (0.70 per workflow) Numbers can differ substantially, based on what your workflow does, but as the general trend shows, Schedule API Workflow on a list is a more performant and workload-friendly operation. There are a few reasons why: #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#performance) Performance When using _Schedule API workflow on a list_, the completion time is generally shorter because Bubble is capable of running multiple workflows concurrently. This means if you have Workflow 1, 2, and 3, Bubble can process them all at the same time, aiming to complete the task as quickly as possible. This parallel execution helps in speeding up the processing. Secondly, using the _SAWOL_ action will schedule all the workflows in one operation, whereas a recursive workflow will schedule each workflow separately. In other words, Schedule API workflow on a list is one action, while a recursive workflow (using our earlier examples of a list of 5,000 things) is 5,000 actions. Scheduling an API workflow is a fast process, but noticeable when multiplied by a long list of things such as 5,000. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#workload) Workload Recursive workflows consume more server resources in two main ways. * Reschedule action: Firstly, they need that extra action to reschedule themselves, using additional server capacity. * Conditions: Secondly, each cycle typically requires a conditional check to prevent infinite looping, further increasing server load. Each of these factors contributes cumulatively to the total workload on the server. Improperly configured recursive workflows can unexpectedly use up your allocated workload units, possibly exhausting them in a single operation. This risk arises if the condition meant to halt the indefinite looping of the workflow is absent or incorrectly set up. Without a properly functioning stopping condition, the workflow may continue until it has consumed all available workload units ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#parallel-versus-sequential-processing) Parallel versus sequential processing As we touched upon earlier, Schedule API workflow on a list runs the workflows in parallel when possible. That doesn’t mean that all 5,000 run simultaneously, but generally that Bubble will not make any attempts to stop them from overlapping. This in turn means that even if you specify an interval (such as 1 second) between the workflows, they might still overlap if the prior workflow takes some time to finish. On longer lists, this is more likely to occur. As a result, setting an interval can stop workflows from overlapping, but there’s no guarantee. Recursive workflows, on the other hand, can be guaranteed to run in sequence, since the action that schedules the next cycle is often the last action in the recursive workflow. That means the workflow first runs through the action steps, and the next cycle will not start until it’s scheduled. While this can take longer and spend more server resources, it can be useful in scenarios where you want to avoid any overlap. We can illustrate this with a few examples: #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#example-1-race-conditions) Example 1: Race conditions A race condition is a term often used in software development to describe when two or more processes access shared data and try to change it simultaneously. For example, if two Bubble workflows try to make changes to the same thing at the same time, the metaphor implies that those two processes are “racing” against each other to make the change, which can affect the outcome. This can lead to unexpected behavior, where it’s difficult or even impossible to predict which process will finish first. If you are using _Schedule API workflow on a list_, and the workflow involves making changes not only to each individual thing in the list, but also to one thing that’s shared across more than one workflow, you may not get the expected result, since the order of execution is not guaranteed. To avoid this, you can use a recursive workflow to run the operation sequentially, or, if possible, make the change to the shared thing only when all the workflows in the list have finished. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#example-2-depending-on-data-from-prior-step) Example 2: depending on data from prior step Sometimes, you’ll need to send a dynamic parameter along with the next scheduled API call. In cases where this parameter relies on information from the current cycle, you’ll need to be sure that the data is generated before the next iteration. Consequently, you can’t schedule the workflows in one operation, but will need to schedule them one by one recursively. While this can be necessary and useful in some scenarios, finding a workaround that doesn’t force you to send unique parameters for each iteration can have a big effect on the performance and workload consumption of the process. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#example-3-tracking-the-progress) Example 3: Tracking the progress With Schedule API workflow on a list, it’s difficult to predict or confirm when a process is done, as there is no guarantee on order of execution and the workflows are all independent. A recursive workflow gives you more flexibility to track the ongoing process, or to know when it’s finished. Typically the iteration number is passed as a parameter to a recursive workflow and decremented in each subsequent call to schedule the next one. This allows you to include actions in the workflow with conditionals that reference where the workflow is in the current sequence. This can be useful to show the progress visually on-screen, start a workflow when the process is done or communicate to the user (such as sending an email) when it’s finished. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#setting-a-dynamic-timestamp-on-each-iteration) Setting a dynamic timestamp on each iteration Recursive workflows are not only used for bulk processing, but can also be used to perform a specific task at a given interval or time. For example, you may want to run a workflow at a dynamic time, such as the fifth day in every new month; by using a recursive workflow, you can have the workflow dynamically schedule itself to run again at a future time, potentially continuing this pattern indefinitely. This capability allows for flexible and precise timing in automating tasks. Let’s say you’re using a workflow to schedule a regular email to users. By default, it's sent every month, but you may offer your users to change that schedule, such as setting a bi-monthly mail instead. 1. If you use _Schedule API workflow on a list_, you will have to schedule each iteration on a set, unchanging schedule 2. If the user changes their schedule setting, a recursive workflow can easily adapt to the new pattern This is just one example to show that recursive scheduling can help you experiment more freely with dynamic patterns in execution. You could also have the time of the next iteration be based on data generated in the current iteration, keeping it truly dynamic. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#reliability) Reliability With _Schedule API workflow on a list_ scheduling all workflows in one operation, they are guaranteed to run. A recursive workflow relies on the rescheduling action, and as such, can technically fail to move on to the next iteration. If one iteration stops, all upcoming iterations stop. This is not a bad thing in all scenarios – after all, if a workflow hits an error, you may want it to stop rather than to continue the work on all the things in the list. But if it's important that the workflow finishes, _SAWOL_ will provide a slightly higher level of reliability. When using _SAWOL_, all workflows are queued in a single operation, ensuring completion. In contrast, recursive workflows, depending on rescheduling actions, can occasionally fail to proceed to the next iteration due to various reasons. While this is rare, but not impossible, and there are a few reasons as to why it can happen: * excessive server resource consumption may cause timeouts, halting the rescheduling action * If one rescheduling action stops, it disrupts the entire cycle. * Server outages or errors can prevent the reschedule action from executing The longer the list and timeframe of the full operation, the bigger statistical chance of an error is, making Schedule API workflow on a list a safer action. In cases of server errors, this workflow type simply pauses and then resumes once server resources become available again. [](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#the-workflow-scheduler) The workflow scheduler ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The API workflow scheduler is Bubble’s built-in tool for keeping an eye on scheduled workflows. This tool allows you to see a list of scheduled workflow within a given timeframe, and take actions such as pausing or deleting them. This process is more easily controlled with the Schedule API workflow on a list action, since it will simply list all the scheduled actions as soon as that action has completed. Recursive workflows, on the other hand, are “invisible” until scheduled. That is, Bubble doesn’t know that they will be scheduled until each iteration actually is. This can make them more complicated to handle in the API workflow scheduler; by the time you have canceled one scheduled workflow, it may already have scheduled the next iteration, forcing you to update your search. Last updated 22 days ago Was this helpful? * [Introduction](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#introduction) * [What do we mean by bulk operations?](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#what-do-we-mean-by-bulk-operations) * [The two methods in short](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#the-two-methods-in-short) * [Schedule API workflow on a list](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#schedule-api-workflow-on-a-list) * [Recursive workflows](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#recursive-workflows) * [Comparison table](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#comparison-table) * [Which method should I use?](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#which-method-should-i-use) * [Workload and performance](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#workload-and-performance) * [Parallel versus sequential processing](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#parallel-versus-sequential-processing) * [Setting a dynamic timestamp on each iteration](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#setting-a-dynamic-timestamp-on-each-iteration) * [Reliability](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#reliability) * [The workflow scheduler](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared#the-workflow-scheduler) Was this helpful? --- # Bubble AI Agent | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/ai/bubble-ai-agent.md) . **AI Agent availability:** The AI Agent is currently available on all new apps — blank, templated, and built by Bubble AI. It’s a beta release, and we’re continuously improving its output. Some responses may contain errors or inaccuracies. The Bubble AI Agent is an in-editor assistant that helps you build, troubleshoot, and understand your app more efficiently. It uses Bubble documentation and app context to provide hands-on guidance so you can spend less time searching for answers and more time building. You can also prompt it to create and modify simple UI elements. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#permissions) Permissions The Agent has the same permissions as the user who initiates the chat. If you are an editor, it can make edits on your behalf. If you only view-only permissions, the Agent will only be able to inspect and provide guidance. If you have collaborators in your app, their Agent will inherit their permissions. This ensures that someone with read-only or view-only permissions to your app will not be able to edit your app using the Agent. If they try to edit, the Agent will gracefully decline. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#how-to-access-the-ai-agent) How to access the AI Agent The Agent opens automatically the first time you load your app — there’s nothing to install or activate. You can minimize it at any time and reopen it by clicking the magic wand icon in the top navigation bar: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FywEwNavcFGIHpu7stf8w%252Fai-agent%25402x.png%3Falt%3Dmedia%26token%3D42d4446f-f741-4dc7-a0d0-5f17f1ce9d7f&width=154&dpr=3&quality=100&sign=b25fce5b&sv=2). The window is resizable and responsive, and it remains open until minimized ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FYF95EINdFcC5jhh8JDXu%252Fminimize-icon%25402x.png%3Falt%3Dmedia%26token%3Dced46c82-344a-4dd4-880c-0da76adb816d&width=40&dpr=3&quality=100&sign=41ce500b&sv=2). You can keep it visible while working in the editor or hide it when you prefer a cleaner workspace. [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#what-the-ai-agent-can-do) What the AI Agent can do ------------------------------------------------------------------------------------------------------------------ The AI Agent has the following capabilities: * [UI creation and modification from prompts and images](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#ui-creation-and-modification) * [Generate images, and find suitable stock images](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generating-images) * [Generate and edit data types](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#data-type-generation-and-modification) * [Generate and edit option sets](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#option-set-generation-and-modification) * [Dynamic expressions](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#dynamic-expressions) * [Generate and modify frontend workflows](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generate-and-modify-workflows) * [App-specific explanations](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#app-specific-explanations) * [Issue checker integration](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#issue-checker-integration) * [Education and guidance](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#education-and-guidance) Make **one request at a time** for the most accurate results. It’s multilingual — you can prompt it in your preferred language, and it will respond in the same language. The Agent supports you in building, understanding, and learning within Bubble — from making visual edits to explaining how your app works. If you click on any part of your app, the Agent automatically gets the context of what you’ve clicked on, so it will give higher quality output in all three key areas listed above. We highly encourage you to click on a part of your app (hold down shift to select multiple elements) when you want to make changes to it or learn more about it. You have full control here – remove the context by clicking “x” next to the relevant icon within the chat: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FEFio5iedVnbT821woqMA%252Fremove-element-bubble-ai-agent.gif%3Falt%3Dmedia%26token%3D8f557dd3-69ec-4855-8a9f-89e3d1a5c7bb&width=768&dpr=3&quality=100&sign=21814bd0&sv=2) ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#ui-creation-and-modification) UI creation and modification The Agent can create or modify your app’s design, including: * Full pages – you can prompt to create a new page * Specific sections like headers, navigation bars, or footers * Individual components such as groups, image elements, text, and buttons * The AI agent can also generate images. See more [below](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generating-images) . When generating elements that benefit from images, such as pages, repeating groups, or individual image elements, the Agent also generates the images. Placeholders like sample images in repeating groups are pulled from stock sources such as Unsplash or Picsum, while static assets use AI-generated images. Sample prompt: _"Build a landing page for a coffee subscription with a hero image and a 3-column feature section with icons."_ You’ll get the best results when prompts are specific about what to change and where. You can also [upload images](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#uploading-images) to guide the Agent. When the Agent creates elements, it follows design best practices: * All elements are responsive by default * Layouts are well-organized with logical parent-child relationships * Proper margins and padding are applied * App style variables are respected for consistent design #### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#uploading-images) Uploading images You can upload images of a desired UI to the Agent and it will replicate them using Bubble elements. ![Uploading images to the Bubble AI Agent](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F30Sg6z0feMmw13jevfq2%252FCleanShot%25202026-04-15%2520at%252017.27.34.png%3Falt%3Dmedia%26token%3D13ec7c3b-22dd-482d-a004-e2bf24ce18c2&width=768&dpr=3&quality=100&sign=9551b992&sv=2) Click the image icon in the bottom left corner to upload up to five images. This makes it faster to convert Figma designs into Bubble elements, or use screenshots of other products as inspiration. Note that asking the Agent to insert images into your canvas is not supported. You can upload up to five images with a prompt, and we currently support JPG, PNG, GIF and WebP. **Sample prompt:** #### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#confirming-your-ai-prompt) Confirming your AI prompt After you prompt UI creation and modification, the Agent will present a plan to you that you can either approve or cancel. Click approve and the changes will instantly be made. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FfQzlVl1WOA4N3jj4QJTE%252Fedit-user-popup-add-field%25402x.png%3Falt%3Dmedia%26token%3D64e1e603-db88-46eb-bf51-05c0cfca541d&width=768&dpr=3&quality=100&sign=8f343516&sv=2) You can easily add new elements, and the AI Agent understands your app’s context to ensure they’re created and configured correctly. More examples: UI creation and modification[](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#more-examples-ui-creation-and-modification) * `Add a new page with a form allowing users to upload new products into the database` * `Add a button labeled “Sign up” to the Home page header.` * `Insert an input field and a “Submit” button in the Contact page form.` * `Add a repeating group on the Products page showing each product’s name and price.` * `Set the Signup button’s color to Primary.` * `Create a popup where users can edit their first name, last name, and phone number.` ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#dynamic-expressions) Dynamic expressions The AI Agent automatically creates or edits dynamic expressions based on your prompt. When you ask it to make a change, it searches your app for the right data sources and operators needed to complete the task. It then summarizes the updates it plans to make so you can review and approve them. * You might have a repeating group which contains a list of all tasks completed by all users, and you want to show tasks completed by the current user. **Example prompt:** After selecting the repeating group to give the AI Agent context, you can prompt: _“Can you generate an expression for this repeating group that searches for a list of tasks completed by the current user?”_ ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F0CZs93JNwcrGCUbEPPE9%252Ftask-list-bubble-ai-agent.gif%3Falt%3Dmedia%26token%3D4d0fb64f-b576-41f9-8ddc-29097db4754c&width=768&dpr=3&quality=100&sign=ab21fcb&sv=2) * If you have a task management system, you can display who completed a task by adding a text element to the cell. **Example prompt:** _“Edit this expression to also include the email address of the user who completed the task.”_ **Current limitations:** this version can’t incorporate conditionals, and it can’t leverage data sources from API calls, since plugins aren’t currently supported by Bubble AI. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#data-type-generation-and-modification) Data type generation and modification The AI agent can generate new data types and modify existing data types and their accompanying fields. We recommend using the Agent over the data type generation tool on the Data tab because it’s able to modify existing fields as well. Create new data types Say you're building a gym management app. You might need to add additional data types beyond what was initially generated, like a Gym data type. * You can prompt: "Add a Gym data type with fields: Name (text), address (text), capacity (number), opening\_hours (text).” ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FqjZUu56NHALcEmlRUhP1%252FAdobe%2520Express%2520-%25201-generate-data-type-from-agent.gif%3Falt%3Dmedia%26token%3Dca2d4ff3-6b8c-4033-8e60-2444dd3c0a0c&width=768&dpr=3&quality=100&sign=f254ce2e&sv=2) Modify existing data types You can also add fields to data types that already exist: * Prompt: "Add Location and Hiring Manager fields to my Job data type" ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FRImGpEeAygskk6paYfbl%252FAdobe%2520Express%2520-%25202-modify-data-type-from-agent.gif%3Falt%3Dmedia%26token%3Dac70973b-6fa8-40cb-9eee-796d152e3441&width=768&dpr=3&quality=100&sign=18711625&sv=2) You can view and edit any generated data types in the [data tab](https://manual.bubble.io/help-guides/data/the-database) immediately. Current limitations: this version can’t delete data types or field types, or remove fields from existing data types. It cannot modify existing field types (like converting a Salary field to be a number instead of text). ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#option-set-generation-and-modification) Option set generation and modification The AI Agent can also create and modify [option sets](https://manual.bubble.io/help-guides/data/static-data/option-sets) . It can do this as the result of a direct prompt (`"Generate an option set for [...]"`), or as part of a broader request where the AI Agent determines that an option set is needed. You can view and edit any generated option sets in the [data tab](https://manual.bubble.io/help-guides/data/the-database) immediately. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generate-and-modify-frontend-workflows) Generate and modify frontend workflows You can prompt the AI Agent to generate frontend workflows within your app (backend workflows are coming soon). Prompt the Agent, then navigate to the Workflow tab to see the workflow it built for you. We recommend starting with simpler prompts for highest accuracy. At launch, workflow creation has higher accuracy than workflow editing. **Create new workflows** For example, as you're building a login and signup flow, you can click on the login button, then ask the Agent to “Please add a workflow that signs the user up given these inputs. Be sure to include the password confirmation and full name field.” For the above prompt to work, you’ll need an existing Full name field in your User data type. The Agent cannot yet create data types and workflows from the same prompt. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FUJoarb5rwyHYqpjRietf%252Fworking-signup-flow-gif.gif%3Falt%3Dmedia%26token%3D5294dd78-886a-4e92-a93e-4f9f22c04820&width=768&dpr=3&quality=100&sign=14dd305e&sv=2) Here’s a full list of events that the Agent can create workflows for: * General * User is logged in * User is logged out * Page is loaded * Do every five seconds * Do when condition is true * An unhandled error occurs * Elements * An element is pressed * An input’s value is changed * An element has an error running a workflow With the following actions: * Account actions * Navigation actions * Data/things actions (base actions, not actions installed later) * Emails/Notifications (base actions, not actions installed later) * Element actions **Modify existing workflows** If you’ve made some changes to your database and you need to update the workflow accordingly, you can prompt “I’ve added a birthday date field to the user data type and to the form. Please capture that date field’s value here in the sign up action.” ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FbqIkCA0DQgeKjz26n5sv%252Fmodifiying%2520a%2520workflow.gif%3Falt%3Dmedia%26token%3De1fd0945-d1ff-4ff2-bdde-bce8dcd9c733&width=768&dpr=3&quality=100&sign=194c83c2&sv=2) Current limitations: This version is limited to the most common actions that users take. Currently, backend workflows, analytics actions, custom events and very complex workflows are not supported. Bubble AI does not support plugins, so payment actions, analytics actions, and plugin actions are also out of scope. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#app-specific-explanations) App-specific explanations The AI Agent understands your app’s structure and elements, along with general context — such as the page you’re viewing or the element you’ve selected — allowing it to: * Help troubleshoot workflows and dynamic expressions * Answer questions about how elements are configured * Explain how your app is wired together Selecting an element gives the Agent clear instructions to focus on it in relation to your prompt. The Agent also includes deep-links to UI elements in its explanations, so you can click and see what elements it’s referring to. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fur9IR5zavQq0E1S32i4E%252Fai-agent-explaining-elements%25402x.png%3Falt%3Dmedia%26token%3D260f5e25-4fb4-4752-b265-63775fc245a5&width=768&dpr=3&quality=100&sign=ac917153&sv=2) The AI Agent links directly to the elements mentioned in your query, allowing you to click and view exactly what it’s referring to. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FmoETLkFX1TENTao6EIy4%252Fbubble-ai-agent-explain-action%25402x.png%3Falt%3Dmedia%26token%3D90621512-06af-407a-9601-658fffafa626&width=768&dpr=3&quality=100&sign=aa65942f&sv=2) The AI Agent can explain the purpose of specific parts of your project and suggest logical next steps in your development process. More examples: App-specific explanations[](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#more-examples-app-specific-explanations) * `How do custom states work for showing and hiding elements?` * `What’s the difference between frontend and backend workflows?` * `How do I display data in a repeating group?` * `How do privacy rules work in my app?` * `Are there any button missing workflows on this page?` * `Can you explain all the places a user can navigate to from this page?` #### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#context-limitations) Context limitations Currently, the AI Agent can’t access or interpret plugins, logs, or other app details beyond your app’s design, logic, and data. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generating-images) Generating images When generating elements that benefit from images, such as pages, repeating groups, or individual image elements, the AI Agent also generates the images. Placeholders like sample images in repeating groups are pulled from stock sources such as Unsplash or Picsum, while static assets use AI-generated images. #### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#sample-prompt) Sample prompt: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FmkjQecNeg228vsKtimLS%252FCleanShot%25202026-06-12%2520at%252011.00.09.png%3Falt%3Dmedia%26token%3D9ff5ad58-4f90-4f8c-9b70-0e104657fd0b&width=768&dpr=3&quality=100&sign=cb734d96&sv=2) The AI Agent can generate images for purposes like hero sections and find suitable stock photos for placeholders and sample content. [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#issue-checker-integration) **Issue Checker integration** ------------------------------------------------------------------------------------------------------------------------ The AI Agent has access to Issue Checker context, allowing it to automatically resolve issues within its current capabilities. At the moment, it has access to the first 100 issues in your app. To fix an issue, prompt the system with a command such as “Fix the first issue for me.” The Agent will then attempt to resolve it automatically. For best results, **click on the issue you are trying to solve**, and then prompt the Agent to solve it. **Note:** This feature is in **early access**. While using experimental features, please make sure to double-check the Agent’s work and expect more polish coming soon. Note that **only supported issues can be fixed**. Issues outside the agent’s current capabilities will need to be handled manually. ### [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#education-and-guidance) Education and guidance Bubble’s AI Agent uses Bubble knowledge and documentation to guide you accurately through building, editing, or troubleshooting your app. When you ask a question, the Agent references official sources — including the Bubble Manual — and responds with citations and helpful links. It can also search the web to surface the most relevant and up-to-date information. This means its responses are based on trusted Bubble resources, and it can still guide you through solutions, even for tasks it can’t perform directly. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Faj7a4LDQtD7q5MtlBMeI%252Fconnect-chatgpt-explanation-bubble-ai-agent%25402x.png%3Falt%3Dmedia%26token%3Dd792abb8-de45-449f-95c7-d6e199d2794a&width=768&dpr=3&quality=100&sign=79619a7e&sv=2) The AI Agent can walk you through complex problems with clear, step-by-step guidance. More examples: Education and guidance[](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#more-examples-education-and-guidance) * Show me how to connect an API using the API Connector. * What are the best practices for setting up database privacy rules? * Explain how to structure data for a marketplace app. * How can I optimize backend workflows for performance? * How can I set up user log in with Google? [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#general-prompting-advice) General prompting advice ------------------------------------------------------------------------------------------------------------------ * Keep prompts short and focused — concise requests are easier for the AI to interpret. * Include specific details such as element names, field types, or labels. * Make one request at a time for the most accurate results. * Use Bubble terminology to describe what to create or edit. * When modifying something, specify both what should change and how. * You can also ask the AI to explain what a change will do before applying it. [](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#whats-coming-soon) What’s coming soon ----------------------------------------------------------------------------------------------------- The AI Agent is currently in beta and continues to evolve. Upcoming capabilities include: * Full editing support for the native mobile editor (currently guidance only) * Better self-improving loop / validation * Compound edits: currently the Agent can only make one edit at a time, to edit UI, data, expressions, or workflows. Compound edits will allow the Agent to make multiple edits at the same time, so you can build full features with one prompt. Last updated 6 days ago Was this helpful? * [Permissions](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#permissions) * [How to access the AI Agent](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#how-to-access-the-ai-agent) * [What the AI Agent can do](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#what-the-ai-agent-can-do) * [UI creation and modification](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#ui-creation-and-modification) * [Dynamic expressions](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#dynamic-expressions) * [Data type generation and modification](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#data-type-generation-and-modification) * [Option set generation and modification](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#option-set-generation-and-modification) * [Generate and modify frontend workflows](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generate-and-modify-frontend-workflows) * [App-specific explanations](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#app-specific-explanations) * [Generating images](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#generating-images) * [Issue Checker integration](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#issue-checker-integration) * [Education and guidance](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#education-and-guidance) * [General prompting advice](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#general-prompting-advice) * [What’s coming soon](https://manual.bubble.io/help-guides/ai/bubble-ai-agent#whats-coming-soon) Was this helpful? Copy Can you build me a login page that is inspired by this screenshot, but customized to my app’s styles and design aesthetic? Copy Build a landing page for a coffee subscription with a hero image and a 3-column feature section with icons. --- # SEO: Page | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page.md) . From an SEO perspective, the pages in your app consist of three important data areas: * **The URL**, or the _web address_ your page tells both your users and search engines what the page is about. * **Metadata** is data "about" the page: its title, description and social media images. * **Content** is the actual information on your page – the design, text, images and videos that both your users and search engines see Let's explore each of these areas. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#the-url) The URL ----------------------------------------------------------------------------------------------------- The URL is a part of the HTTP protocol – a big part of how the internet works. If you want to learn more about the technical side of how the HTTP protocol works, you can check out the article section below: Article section: [The HTTP protocol](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-http-protocol) (advanced) The URL is the humanly readable "address" of the page. It's used by search engines to isolate content: for example, one page in your app may be about _sports shoes_ and another about _horses:_ they would both have a unique URL and can show up differently in search results. URLs serve a function both for search engines and your users; they are the humanly readable way to access the page, and as such should be clear and understandable. For example, compare the URLs below: Copy ❌ https://www.my-bubble-application.com/mcakos/najsdnf Copy ✅ https://www.my-bubble-application.com/product/runnning-shoes The first one is not easy to decipher, but the last one gives an easily understandable indication of what the page is about. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#can-i-set-up-page-folders) Can I set up page folders? Bubble doesn't use page folders in the traditional sense, but instead relies on _dynamic pages_. These are pages where the content is dynamically generated from database data, and it can be used to set up unique pages for each database thing. Read more about this in the section below. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#dynamic-pages) Dynamic pages Every page lets you set a _type of content._ This tells Bubble what kind of data you want to load onto the page and it's how you set up dynamic pages with unique URLs. Let's say that you have an eCommerce store. On a page called _products_ you want to dynamically show different products from your database. The data type is called _Product_. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FFK4puEbGFsqCRiwAr4Gr%252Fproduct-page-thing.png%3Falt%3Dmedia%26token%3D83777585-23b9-4dc6-a3cd-e5e6f8244e82&width=768&dpr=3&quality=100&sign=341dfee2&sv=2) In the example above, we've set the _Type of content_ to the _Product_ data type. This means Bubble is ready to accept a Product thing that we'll pass through the URL. There are two ways in which Bubble will recognize a page thing in the URL: * The thing's unique ID * The thing's slug The unique ID is automatically created whenever a database thing is created, and as such, that field is never empty. The _slug_ on the other hand, can be left empty and can be added or modified as needed. Let's say we have a _Baseball cap_ product in our database – we could give that the slug _baseball-cap_ to give that product its own unique URL: This is a nice, humanly readable URL that makes it clear to your users what the page is all about. But search engines see this in the same way: while you only have one page (product), search engines considers the _slug_ a page on its own. Using the slug, you can set up just one page, but potentially hundreds, thousands or even millions of unique URLs that each contain unique content. For example, if your eCommerce was selling sports goods, every product in your inventory would get its own unique URL and could be found in search engines. Instead of searching for your _app,_ new customers would find your site by searching for things like baseball caps and golf equipment. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#what-happens-if-the-slug-is-empty) What happens if the slug is empty? If you leave the slug field empty, Bubble defaults to using the things Unique ID instead. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FFyd87XXuo5ZlBgYMYBgW%252Fbackup-field.png%3Falt%3Dmedia%26token%3D4667d9ba-359c-4e65-adf8-3d8a7ff130f5&width=768&dpr=3&quality=100&sign=aad11343&sv=2) Selecting a value the _Backup field for URL_ will instruct Bubble to use another field as a backup in case the slug field is empty (in this case the name) – but there's a caveat: since the URL needs to be unique (and the name field does not), Bubble will append the unique ID to a web-friendly version of the name. The result might look something like this: So if you want readable, SEO-friendly URLs, we recommend making sure the slug field is never empty. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#changing-urls) Changing URLs Also keep in mind that URLs that keep changing will need to be re-indexed by search engines, and they might consider it new – or even duplicate – content, which hurts your ranking. It's best to employ a strategy where you keep your URLs as consistent as possible: * Once set, don't change the slug field on a database thing * Don't change the names of your pages Keep in mind that these are not absolute rules, but rather guidelines to incorporate within your overall SEO strategy. Sometimes, changes are needed, and that's fine. If you decide to change the URL of a page (page name or thing's slug), you can inform search engines that the content has moved by using a 301 redirection. Article section: [301 redirects](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#301-redirects) [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#metadata) Metadata ------------------------------------------------------------------------------------------------------- Metadata is a data _about_ the page. It's not necessarily visible on the page itself, but is part of the page's code and helps search engines understand what the page is about. Information contained within a page's metadata is also often visible in the preview that search engines provide of a given page in the result. You can think of metadata then serving two purposes: * One is to "convince" the search engine that your page is a relevant result for a given search by including relevant keywords * The second is to make potential visitors want to _click_ your page instead of another page in those same search results So while you should have the search engine robots in mind when setting up your metadata, you should also keep in mind that in the end, your potential readers are human beings that will also judge the quality of your page in terms of its title, description and structure. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fi3yLfRJEkpNoCZpOhjxO%252Fsearch-preview%25402x.png%3Falt%3Dmedia%26token%3Db80ff6a0-b13f-400a-8efd-a3d2d6277e6f&width=768&dpr=3&quality=100&sign=e60f49c&sv=2) Here's how the title and description Bubble's main page looks in the desktop and mobile version of a Google search. Optimally, all your pages should have unique metadata, so that search engines and users understand the difference between them and they don't end up competing with each other. Metadata is a wide field of different ways you can standardize data to communicate to search engines what your page is about, but the most common fields consist of the following: ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-title) Page Title The page title is short representation of your page's content. It's often displayed prominently in search engine results and it's visible to your user's in the browser tab. When crafting a page title, ensure it is descriptive, relevant, and includes your target keywords. Google may use this field, the SEO title below or craft its own title to represent the content in a given search. If you have experience working with HTML, this field defines the page title as illustrated with the code below: ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#title-for-seo-fb) Title (for SEO / FB) The _Title (for SEO / FB)_ defines the OpenGraph title. If you have experience working with OpenGraph, this represents the fields below: This is essentially an optimized version of your page title, specifically tailored for search engines and social media sharing. It is often the first line of text that appears in search engine results and should be engaging and relevant to your content. To maximize its effectiveness, keep it under 60 characters and incorporate the primary keywords for this page. Search engines may use this field, the page title above or craft its own title to represent the content in a given search. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#description-for-seo-fb) Description (for SEO / FB) The _Description (for SEO / FB)_ defines the OpenGraph description. If you have experience working with OpenGraph, this represents the fields below: This is an optimized summary of your page, designed for search engines and social media sharing. It typically appears beneath the title in search engine results or as a preview when the page is shared on platforms like Facebook or X. To make it effective, keep it concise (under 160 characters) and ensure it clearly conveys the core message of the page. Search engines may use this field, extract a description from the page content, or generate their own. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#social-media-image) Social Media Image The social media image is the visual representation of your content when it's shared on social platforms like Facebook and X. Select an image that accurately represents your content and is visually appealing and keep in mind that posts that include an image will take up more space on a social media wall, which can lead to a higher click-through rate. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#example-opengraph) Example (OpenGraph) The metadata that you add in the _Title (for SEO / FB)_ and _Description (for SEO / FB)_ are used by social media and other sharing platforms to generate a preview of the content that is shared. How exactly it ends up looking can vary between platforms and is subject to change. The example below shows how a social media post of Bubble's homepage would look on Facebook: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FEHhDpMsNdOcOSMUk63mZ%252Ffacebook-opengraph-card-exxample-bubble.png%3Falt%3Dmedia%26token%3Df1c69045-3bd5-4462-8ecd-6cbb8e5c9bb1&width=768&dpr=3&quality=100&sign=6857061&sv=2) From top to bottom in this example, we are seeing: * The social media image (blue background, text and logo in one image) * The domain (bubble.io) * The OpenGraph title (as defined in _Title (for SEO / FB)_ field) * _The OpenGraph description (as defined in Description (for SEO / FB)_ field) ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-html-header-and-html-elements) Page HTML Header and HTML elements The page HTML header can contain various tags and information that help search engines understand and index your content. These tags include: * additional meta tags * structured data * canonical tags * language tags Using the HTML header for SEO purposes is among the more advanced strategies and is outside the scope of this guide, but there are many tutorials and Youtube videos available that go in-depth on this topic. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#metadata-in-the-page-body) Metadata in the page body Some metadata (such as Schema.org Microdata and JSON-LD (JavaScript Object Notation for Linked Data) can also be placed in the body of your page, which gives access to a broader set of data sources. You can do this by placing an HTML element on the page. This is getting into fairly advanced SEO territory, and is outside the scope of this article. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#metadata-settings-in-bubble) Metadata settings in Bubble First, keep in mind that there are separate _app_ settings and _page_ settings. The metadata we discuss in this article relates to the page, and can be different on every page in your app. They can also contain dynamic content, as we'll explore later in the article. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#accessing-a-pages-metadata) Accessing a page's metadata Since the metadata we want to work with is stored in a _page_ basis, we first need to navigate to the page that we want to work with in the Bubble editor. Use the page navigator to open the page. The settings are found in the element inspector of the page itself. You can access this by double-clicking the page in the editor, or clicking the name of the page at the top of the element tree (such as _page index_). ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FndmGAc6ojwjb6qthP6PP%252Fpage-metadata-seo-settings.png%3Falt%3Dmedia%26token%3D5a483ad3-463f-46bb-8293-33aee6296a67&width=768&dpr=3&quality=100&sign=6d6011dd&sv=2) All the metadata for the page can be edited on the Each of the fields can be filled with static content, or you can populate it with dynamic content from the data on the page. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#populating-metadata-with-dynamic-content) Populating metadata with dynamic content The metadata fields accept dynamic content from the following data sources: * Current User * Current page thing * Do a search for * Get an option * Arbitrary text * Get data from page URL * App text * Arbitrary date/time In addition, it accepts static text values so that you can give any page the title and description you want without referencing any data sources. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#content) Content ----------------------------------------------------------------------------------------------------- As we explored in our Introduction to SEO, the _content_ of your page remains one of the most important parts of your SEO. Generally, the rule of thumb is as simple as it is challenging: the content should be high-quality. While it's outside of the scope of this guide to try to determine _what_ quality content is, there are still guidelines that can help you gain a higher ranking. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#design) Design The design of the page matters from a SEO perspective too: while search engines may not care whether your app looks _good_ per se, it cares that it's accessible: * Organize your app with a logical structure and provide clear, easy-to-use navigation menus * Ensure good contrast between page elements like text and background to improve readability. For instance, dark grey text on a light grey background may be challenging for visually impaired users * Size and distribute elements in a way that makes it easy for all users to interact with them. For example two buttons that are too small or placed too closely together can make navigation difficult * Add _alt text_ to your images: this not only tells search engines what the images are, but it helps visually impaired users understand your content and shows a text if the image doesn't load * Use descriptive link texts: search engines look at the label of a link when they try to understand what the link is about. Instead of just using the name of the page you are linking to, you can use the opportunity to describe it from another angle. For example, a page with the title _SEO tutorial_ could have a link that says _Learn SEO basics._ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#text) Text The easiest way for a search engine to understand the content of the page is to scan its text for keywords. * Write for people, not for bots * Use keywords in a natural way: keywords are the corner stone of your content; it's basically _what_ the user wants to find. You should use keywords in your text content repeatedly, but not in an exaggerated way (known as keyword stuffing). Make the text useful and enjoyable, and make sure to mention keywords where it makes sense. * Use headers: Headers (such as `

`, `

`, etc) is how search engines understand your pages structure. Split your text into sections and use a clear and structured hierarchy. You can enable tags for text elements by going to _Settings - SEO / metatags_ and checking _Expose the type of tags for text elements_. * Link pages together: when relevant, place links within your text to other pages in your app or even to external pages. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#media) Media Mix media on your pages where possible. Use a mix of text, images and video to make it as useful a page for your users as possible. Keep in mind that some types of media can increase the download size of your page. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-load) Page load Search engines also consider two more factors when evaluating your content: * Total page download size: A lightweight page can achieve better rankings, as it is considered more user-friendly, particularly for mobile devices. The things that typically add to its total size is large images, fonts, external Javascript files (sometimes added by plugins). In essence, the less stuff you add to a page, the lighter it is. * Total page load time: The time it takes from the page is opened until the content is finished rendering on the screen is also an important factor in your ranking. Avoid placing heavy, complex searches and workflows on page load, and reduce the page's total size to optimize it for fast loading. Bubble has a base loading time on all pages that we are continually working to optimize. Last updated 22 days ago Was this helpful? * [The URL](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#the-url) * [Dynamic pages](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#dynamic-pages) * [Metadata](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#metadata) * [Page Title](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-title) * [Title (for SEO / FB)](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#title-for-seo-fb) * [Description (for SEO / FB)](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#description-for-seo-fb) * [Social Media Image](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#social-media-image) * [Example (OpenGraph)](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#example-opengraph) * [Page HTML Header and HTML elements](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-html-header-and-html-elements) * [Metadata settings in Bubble](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#metadata-settings-in-bubble) * [Accessing a page's metadata](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#accessing-a-pages-metadata) * [Populating metadata with dynamic content](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#populating-metadata-with-dynamic-content) * [Content](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#content) * [Design](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#design) * [Text](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#text) * [Media](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#media) * [Page load](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page#page-load) Was this helpful? Copy https/www.my-bubble-application/product/baseball-cap Copy https://my-bubble-application.com/product/product-1-1676895473036x923438355480530400 Copy Your Page Title Copy Copy --- # API Glossary | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/api-glossary.md) . Authentication and authorization[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#authentication-and-authorization) **Authentication** is the process of verifying the identity of a client sending an API request (**who** the client is). For example, the Bubble API can be set up to require a bearer token to prove the identity of the client trying to connect. This process of providing the credentials and the server verifies them is the authentication process. **Authorization** is the process of determining **what** a client has access to after they have authenticated themselves. It is the mechanism by which an API can determine what a user or system is allowed to do once they have been authenticated. For example, after a client has authenticated themselves with the Bubble API, the API will check your app's Privacy API settings, privacy rules and other details to determine whether they have access to specific [resources](https://manual.bubble.io/help-guides/integrations/api/api-glossary#resource) . **In short:** Authentication is the process of verifying **who** you are, while authorization is the process of verifying **what** you have access to. **Other ways to learn:** Article: [Authenticating with the Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication) Article: [Setting up Authentication in the API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/authentication) Article: [The Data API and Privacy Rules](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules) Article: [The Workflow API and Privacy Rules](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules) API[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#api) API stands for _Application Programming Interface_ and it is a set of protocols, routines, and tools for allowing different software systems to communicate with each other. Imagine you're at a restaurant. You, the customer, want to order food, but you don't go into the kitchen yourself. Instead, you give your order to a waiter. The waiter then goes to the kitchen, gets your food, and brings it back to you. In this scenario, the kitchen is like an external app or system (the server). You, wanting to get some data or service from this system, are the client. The waiter is like the API. Just as the waiter takes your order to the kitchen and brings back your food, the API takes requests from one app (the client) to another (the server) and returns the needed response. **Examples:** 1. **Data Retrieval:** Fetching data from a remote database, like getting weather updates from a weather service. 2. **Integration:** Connecting to different services, like integrating a payment gateway (e.g., PayPal or Stripe) into your app. 3. **Automation:** Performing tasks in other systems, like posting a social media post to LinkedIn or creating an appointment in Google Calendar. 4. **Enrichment:** Enhancing functionalities, like using a map API to display locations in your app. 5. **Authentication:** Verifying user identity and granting access using an authentication system like OAuth to log into your app through Google or Facebook credentials. **Other ways to learn:** Article: [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) Article: [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) Client/Server[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#client-server) In the context of an API call, the **Client** is the one that initiates the call and the **server** is the one to respond. In the case of an **incoming** API request (The Data API or Workflow API) the system sending the request is the **client** and the Bubble server that hosts your app is the **server.** In the case of **outgoing** API request (The API Connector) your Bubble app is the **client** and the system you are connecting with is the **server**. **Other ways to learn:** Article: [The Client/Server relationship](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#client-server-and-resource) Endpoint[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#endpoint) An endpoint is a specific URL that an application can send requests to, to retrieve or manipulate data. In the Bubble API, the endpoint is the URL that identifies a **data type** or a specific **API Workflow.** In outgoing requests made via the API Connector, the endpoint is the HTTP action and URL that you are pointing the call towards. **Other ways to learn:** Article: [Data API endpoints](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-endpoints) Article: [Workflow API endpoints](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-endpoints) HTTP Method / HTTP Verb[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#http-method-http-verb) The HTTP method is the instruction for the server to indicate the desired action to be performed on the specified [resource](https://manual.bubble.io/help-guides/integrations/api/api-glossary#resource) (e.g. GET, POST, PUT, DELETE). * **GET:** Retrieves data from a server (like viewing a webpage or getting a weather update). * **POST:** Sends data to a server to create a new resource (like adding a new calendar appointment to Google Calendar). * **PUT:** Updates an existing resource with new data (like changing the date of a calendar appointment in Google Calendar). * **DELETE:** Removes a resource from the server. (like deleting an appointment in Google Calendar) **Other ways to learn:** Article section: [What is the HTTP protocol?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-http-protocol) Article section: [What is the HTTP method?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#http-method) Article: [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) HTTP protocol[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#http-protocol) The HTTP protocol is the blueprint for how most data is exchanged between a client and a server. It defines how a request and response is formatted, so both systems understand each other. **Other ways to learn:** Article section: [What is the HTTP protocol?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-http-protocol) Article section: [What is the HTTP method?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#http-method) Article: [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) JSON[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#json) JSON is a lightweight data interchange format typically used in Javascript. It uses human-readable text to transmit data objects that consist of attribute–value pairs and array data types. It is commonly used both in incoming API Connections (the Data API and Workflow API) and outgoing API Connections (The API Connector). #### [](https://manual.bubble.io/help-guides/integrations/api/api-glossary#example) **Example** Below is an example of what JSON code may look like. In this example we're storing data about a user, and as you can see, it's easily readable both by humans and computers: `{` `"user": {` `"id": "123456",` `"username": "johnDoe123",` `"email": "johndoe@email.com",` `"firstName": "John",` `"lastName": "Doe",` `"birthdate": "1990-01-01",` `"profilePictureUrl": "https://example.com/profiles/johnDoe123.jpg",` `"phone": "555-1234",` `"joinedDate": "2022-04-20"` `}` `}` **Further reading:** API glossary: [Object / JSON object](https://manual.bubble.io/help-guides/integrations/api/api-glossary#object-json-object) Article section: [What is the JSON format?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api#what-is-the-json-format) Key-value pair[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#key-value-pair) A key-value pair is a basic data structure where a 'key' (a unique identifier) is linked to a 'value' (the data). It's used in many programming languages, and in Bubble you can often come across it when you work with the API Connector. For example, in the [JSON](https://manual.bubble.io/help-guides/integrations/api/api-glossary#json) code below, the text marked in bold are two key-value pairs: * Key: "id" - value: "123456" * Key: "username" - value: "johnDoe123" `{` `"user": {` `**"id": "123456",**` `**"username": "johnDoe123",**` `}` `}` Oauth2[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#oauth2) OAuth2 is a protocol used by a server to determine a client's authorization. It lets a User grant an app (like your Bubble app) access to the resources stored in an external app without having to share their login credentials with the first app. Instead, the server that hosts the external app will issue a token that your app can use to access the User's resources. That way, subsequent requests can be made without the User having to authorize each one or share their credentials. **Examples:** * A User wants to connect their social media account (such as Facebook or Twitter) to your Bubble-built social media management app in order to share posts automatically. The User grants your app access to their social media account using OAuth2, and your app is issued a token that it can use to post photos on behalf of the User. * A User wants to be able to automatically add appoints to Google Calendar when a meeting is booked in your Bubble-built CRM. The User grants your app access to their Google account your app is issued a token that lets your app make changes to the User's calendar as needed. * An enterprise clients wants to allow your app to access resources from their server without giving them actual login credentials. They use OAuth2 to issue a token to your app that you can use for subsequent calls. Object / JSON Object[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#object-json-object) A JSON object is a way to structure data in a way that both computers and humans can easily understand. An object can consist of multiple **keys**, and each key has a **value**. This is often called a key-value pair. In Bubble, consider the _User_ data type as an example. When you examine a User in Bubble, you'll notice it consists of various built-in and custom fields like email, name, and phone number. These fields act as keys in a key-value pair, and the specific information for each user (their actual email address, name, and phone number) represents the values. In JSON, a user object may look something like this: `{` `"user": {` `"first_name": "Ana",` `"last_name": "Silva",` `"email": "ana.silva@example.com"` `}` `}` As you can see, this is perfectly readable for a human, but the consistent structure also means computers can easily read it. The similarity to Bubble is not a coincidence – in fact, Bubble downloads data to the page in a JSON structure. This is why Bubble communicates with other apps and systems so easily – because JSON is a widely used format. Payload[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#payload) The payload refers to the data sent with the request. Depending on the [HTTP method](https://manual.bubble.io/help-guides/integrations/api/api-glossary#http-method) used, the payload can be part of the request body (as in a POST, PUT, or PATCH request) or within the URL itself (as in a GET request with query parameters). For most API interactions that involve the transmission of data (like creating a new user or updating a record), the payload carries the necessary information. #### [](https://manual.bubble.io/help-guides/integrations/api/api-glossary#example-1) **Example:** Imagine you're creating a new user in a system using an API. The API documentation specifies that the endpoint expects data like a username, email, and password. The payload for this API call might look something like this: `{` `"username": "johnDoe123",` `"email": "johndoe@email.com",` `"password": "securePassword123"` `}` In this example, the [JSON](https://manual.bubble.io/help-guides/integrations/api/api-glossary#json) structure containing the username, email, and password is the payload. When making a POST request to the API endpoint, this payload would be included in the body of the request. The API server processes this payload and performs the necessary actions, such as creating the user in the database. Resource[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#resource) A resource is a specific data object or service that is made available by an API and can be accessed via a unique endpoint using methods such as GET, POST, PUT, and DELETE. For example, if you are trying to access data about a specific User in your Bubble app from an external application, the _User_ endpoint can be considered a resource. The same can be said about a specific API Workflow. In other words, a resource represents a specific piece of information or functionality that an API can provide. **Other ways to learn:** Article: [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) Request/Response[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#request-response) In an API call, the **request** is the data sent from the client to initiate the connection. It contains all the data needed to authenticate and instruct the server what the request is about. The **response** is the data sent back from the server to the client in response to the request. **Further reading:** Article: [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) RESTful[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#restful) APIs that are RESTful mean that they are built on a set of architectural principles for building web services known as _Representational State Transfer (REST)_. Most commercial and public API services adhere to these principles. In short, this is a way to ensure that APIs that communicate with each other are compatible, or "speak the same language" if you will. Bubble's API and the API Connector is built around RESTful principles, which means it can connect to almost any web API. **Other ways to learn:** Article: [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) Token[](https://manual.bubble.io/help-guides/integrations/api/api-glossary#token) A token is a string that identifies the client sending an API request. In the case of **incoming** requests (The Data API or Workflow API) the token is issued by Bubble. In the case of **outgoing** requests (The API Connector) the token is issued by the server you are connecting to. #### [](https://manual.bubble.io/help-guides/integrations/api/api-glossary#how-are-tokens-different-from-username-password) How are tokens different from username/password? A token is a unique, randomly generated string that confirms a user's session or authorization, usually given _after_ the first login. It lets users access services without constantly inputting their username/password, enhancing security. Think of it like this: If a user logs into your app using Facebook, they don't hand over their Facebook login details to your app. Instead, Facebook verifies their login and hands your app a token as proof. A key advantage is that tokens can be swiftly revoked, making them more secure and flexible compared to the traditional username/password method, which can be tedious to alter. **Other ways to learn:** Article section**:** [What is a bearer token?](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai/authentication#the-bearer-token) Last updated 22 days ago Was this helpful? Was this helpful? --- # Introduction to APIs | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis.md) . This chapter covers how RESTful APIs work in general. If you want to skip to the section where we cover Bubble’s API features, you can click the link below: Article: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) Throughout the API section you may also find our [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) useful. There are many different kinds of API calls but they mostly follow the same kind of pattern. The most simple definition of an API call can be summed up in two steps: * The **client** will send a request to another system * The **server** sends a response back. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#introduction-to-apis) Introduction to APIs ----------------------------------------------------------------------------------------------------------------------------- Our in-depth API course gives an introduction to what APIs are and how to use the [API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) When you want to connect your Bubble app to another application or data source, you use an API. An API is a set of principles that allows two applications to speak a common language, allowing them to establish a connection securely and exchange information and trigger workflows. The technology has been around for several decades. going as far back as the 1960s and 1970s, when computer programs were first being developed for commercial use. While the technology and security has evolved since then, many of the basic principles still apply. Bubble is set up to take care of a lot of the technical stuff for you. This lets you set up both incoming and outgoing connections securely and efficiently. Still, it can be useful to know what's going on under the hood to understand what the different settings and values in an API call mean. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#example-of-api-call-in-action) Example of API call in action: ------------------------------------------------------------------------------------------------------------------------------------------------ > _Imagine you have built a travel planning software in Bubble that displays the weather forecast for a specific location at some time in the near future. In order to get the weather data, your app (the client) must send a request to the server of a weather service (the server). The server processes the request, retrieves the weather data, and sends it back to the app in a format that your app can understand. You take this data and display it in a user-friendly way. The whole process is usually finished in a few hundred milliseconds._ APIs allow you to request specific information or execute commands within very specific constraints in the external application, but they don't provide access to how the application actually works. For example, contacting a weather service doesn’t give you any say over how the weather data is stored and processed – it only gives you a short piece of text data in response to your exact request. In other words, APIs provide a line of communication without revealing the inner workings of the external application. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FgSljyyLZqCjw854L1omN%252Fweather-api-bubble.jpeg%3Falt%3Dmedia%26token%3D2ba58add-83dc-4b53-baa4-b7b63a91299a&width=768&dpr=3&quality=100&sign=cdc38248&sv=2) Showing up-to-date weather predictions is one use case where your app would be likely to depend on an external API service to get accurate data. In a way, it’s like ordering food at a restaurant: the menu presents you with a static set of options and whatever you pick it will be prepared to you out of sight. You don’t have access to the kitchen and the chef gets to keep their secret recipe secret. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#incoming-and-outgoing-connections) Incoming and outgoing connections ------------------------------------------------------------------------------------------------------------------------------------------------------- Since two systems can communicate with each other, it follows that connections can go in both directions. This means that your Bubble app can connect to a third party, and that a third party can connect to your Bubble app. We sort these two types of connection into two categories: ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#incoming-connections) Incoming connections Incoming connections means that another system can initiate a connection and have your Bubble application: * Send data back * Make changes to your database (create, modify or delete one or more records) * Run a specific API Workflow Being able to share data and commands across apps opens up a world of possibilities where you can use different technologies and services together in creative ways. > In many ways, the API standard is powering a big part of the web as we know it today. When you activate the Data API or Workflow API, Bubble automatically sets up your app to be ready to accept incoming connections, making it quick and easy to expose your application’s data to other systems in a secure and controlled way. Setting up incoming connections to a Bubble app[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#setting-up-incoming-connections-to-a-bubble-app) To send data requests to a Bubble application, you activate and use the **Bubble API**. You can read our in-depth article on the Bubble API [here](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) . ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#outgoing-connections) Outgoing connections Outgoing connections means that your application initiates a connection with another system to: * Retrieve data from that system. * Send data to that system. * Access functionality or features provided by that system. Using outgoing connections you can do things like: * Fetch data like weather reports, stock prices, animated GIFs and social media profiles. * Send data like adding a calendar event to Google Calendar, creating an invoice in Freshbooks or adding a new contact to HubSpot CRM. * Signing the user in using an existing account in another system (such as Google, Facebook and LinkedIn). * Start a workflow like sending an email with SendGrid, making a payment with Stripe or Paypal and sending an SMS with Twilio. Making outgoing API requests from a Bubble app[](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#making-outgoing-api-requests-from-a-bubble-app) There are two ways to make outgoing API requests from a Bubble application. You can use the [API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) or you can browse for a [plugin](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis) in our [plugin store](https://bubble.io/plugins#!) . [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#client-server-and-resource) Client, server and resource ------------------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#client-and-server) Client and server Whenever an API connection is established there are two parties involved: the client and the server. The client is the one that **sends the request**, and the server is the system that **responds**. * If you are connecting to a third party using the API Connector or a plugin, your app is the **client** * If another system is connecting to the Bubble API in your app, your app is the **server** ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FG0TSO4vDP06sIMOtFG0Z%252Fserver-client-relationship.jpeg%3Falt%3Dmedia%26token%3Dfa8ff3f2-1eb1-48ad-9c22-f9b7cdd5597e&width=768&dpr=3&quality=100&sign=10332eb0&sv=2) API calls consist of a request sent by the _client_, and a response sent back by the _server_ ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#resource) Resource A resource is a specific piece of data or functionality that can be accessed through the API. Many APIs expose multiple resources, which means that the client has to specify what resource they want to access. For example, a third-party system might connect to your Bubble application to fetch a list of users, create a new database record or start a workflow: each of these would be considered a resource that this client can access. If your app is connecting to an external system like a CRM to create a contact, fetch a list of calendar events or send a customer email, each of those operations would also be a separate resource. Resources are typically accessed through a specific URL that points to that resource. Bubble offers two kinds of resources, and URLs are generated automatically whenever a resource is set to be exposed in your app’s API: * **Data types** in your database can be exposed to allow other systems to read, create, modify and delete records. Each of your exposed data types and each action (create, edit and delete) connected to that data type is a resource that can be accessed from the outside. This is done with the Data API. * **Workflows** can be exposed to allow other systems to trigger them. Each workflow that you set up and expose is a resource. This is done with the Workflow API. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#authentication-and-authorization) Authentication and authorization ----------------------------------------------------------------------------------------------------------------------------------------------------- When we discuss APIs, we need to make a clear distinction between two similar-sounding words: **Authentication** is the process of verifying the identity of the client that is trying to access the server. You can compare this to a passenger wanting to board an airplane. At some point the passenger will reach a security checkpoint where they have to present valid credentials to confirm their identity, usually in the form of a passport. In other words, authentication is about asking **who the client is.** ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FRuxi0Oh5kFl4JzgmVGEY%252Fauthentication-bubble.jpeg%3Falt%3Dmedia%26token%3D2108a28a-f76c-42aa-87f8-6c0018441c88&width=768&dpr=3&quality=100&sign=ef5bb99f&sv=2) Authentication identifies **who** the client is and authorization determines **what** they should have access to. **Authorization** happens after authentication, and is the process of determining whether a client has the necessary permissions to perform a particular action or access a particular resource on the server. Returning to our airport example, after we know who the passenger is, we can determine whether they have access to board the plane and the VIP lounge. In other words, authorization is about asking **what the client is allowed to do**. Whenever a third-party system attempts to connect to your app, you can use these two security processes to have complete and secure control over who can connect and what they can access. Whenever the connection goes the other way, your app may be asked to go through the same steps. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#webhooks) Webhooks ----------------------------------------------------------------------------------------------------- Sometimes two applications need to exchange some sort of info in real-time – that is, when a specific event occurs in one app, another app should be notified of the event. This kind of call is often called a _webhook_. Even if the term webhook is used, it's not technically different than any other API call, except that it's created with the specific purpose of being made when a specific event occurs. ### [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#webhook-examples) Webhook examples * A payment gateway such as Stripe may inform your app whether a payment attempt was successful or not * An inventory platform (such as Shopify's inventory module) may need to notify your app when the inventory of an item is running low or out * A CRM may send a webhook whenever a new lead is created * A booking platform like Calendly may send a notification whenever a new appointment is booked As you can see from the examples, webhooks can be considered time-sensitive API Calls that keep systems in sync. Just like any other API Calls they can contain parameters that carry important information about the event about which they're reporting. For example, a payment webhook call from Stripe may contain information such as the sum captured, the payment ID and the customer ID. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fxrj0KJhsYBvbi1BekXa1%252Fwebhook-example.jpeg%3Falt%3Dmedia%26token%3Dd7e6b61f-0c9a-482b-b2fd-6004d9548e0d&width=768&dpr=3&quality=100&sign=ee84c3ae&sv=2) A **webhook** is an API Call that's made as a result of a specific event. For example, Stripe may send a webhook to your app to confirm that a payment was successful. Also just like other workflows, webhooks can connect to your Data API to make changes in the database or to the Workflow API to trigger a workflow in your app. [](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#recap) Recap ----------------------------------------------------------------------------------------------- We’ve covered how an an API is a common language for apps to be able to exchange information and give each other commands. You can set up your Bubble app to initiate outgoing connections to other systems, and you can offer an incoming connection for other systems to speak to your app. By using online tools you have most likely already witnessed the use of a long list of APIs without knowing it: your local newspaper getting updated weather reports, sports statistics and showing Google maps, an eCommerce website accepting payments through Stripe, Paypal and Authorize.net and a social media marketing platform scheduling posts on Twitter, LinkedIn and Instagram are all examples of apps working together by use of APIs. Bubble automates a lot of the work that goes on behind the scenes to make it easy and safe to make connections that go both ways. In the next section we'll take a more in-depth look at what exactly a RESTful API is. [What is a RESTful API?](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api) [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) [The API Connector](https://manual.bubble.io/help-guides/integrations/api/the-api-connector) Last updated 22 days ago Was this helpful? * [Introduction to APIs](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#introduction-to-apis) * [Example of API call in action:](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#example-of-api-call-in-action) * [Incoming and outgoing connections](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#incoming-and-outgoing-connections) * [Incoming connections](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#incoming-connections) * [Outgoing connections](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#outgoing-connections) * [Client, server and resource](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#client-server-and-resource) * [Client and server](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#client-and-server) * [Resource](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#resource) * [Authentication and authorization](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#authentication-and-authorization) * [Webhooks](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#webhooks) * [Webhook examples](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#webhook-examples) * [Recap](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis#recap) Was this helpful? --- # Performance | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md) . The Bubble team is constantly looking to optimize scalability and performance. This means improvements to both the Bubble platform to handle all the thousands of Bubble apps (our scalability and performance), as well as to the platform so that Bubble apps provide a good experience for their end-users. Performance and scaling of a Bubble app are heavily impacted by how the app is built. This page will give an overview of app performance and scalability as well as offer some concrete tips. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#general-principles-and-tips-about-performance) General principles & tips about performance ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ * **The less data being fetched, the faster the performance** - a page often needs to fetch some data on page load; a page that fetches 100 things on page load will load faster than a page that fetches 1 million data items; similarly, fetching simple data types like numbers will be faster than fetching MBs of data * **Similarly, having many small, simple pages will be faster than having fewer, complex pages** * **Keep any sorting or filtering as close to the original search as possible** - Bubble already optimizes database queries in many ways, but performing a sort or filter at the database level is very efficient. This means that queries that apply :sort or :filter to them will tend to be more efficient than queries with sorting or filtering after some other kind of manipulation of the results (example: doing search:count will be more efficient than search:group by:count) * **Using advanced filters can slow queries down** - An underlying principle is that if a filter (or sort) can be done "on the database", it will be faster than a filter (or sort) that Bubble has to do after retrieving an initial set of data from the database. Which filters are done on the database vs. not? Filters which show up in the Search palette (the additional sidebar which slides out when you click "Do a search for") are done on the database and are thus are generally fast. Filters which are applied with :filter are generally "advanced" filters that are generally slower. * **Chained queries run in series, not in parallel** - With Bubble it's possible to use the results of one search as the constraints of another search, and so on. These searches run in series, not in parallel, so if the first search returns a lot of data, that will slow the second search down, and so on * **Bubble already does a lot of performance optimization** - Bubble tries to run queries on the database, resize images on the server, tell the browser to cache Javascript, etc. as appropriate. If you're running a query that feels relatively simple and retrieves a relatively small amount of data that's running very slowly, check if there is some optimization that can be done to the app's data hierarchy or queries, based on some of the guidance here * **In general, the simpler way to express a query is faster** - Not always true but a good rule of thumb. Bubble is constantly working on database optimizations for the most common patterns * **Avoid modifying data on every page load** - Changing element states is more performant than making additional database calls to accomplish the same behavior * **Try moving expensive calculations to behind-the-scenes scheduled workflows** - A scheduled workflow can run the heavy query then save the result somewhere to use later; this is more performant than running the heavy query on a page load * **Use the "Make changes to a list of X" workflow action cautiously** - This action is great when making a quick change to a short list of things, but as the number in the list grows, it quickly raises the risk of the workflow timing out. If you're experiencing timeouts with this action, consider instead "Schedule API Workflow on a list", which is more performant because it takes the list and schedules an API Workflow to run on each item of the list, separately (i.e. lowering the risk of a timeout) Watch out! Your Bubble app's database is very flexible and powerful. It can store a lot - but if you try to store too much data in one field, it can lead to performance issues relating to that field. For example, if you have a Blog data type with a field for Contents, this should be able to handle blog posts just fine. But, if you try to stuff all the contents from Wikipedia into that one field, it probably will not work as well! More realistically, if you try to store a base64-encoded image (which is a lot of text) in a text field, this can lead to slower performance and unexpected behavior. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#what-happens-on-page-load) What happens on page load? ----------------------------------------------------------------------------------------------------------------------------------------------------- Here is a rough sequence of events of what happens when Bubble loads a page: 1. Bubble sends the code for all the elements (visible and invisible) 2. Bubble draws all the _visible_ elements on the page 3. Bubble fetches all the dynamic data needed for the _visible_ elements This means: * Invisible elements aren't drawn until they get displayed later... * ...unless a visible item refers to an invisible item's data source. (Note that using one visible element to cover another visible one does not make the latter one "invisible" in this context!) * For page load speed, the number of elements is a bigger factor than the type of elements All the element types are fairly similar to each other in terms of performance, with two exceptions: 1. Repeating groups load different amounts of data depending on the Layout Style property; notes on performance of the different choices are in the [Reference](https://bubble.io/reference#Elements.RepeatingGroup.data_source) . Note also that the more elements there are in each cell of the repeating group, the more time it takes to render the page 1. A repeating group with 10 cells each with 2 elements is faster than 20 separate elements, but slower than 3 elements 2. A _nested_ repeating group has a multiplicative effect on the number of elements! 2. Plugins have their code included on each page load regardless if it's used. This isn't as big a performance impact because Bubble won't _render_ the plugin if it's not used, but in general, it's a good idea to uninstall plugins that the app isn't using [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#additional-notes-about-performance) Working with soft limits ------------------------------------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#hard-vs-soft-limits) Hard vs soft limits Before we look at how different limitations might affect your project, we'd like to briefly cover the concept of hard and soft limits: **Soft limits** are flexible boundaries that can be exceeded in but may impact performance or stability. Soft limits are influenced by factors such as the structure of your application and your pricing plan. For instance, a large volume of database records with substantial data can result in slower search performance. **Hard limits** are fixed boundaries that cannot be exceeded. Some hard limits can be increased by upgrading to higher pricing plans, and others can be circumvented through thoughtful app design and optimization, but as a developer you should be aware of them and how they might affect your project. You can read more about hard limits in our dedicated article on the subject: Article: [Bubble's hard limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits) ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#timeouts) Timeouts Timeouts can happen when a specific action takes too long to complete and is terminated by the system. They are used to prevent a single request or app from monopolizing server resources, to make sure that all applications on our shared servers remain responsive and performant. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#predicting-and-planning-for-limitations) Predicting and planning for limitations As with any database system, slowdowns, timeouts and errors when applying pressure on the Bubble server can be challenging to predict and plan for and depend a great deal on how your app is designed and the volume of data you are working on. Timeouts are rare, but can be challenging to predict and can lead to data loss and other consequences as a result of a process being terminated before it has finished. While we can document the hard limits you might encounter, soft limits are more complex as they can vary greatly depending on what your app is doing. To minimize the risk of slowdowns and timeouts, we recommend you break up complex processes into smaller chunks. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#throttling-and-how-it-may-affect-timeouts) Throttling and how it may affect timeouts If your app spends its near-maximum allotted capacity for some time (closing in one one minute), your app may be throttled to keep it running without exceeding capacity. This can lead to a negative feedback loop where workflows are slowed down and exceed their hard timeout limit as a result. Therefore, timeouts may appear to be unpredictable, as a process may complete successfully on one occasion but time out on another. We recommend thinking holistically about your app's total capacity and keep in mind that simultaneous process can affect each other. If you can, try to move heavy processes to times when your app is less active (for example at times where you have fewer active users) [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#known-soft-limits) Known soft limits ------------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#svg-image-size) SVG image size SVG images are stored in XML code which is parsed by your browser to render a vector-based graphic that can be scaled up or down without losing resolution. This is different from raster images, such as JPEG or PNG files, that can become pixelated when scaled beyond their original size. This makes SVG files very useful in many situations, but we recommend a **soft limit of 1 Mb** for SVG files to avoid the local device slowing down when processing the file. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#searches-with-the-advanced-constraint) Searches with the :advanced constraint Searches that use the :advanced operator can be more taxing on the server. While there's not a hard limit on what you can search through, we generally don't recommend using this constraint on more than 10,000 things. [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#additional-notes-about-performance-1) Additional notes about performance ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ The power of reuse: * If a page has the same search in more than one place, Bubble will automatically combine them to run the query once * Leveraging Styles helps improve performance * The first few times you run a particularly heavy search might be a bit slower than future runs, because after Bubble sees a heavy query run a few times, Bubble builds an index that should massively speed up the search in the future (building the index could take up to an hour or so) X vs Y: * An action that changes a dozen fields is more efficient than a dozen actions that change one field * Changing a list of things is fast for relatively small lists, but for bigger lists, an API workflow will be more scalable since it doesn't run the risk of timing out the workflow * When changing a (large) list, recursively calling an API workflow for subsequent items on the list is more scalable, though a bit slower, than running the API workflow on the entire list at once * Navigating to a new page via a link element is generally a little bit faster, because workflow actions that navigate will wait on other workflows to save data before changing the page * For situations where data type A has connections to multiple Bs (e.g. posts having categories but only one category per post; A = category, B = post), having a field on B that references the A it belongs to is generally better. Having a field on A that lists out all the Bs that belong to it is not going to work as well when that list can get very long * For API workflows, the number of items the workflow has to act upon is a bigger impact on performance than the size of each item [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#capacity) Capacity ------------------------------------------------------------------------------------------------------------------ In non-technical terms, "capacity" measures how much "stuff" your app can do in a given period of time. A user coming to your website uses a bit of capacity; having hordes of users coming to your website uses much more capacity. Calling the database uses capacity; performing lots of heavy database queries uses much more capacity. Running certain workflows (the ones that happen on the server) uses capacity, and similarly calling an app's APIs uses capacity. Throughout Bubble, there are references to "units" of capacity. A "unit" is a weighted measure of different scarce resources that Bubble's systems use; it includes factors like server CPU time, database CPU time, other backend systems, and more. The exact formula for a "unit" will change over time as Bubble adds, removes or improves backend systems; one of Bubble's goals is to improve the amount of user-facing performance that a unit of capacity delivers. On certain Bubble [pricing tiers](https://bubble.io/pricing) (namely Free and Personal), the app will have "Basic" server capacity, which means it's sharing the same computing resources with all other Bubble apps of these tiers. When an app is upgraded to the "Professional" and "Production" tiers, the app gets dedicated or "reserved" units of capacity which are reserved for that app. When capacity is exceeded, the app is rate-limited; again in non-technical terms, it means the app won't be able to do as much "stuff" in a given period of time, and users' requests on the app will effectively be slowed down. Thus, having more capacity generally means that the app can do more "stuff" if a lot of "stuff" is going on. There's a slight twist to this. Capacity can be compared to how many checkout lines there are at a grocery store. If the store adds more lines, it can handle more customers checking out at the same time. But, if a customer comes along with a cart of hundreds of items, that customer will still take up a whole checkout line for a while; also, having more checkout lines doesn't mean that resource-intensive customer will finish faster. Similarly, having more capacity won't make a very complex database query run that much faster - it's like that one customer checking out with a lot of items in their cart. (There is a caveat to this: if Bubble detects that a large query will eat up all of an app's capacity, Bubble will slow down that query to try to maintain a reasonable user experience for the rest of the app. Thus, in certain situations, adding capacity _might_ make a large query run faster.) Users can see how much capacity their apps are using by going to Logs on the left-side nav. The first chart shows how much time the app has hit its maximum capacity; the second chart shows how much capacity has been used by the app relative to its maximum capacity. Further down on the page is the server capacity usage details chart, which shows the breakdown of capacity used by different parts of the app within the past 24 hours. If an app is slow and is hitting capacity limits, purchasing reserved additional capacity may help. **Note:** Our server logging provider, AppOptics, has limits on the metric we use for the Maximum Capacity charts. Very high-activity Bubble apps may hit this limit when trying to query the logs for a long time period (i.e. 30 days). If this happens in your app, consider setting the chart date range to a shorter duration (i.e. 7 days). [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#what-about-dedicated-instances) What about dedicated instances? --------------------------------------------------------------------------------------------------------------------------------------------------------------- Dedicated instances can help with performance in three primary ways: 1. Geography - a dedicated instance can be located geographically closer to your users, which helps with the performance of large static assets 2. Heavy data operations - these can be substantially faster on a dedicated instance 3. Stability - with dedicated instances you can test an app on the main Bubble cluster before upgrading the dedicated instance; this can be useful for ensuring an app's stability with a new version of Bubble, as well as eliminate the risk of a Bubble-wide outage If you're interested in hosting your app on a Dedicated instance of Bubble and want to learn more, please contact our sales team [here](https://bubble.io/contact-sales) . [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#in-closing) In closing ---------------------------------------------------------------------------------------------------------------------- At the end of the day, the above are general guidelines that are meant to provide some transparency into factors impacting performance. However, these are only guidelines; if performance is critical in a particular case for your app, try testing different approaches empirically to see what's faster![](https://manual.bubble.io/architecture-optimization-and-limits-of-the-bubble-engine) Last updated 2 years ago Was this helpful? * [General principles & tips about performance](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#general-principles-and-tips-about-performance) * [What happens on page load?](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#what-happens-on-page-load) * [Working with soft limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#additional-notes-about-performance) * [Hard vs soft limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#hard-vs-soft-limits) * [Timeouts](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#timeouts) * [Predicting and planning for limitations](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#predicting-and-planning-for-limitations) * [Throttling and how it may affect timeouts](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#throttling-and-how-it-may-affect-timeouts) * [Known soft limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#known-soft-limits) * [SVG image size](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#svg-image-size) * [Searches with the :advanced constraint](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#searches-with-the-advanced-constraint) * [Additional notes about performance](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#additional-notes-about-performance-1) * [Capacity](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#capacity) * [What about dedicated instances?](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#what-about-dedicated-instances) * [In closing](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling#in-closing) Was this helpful? --- # SEO: App | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app.md) . The technical side of SEO starts on the app level. Search engines look at your site as a collection of pages under an umbrella: _your_ _domain_. The settings that you set on the app level are less about the identity of your app (with the exception of social media sharing, which we'll cover further down), and more about providing **instructions** to the search engines, such as: * Which pages to crawl and not to crawl * URLs that have been moved and should be redirected to another URL (301 redirect) * To read a sitemap file Some parts of your app's SEO settings can be fairly technical, but if you are not sure if you need them right now, then you most likely don't. We will still cover the basics of each part here. Your app's SEO settings are found under _Settings - SEO/Meta tags:_ ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FqOtkU7hRX6HhWuCmrJBL%252Fseo-settings%25402x.png%3Falt%3Dmedia%26token%3D35db5d88-d9e7-4182-80f3-14884b751ab0&width=768&dpr=3&quality=100&sign=ce8c1d7b&sv=2) [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#sharing-in-social-media-opengraph) Sharing in social media (OpenGraph) ---------------------------------------------------------------------------------------------------------------------------------------------------------- The first part of your app's SEO settings are the OpenGraph details. This lets you set an identity for your app that social media sites such as LinkedIn, X and Facebook will use when a link to your app is shared. OpenGraph metadata can also affect how your page ranks and is displayed in search engines. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FU1A1rIxpIeHZyZKkvYKR%252Fseo-settings%25402x.png%3Falt%3Dmedia%26token%3D5d0763b4-076d-4b34-87ee-e21afabe3f7a&width=768&dpr=3&quality=100&sign=f4e14847&sv=2) In the example below from LinkedIn, you can see how as soon as a link is typed into a post, LinkedIn fetches the metadata. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FsUqk0WErM8S7M9exBTVM%252Fsocial-media-sharing%25402x%2520%281%29.png%3Falt%3Dmedia%26token%3D29e73178-249b-4d78-b292-dcedb7a91c2f&width=768&dpr=3&quality=100&sign=50b76c7&sv=2) This helps you convey a consistent brand identity across both social media and search. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#seo-settings) SEO settings -------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#setting-up-headers-less-than-h1-greater-than-less-than-h2-greater-than-less-than-h3-greater-than) Setting up headers (

,

,

) The structure of your page plays a role in determining its ranking. A well-structured page involves organizing your text content into distinct sections, each separated by headers at various levels (such as "`

` and "`

`"). By default, the setting to add a tag to a text element is not available, but you can enable it by checking _Expose the type of tags for text elements_. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#canonical-urls) Canonical URLs Imagine you have a well-researched article in your app, and for some reason, it exists in two different places with slightly different URLs. This situation can create confusion for search engines, as they struggle to determine which version should be displayed in search results. Canonical URLs are the solution to this problem. They act as a signal to search engines, specifying which version of a webpage should be considered the "primary" or "preferred" one. By using a canonical URL, you help search engines avoid indexing multiple versions of the same content, thereby improving your website's search ranking and overall visibility. The setting _Point URLs to primary domain for better SEO_ enables a Bubble-defined canonical url tag. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#robots.txt) Robots.txt Sometimes, you will want to instruct search engines to _not_ crawl specific pages in your app. For example, if your app has a front-facing index page with other pages like _about_ and _privacypolicy_ you will want those indexed, but you may not want to index backend or admin pages. Robots.txt (see [example](https://bubble.io/robots.txt) ) is a small file that Bubble automatically places in the root directory of your app. It contains instructions to search engine crawlers, specifying which parts of the app they are allowed to access and which parts they should avoid. By default the development version of your app isn't indexed. Keep in mind that robots.txt is a _request_ to search engines to avoid crawling certain pages. While most search engines will respect this, it doesn't actually _stop_ them from crawling. So this is considered an SEO setting – not a security setting. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#how-do-i-instruct-search-engines-to-hide-a-page) How do I instruct search engines to hide a page? Let's say that you want to hide the two pages _dashboard_ and _admin_ from crawlers. You use the _Disallow_ command in robots.txt along with the page name to do so: ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#sitemaps) Sitemaps Web crawlers work by following links. If they discover your app's domain and its front page, and this page links to a page called _about_, then the crawler will also index that page. But what if a page _isn't_ linked to? Or if a page contains dynamic content (such as www.myapp.com/products/running-shoes) – you may link to the product page, but not to every product in your inventory – which is probably the part you want to index. Keep in mind that for pages with dynamic content, each thing counts as its own separate page, even if they are all loaded on the same page. Sitemaps are like blueprints for your app that help search engines navigate and understand your app's structure more efficiently. They are essentially XML files that list all the pages within your app even if they are not linked to. Bubble can automatically generate a sitemap for all your pages, and for dynamic pages we will include the things in your database that matches the data type specified on the page. You can select which pages you want to include in the sitemap. When you check the _Expose a sitemap file_ box, a list of your pages is displayed. Check each page that you want to include. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#custom-header-and-body-content) Custom header and body content All the script and meta tags placed in the header will be inserted between the `` tags on every page of your app, while the scripts added to the body field will be positioned between the `` tags across all pages. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F70Zp7HWRU2PNh2CpMoRJ%252Fheader-body%25402x.png%3Falt%3Dmedia%26token%3D55e428ad-e805-425f-b87f-71c18229c35b&width=768&dpr=3&quality=100&sign=bdbbde37&sv=2) Adding data to this field will add it to all pages – you can also add it to pages one-by-one in the [settings for each page](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page) . [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#id-301-redirects) 301 redirects ------------------------------------------------------------------------------------------------------------------- A 301 redirect is a permanent redirection method that helps maintain SEO performance when a page moves to a new location. It simply says: * The page used to be _here_ * ... and now it's _here_ * ... and it's _permanent_ (301) Bubble offers an easy way to add a _before_ and _after_ URL. The URLs should be the _full_ URL (including the protocol such as https): #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#seo-ramifications-of-301-redirects) SEO ramifications of 301 redirects From an SEO perspective, this is important for a few reasons: * It helps the search engine find the new page when the old one is missing * It tells the search engine that the content on the new page is not duplicated – it has simply moved * It ensures that any referral traffic still reaches the right content #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#when-are-301-redirects-useful) When are 301 redirects useful? 301 redirects is useful in any case where you need to instruct search engines that a page has moved. * Whenever you rename a page * Whenever you change the slug of a thing you are using as dynamic page content * If you are moving from a non-Bubble framework and your URL structure or domain changes ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#using-wildcards-in-301-redirects) Using wildcards in 301 redirects Wildcards in 301 redirects allow you to dynamically match parts of a URL and redirect them to a new URL structure. This functionality is especially useful when dealing with groups of URLs that follow a consistent pattern, reducing the need to create individual redirects for each URL. Wildcards are represented by an asterisk (\*), which acts as a placeholder for dynamic content in the URL. These placeholders can then be referenced in the destination URL to preserve or reorder the dynamic parts of the original URL. For example: **From:** `https://www.example.com/page1/*` **To:** `https://www.example.com/page2` A request to https://www.example.com/page1/_anything_ will redirect to https://www.example.com/page2. Wildcards can also represent multiple dynamic parts in the URL, which can be carried over to the destination using placeholders like %1, %2, etc., corresponding to the order of the wildcard matches. #### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#how-to-use-wildcards-in-301-redirects) How to use wildcards in 301 redirects To enable and use wildcards in 301 redirects, follow these steps: **Enable Wildcards** * Check the box labeled _Allow wildcards in redirects for more dynamic urls_ in your redirect settings. * Note: Exact matches for 301 redirects will work regardless of whether this checkbox is enabled. **Set up the redirect rule** * Replace dynamic parts of the source URL with \* to indicate wildcards. For example: * `https://www.test.com/page1/*` -> `https://www.test.com/page2` **Use placeholders to preserve data** Wildcard matches can be preserved in the destination URL by referencing them using %1, %2, etc.: * %1 corresponds to the first \* in the source URL. * %2 corresponds to the second \*, and so on. For example: `https://www.test.com/page1/*/*` -> `https://www.test.com/page2/%1/%2` **Ensure accuracy in the structure** While wildcards allow dynamic matching, the slashes (/) in the source and destination URLs must remain accurate and consistent. For example: `https://www.test.com/page1/*/*` -> `https://www.test.com/page2/%2/%1` **Query string behavior** URL parameters (the query string) are automatically copied over to the destination URL, regardless of the wildcard setup. For example: A request to `https://www.test.com/page1/abc?user=123` will redirect to `https://www.test.com/page2/abc?user=123`. ### [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#hosting-files-in-root-directory) Hosting files in root directory Bubble lets you upload files to the root directory. There are many use cases for this, but from an SEO perspective the most common use is to upload a custom sitemap .xml file. [](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#seo-audit-criteria) SEO audit criteria -------------------------------------------------------------------------------------------------------------------------- Chrome features an integrated SEO audit tool (found in Inspector > Audits). This tool highlights criteria that may impact your search results. Below is an overview of each criterion and how Bubble apps fare: Audit criteria Mobile-friendly Use the responsive engine and set up pages that follow mobile best practices tag Bubble handles this automatically Title Set up titles on all pages and remember dynamic content Meta description Set up descriptions on all pages and remember dynamic content HTTP status code Bubble handles this automatically Links have descriptive text Set up all your links with descriptive texts Page isn’t blocked from indexing Bubble handles this automatically "robots.txt is valid Bubble handles this automatically, but you can also [customize it](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#robots.txt) Image elements have \[alt\] attributes Add alt tags to all images in the property editor of each image Document has a valid hreflang Bubble handles this automatically Document has a valid rel=canonical Bubble handles this automatically, but you can also set up [301 redirects](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#301-redirects) Document uses legible font sizes Font sizes less than 12px are too small to be legible. Use it sparingly (60% of text above bigger than 12px) Document avoids plugins This does not apply to Bubble (_plugins_ here does not refer to Bubble plugins) Last updated 22 days ago Was this helpful? * [Sharing in social media (OpenGraph)](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#sharing-in-social-media-opengraph) * [SEO settings](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#seo-settings) * [Setting up headers (

,

,

)](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#setting-up-headers-less-than-h1-greater-than-less-than-h2-greater-than-less-than-h3-greater-than) * [Canonical URLs](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#canonical-urls) * [Robots.txt](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#robots.txt) * [Sitemaps](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#sitemaps) * [Custom header and body content](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#custom-header-and-body-content) * [301 redirects](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#id-301-redirects) * [Using wildcards in 301 redirects](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#using-wildcards-in-301-redirects) * [Hosting files in root directory](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#hosting-files-in-root-directory) * [SEO audit criteria](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app#seo-audit-criteria) Was this helpful? Copy User-agent: * Disallow: /dashboard Disallow: /admin Copy ❌ www.bubble.io/page Copy ✅ https://www.bubble.io/page --- # Bubble API terminology | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology.md) . As we've seen in the articles so far in our [Introduction to APIs series](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis) , working with APIs you come across a comprehensive terminology that was not invented by Bubble but has been around for years or decades. You can find a list of some these in our [API Glossary](https://manual.bubble.io/help-guides/integrations/api/api-glossary) . Bubble also introduces its own terminology to describe different parts of its API. To new users they may seem confusing and sometimes overlapping at first and this article will go in-depth in the different terms we use. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#quick-reference) Quick reference ------------------------------------------------------------------------------------------------------------------------------------ Bubble API Umbrella term for the Data API and Workflow API Data API The part of the Bubble API that deals with direct requests to the database Workflow API The part of the Bubble API that deals with requests to trigger API workflows API Workflow The workflow itself that you create and manage in the backend editor Backend workflow Umbrella term for the different workflows available in the backend editor (API Workflow, Database Trigger, Recurring event and Custom event) [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-bubble-api) What is the Bubble API? --------------------------------------------------------------------------------------------------------------------------------------------------- The term Bubble API describes the full suite of API capabilities that Bubble can offer to other applications. In other words, any **incoming** connection to your application is connecting to the Bubble API. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FHWMXCQ8wGUKVLxJggLRG%252Fbubble-api-flow.jpg%3Falt%3Dmedia%26token%3Dce9fee1e-4958-4e3b-96f3-c1b443f076c2&width=768&dpr=3&quality=100&sign=caf0c78&sv=2) Whenever a call reaches the Bubble API it is routed to the Workflow API or the Data API depending on the instructions in the request You can see the Bubble API as an umbrella term for the Data API and Workflow API. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#why-is-the-api-connector-not-considered-a-part-of-the-bubble-api) Why is the API Connector not considered a part of the Bubble API? The API Connector, which is used to establish **outgoing** connections to other applications is as such not a part of the Bubble API. We can illustrate the reason for this with an example moving outside of Bubble: Let's say you are initiating a connection with a Weather API to get updated weather information. That Weather API service may also use one or more APIs in order to function: for example, it could be using the Google Maps API to convert an address into map coordinates. That information, while it helps them deliver a better service, is completely irrelevant to you. As such, it's not a part of their API – it would not be presented in their API documentation and you would never know that it was involved in responding to your request. The same is true for Bubble whenever there's an incoming request: whether your app uses the API Connector to connect to other parties in order to complete a request is irrelevant to the third-party making the request. They simply want to connect to the Bubble API to get a response and what goes on behind the scene is hidden from them. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-data-api) What is the Data API? ----------------------------------------------------------------------------------------------------------------------------------------------- ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FdrrrdG3lmfFwg6W2Wl3a%252Fthe-data-api.jpeg%3Falt%3Dmedia%26token%3D15635745-2dc2-4548-8d37-60eb7d47ea06&width=768&dpr=3&quality=100&sign=ac26d9f5&sv=2) The Data API is the part of the Bubble API that deals with direct access to the database. This allows a third party to send commands directly to your app's database and get a response it can recognize in return. If you open up for it, this lets an external application: * Search for and read records in your database * Create new records * Make changes to records * Delete records Of course this all doesn't happen unrestricted: as we'll see in later sections you have full control over what information and commands they have access to. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#how-are-these-database-operations-different-from-workflows) How are these database operations different from workflows? In Bubble's terminology, a _workflow_ is the combination of an _event_ and a set of _actions_ that should be run as a result of that event. That techie-sounding description is what happens whenever you design something in the workflow editor: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FvqbHo8gQ5trJo8znM66J%252Fbubble-workflow%25402x.png%3Falt%3Dmedia%26token%3D7be6dd0a-68f1-4964-928d-27508a035170&width=768&dpr=3&quality=100&sign=68b055c&sv=2) A workflow can perform any set of Bubble actions. In the example above we're making changes to a User, creating a new database Thing and then sending an email. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#if-the-workflow-api-can-make-changes-in-the-database-why-do-i-need-the-data-api) If the Workflow API can make changes in the database, why do I need the Data API? There are several reasons for why direct access to the database makes sense to use in most cases where you are working with data: #### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#its-already-set-up) It's already set up The Data API is set up to respond to different queries in a format that other APIs will recognize. It has built-in: * Search for single records and get its data * Search for records by criteria and get their data in a paginated format * Create new Things * Bulk create new Things * Delete Things * Change Things All of this is possible without spending any time setting up a single workflow. #### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#its-secure) It's secure The Data API gives you granular control over the security of your database: * By requiring **authentication** you can determine which client is making the query, to... * **authorize** that client to perform certain actions * Find Things * Hide and show specific fields * Create Things * Modify Things * Delete Things Since this is all controlled in one central place – your app's Privacy Rules – you can apply restrictions to a wide set of clients and circumstances in one central dashboard. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F1kt5qksjwMaGc7Rq663e%252Fprivacy-rules-api-example%25402x.png%3Falt%3Dmedia%26token%3D1396c9e2-5a67-4348-8af6-e3453878e8af&width=768&dpr=3&quality=100&sign=7115de7f&sv=2) Using Privacy Rules you have a high level of control over the actions that a client accessing your database can make. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#when-should-i-use-the-data-api) When should I use the Data API? Whenever you want to give a specific app flexible access to your database. Let's go over a few examples to say when the Data API would be the more practical and secure API method: **Case 1: Customer signup to lead** Let's say you have built a CRM for your company in Bubble, but your website is in a different framework such as Wordpress. Each time a potential client signs up using the contact form on your website, you would like to create a lead in your CRM. By setting up Wordpress to send an API request to the Bubble Data API, you can create a new lead in the Bubble database using the [Create a Thing Data API request](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests#create-a-thing) . **Case 2: Project hours info to invoice** This time, let's imagine you have built a project management in Bubble, but the invoices are handled by a separate accounting app. By opening up your database to that accounting app they can get an up-to-date list of work hour logs whenever they need to generate an invoice. In short, whenever you need to read or update information in the database and all the parameters needed are available when the request is sent, the Data API is usually the better choice. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-workflow-api) What is the Workflow API? ------------------------------------------------------------------------------------------------------------------------------------------------------- ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FHT65nB5t9EJuv27OjDXk%252Fthe-workflow-api.jpeg%3Falt%3Dmedia%26token%3D6e725eff-608e-4856-b3ca-35bfc3802da1&width=768&dpr=3&quality=100&sign=6f181e0b&sv=2) As we explored in our last definition, the Workflow API allows external applications to trigger an **API workflow** in your app by sending a request. A workflow can perform any set of actions that you need to perform. Let's re-visit our example from earlier: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FvqbHo8gQ5trJo8znM66J%252Fbubble-workflow%25402x.png%3Falt%3Dmedia%26token%3D7be6dd0a-68f1-4964-928d-27508a035170&width=768&dpr=3&quality=100&sign=68b055c&sv=2) Anything built in the workflow editor is known simply as a workflow - hence the name Workflow API In contrast to the Data API, the Workflow API can perform all sorts of actions with or without involving the database. Just like with workflows on your pages, you can set up a sequence of steps, each with unique conditions to determine whether to execute or not. You can see the Workflow API in the same way as a user visiting a page in your app: they can click a button (make a request) that instructs your app to perform one or more actions that are run in sequence. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#if-the-data-api-can-make-changes-in-the-database-why-do-i-need-the-workflow-api) If the Data API can make changes in the database, why do I need the Workflow API? While workflows _can_ perform database operations, a database operation is not necessarily performed by a workflow. There are many reasons for choosing the Workflow API over the Data API: #### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#it-can-perform-actions-not-related-to-the-database) It can perform actions not related to the database API Workflows can run any kind of server-side actions that Bubble (including plugins) can offer, such as sending emails, resetting passwords, submitting API calls and lots more. #### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#it-can-perform-a-sequence-of-actions) It can perform a sequence of actions Workflows often consist of more than one action that can be run in sequence, and each step can if needed rely on a previous step. The Data API will simply perform the requested action and respond with a preset response whereas the Workflow API gives full flexibility as to what kind of unlimited number actions you want to take. A Workflow can also trigger other workflows in your app. #### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#it-can-return-a-customized-response) It can return a customized response The Data API sends a response back in a format that's recognized by many other systems, but if you need to customize what the response to a call looks like, you can use the Workflow API to set it up. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#when-should-i-use-the-workflow-api) When should I use the Workflow API? In short, whenever you need more flexibility in how data is manipulated, or when you need the API call to lead to executing actions that are not related to the database. **Case 1: Follow-up steps** Even when making changes in the database _is_ what you're looking for, the Workflow API can be the right choice. For instance, an app may need to: * Create a new Thing * Count all Things of the same type * Send an email to an address specified in the request with the total count In this case we are working with the database, but since we also want to perform a few specific actions that rely on the first step it would make sense to set this one up in the Workflow API. It might look something like this: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fl28a9jatKZpnqipfmnCL%252Fapi-workflow-example2%25402x.png%3Falt%3Dmedia%26token%3D587e48fa-08b2-4f83-96c4-fbc83c4db4bf&width=768&dpr=3&quality=100&sign=8f23e8d5&sv=2) While you could use the Data API to Create the Thing, any subsequent action would need to be set up in an API Workflow. **Case 2: Using complex conditions** In scenarios where you rely on conditions in order to determine whether an action should be performed the Workflow API also comes in handy. Let's say your app needs to: * Create a new Thing * But _only_ if today is a Friday and a maximum of 3 Things have been created today A condition like that would involve checking the current day of the week and count the number of Things created today – this complex condition wouldn't be possible to set up in Privacy Rules and would need an API Workflow where you could place the condition in the _Only when_ field. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FLiH8pFfvYpMElVT1EkcV%252Fconditional-api-workflow%25402x.png%3Falt%3Dmedia%26token%3D3dc9ee1c-8661-475c-bfcf-c02fb620e03e&width=768&dpr=3&quality=100&sign=de1022cb&sv=2) If creating this new Thing relies on a condition like the above, you can move from the Data API to the Workflow API to get the desired result. We could provide a lot of different examples, but the important point is that the Data API is used only to read/manipulate data and send a preformatted response, and the Workflow API is used to trigger a workflow that can be set up to run any actions you want. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#why-is-it-sometimes-called-workflow-api-and-other-times-api-workflow) Why is it sometimes called Workflow API and other times API Workflow? While these two terms are indeed closely related, they mean different things. The **Workflow API** is the part of the Bubble API that handles workflows. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FkZXHaACwOKV8cMPy2Qiq%252Fapi-workflows-vs-workflow-api.jpeg%3Falt%3Dmedia%26token%3D27f1b42a-7de4-47f5-b41b-5a326f85fe64&width=768&dpr=3&quality=100&sign=28170f5e&sv=2) The Workflow API is the umbrella term for the part of the Bubble API that handles API Workflows. An **API Workflow** is the workflow itself that you set up in the backend workflow editor. As such the Workflow API consists of API Workflows, and API Workflows are part of Bubble's Workflow API. [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#the-backend-workflow-editor) The backend workflow editor ------------------------------------------------------------------------------------------------------------------------------------------------------------ Bubble's backend workflow editor is the section of the Bubble editor where you create and manage backend workflows. ### [](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#whats-the-difference-between-backend-workflows-and-api-workflows) What's the difference between backend workflows and API workflows? Backend workflows is the umbrella term for any type of workflow you can create in the backend editor. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FNL6KyWXK6ydfVxnxmiHe%252Fbackend-workflows.jpeg%3Falt%3Dmedia%26token%3Def4d7582-99cb-4d5e-8399-db0ad47b5691&width=768&dpr=3&quality=100&sign=95dce9f&sv=2) Backend workflows offer four different kinds of events. API Workflows belong to the Workflow API while the rest are internal tools that serve other purposes. What they all have in common is that they run server-side. These are server-side workflows, meaning that they can run on the Bubble server without anyone visiting one of your app's pages. This includes, but is not limited to, API Workflows. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F9l8zlf84SHTivl9xTP0d%252Fbackend-workflows-highlighted%25402x.png%3Falt%3Dmedia%26token%3D3b2de671-a77a-4f30-aa21-e56a096baf22&width=768&dpr=3&quality=100&sign=e574a59a&sv=2) _Backend workflows_ is the umbrella term for the workflows you add in Bubble's backend editor. API Workflows is one of them. Last updated 22 days ago Was this helpful? * [Quick reference](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#quick-reference) * [What is the Bubble API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-bubble-api) * [Why is the API Connector not considered a part of the Bubble API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#why-is-the-api-connector-not-considered-a-part-of-the-bubble-api) * [What is the Data API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-data-api) * [How are these database operations different from workflows?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#how-are-these-database-operations-different-from-workflows) * [If the Workflow API can make changes in the database, why do I need the Data API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#if-the-workflow-api-can-make-changes-in-the-database-why-do-i-need-the-data-api) * [When should I use the Data API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#when-should-i-use-the-data-api) * [What is the Workflow API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#what-is-the-workflow-api) * [If the Data API can make changes in the database, why do I need the Workflow API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#if-the-data-api-can-make-changes-in-the-database-why-do-i-need-the-workflow-api) * [When should I use the Workflow API?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#when-should-i-use-the-workflow-api) * [Why is it sometimes called Workflow API and other times API Workflow?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#why-is-it-sometimes-called-workflow-api-and-other-times-api-workflow) * [The backend workflow editor](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#the-backend-workflow-editor) * [What's the difference between backend workflows and API workflows?](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology#whats-the-difference-between-backend-workflows-and-api-workflows) Was this helpful? --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta.md). # Property Editor Beta {% content-ref url="/pages/GIIG3EbTAoI4WltzySGr" %} \[Quick start guide (For new users)\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/quick-start-guide-for-new-users.md) {% endcontent-ref %} {% content-ref url="/pages/z8xffuRDRufBaS6ICwg6" %} \[Overview of the property editor beta\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/property-editor.md) {% endcontent-ref %} {% content-ref url="/pages/BQnH2YEYKKUO7W8X7ZHA" %} \[Property editor migration guide (For existing users)\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/property-editor-migration-guide-for-existing-users.md) {% endcontent-ref %} Looking for information about the original property editor? Please see the following section: \[The property editor\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-property-editor.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md). # Building Block Apps \*By Airdev, creators of the Canvas building framework\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Using a building-block framework to create your custom app can help to save time and improve quality. The basic premise is to start with a simple base app, pre-configured with standard things like login/admin/account pages, and then add pages and blocks from a library of assets. By piecing these pre-fab’d components together like Lego pieces, you can avoid reinventing the wheel and focus your efforts on the parts of your app that need to be truly custom. Building-block frameworks can be used to create literally any kind of web application, including: \* Marketplaces and ecommerce stores like Airbnb, Etsy, or Upwork \* Project management, CRM, or productivity tools like Trello, Asana, or Pipedrive \* Social media, forum, or messenger platforms like \[Twitter\](https://notrealtwitter.com/), Reddit, or WhatsApp \* Analytics & data visualization dashboards to support a process \* Anything else – the world is your oyster! There are typically a few user experiences that are consistent across platforms (and included in a building-block framework): \* A homepage and supporting marketing pages to entice and inform potential users \* A login page where users can enter credentials to access personalized content (this is often available as a popup too, in case other pages require signup) \* An account settings page, where users can update their credentials and technical settings \* An admin dashboard, where app owners can access key metrics, users, and other key data objects to manage their platform Below is an overview of the data structure that may be useful in a base template. From there, you will add the data objects and fields that are custom to your app (e.g., connecting a user to their upcoming rentals, or the candidates vying for their gig, or their outstanding projects, or new unread messages). ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.8gkrwvp3rqds) The core of any app is the User, which can come preset with data fields that are useful across all app categories. The App settings object is independent from users since it is at the app-wide level, helping to store general variables that could be accessed by different users at different points in their user journey. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.div9tinuokjh) Someone who can access the application by logging in. #### Suggested fields on this type \* Email (text): the email address the user signs up with \* Name (text): alternatively, you can separate first and last into two fields, and have a third representing full name \* Profile picture (image): a nice mugshot to be displayed with their profile \* Role (Role - an option set): role within the application (member, admin) #### Suggested privacy rules on this type: \* Users can access their own info \* Admins can access any user’s info \* Everyone else can’t find or access any user info (this can always be opened up later depending on the app’s purpose, but it’s best to start conservative) ### App settings [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.pz1buqzku5) This is a handy way to store all sorts of information about the app itself that you’ll need to reference throughout the app. You’ll only have one entry in this table, since there is only one app. Keeping these in the database rather than hard-coding them in the app allows you to change them on the fly and have the change permeate throughout the app (e.g., if you change your app name from AirBnB to Airbnb). #### Suggested fields on this type \* App name (text): the name of the application \* App description (text): a short description of the app, to be used for SEO purposes \* Logo (image): the official app logo (you may want to have a separate field for light/dark versions, or for a favicon) \* Terms (file): the legal terms to be accepted by users (this could also just be a text field) \* Privacy policy (file): same as above \* Primary color (text): the hex code for the app’s primary branding color, which can help dynamically define buttons and other assets #### Suggested privacy rules on this type \* Anyone can find and access this record, since its data is often used in marketing pages (i.e., for logged-out users) \* Specific fields may be deemed sensitive and can be protected to just administrators ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.krr8nsqafyt) \### Role [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.a41gxpkx1e8q) \* Standard \* Admin Having an option set for high-level application roles is useful for any application. This might be buyers vs. sellers, participants vs. owners, or other distinctions (and every app has an admin). This will affect what data the user has access to, and what they can see and do in the app. This is primarily used with the User data type. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.jge3g9i9dho3) Examples of data searches will vary widely depending on the use case of the application, but the admin dashboard will likely come preloaded with some key searches: \* New users this week: Search for Users where Date created > Current date/time + -X days : count. Note: other common Users searches include: \* Users waiting for approval (if the app is invite-only) \* Inactive users (no activity in the past X days) \* Users of a certain type (e.g., buyers, sellers, trainers, students) \* To get any app setting: Search for App settings : first item, then use the field of the particular setting you want. This search is trivial because there is only one entry in the database, which contains all the needed fields. ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.8zfpl9lbgo9s) There are building-block frameworks out there that Bubble users have created. Using one of these can give you a jumpstart on building your own application. Selecting a building-block framework to work with involves a certain level of commitment. Below are some factors to consider: \* How many people have used the framework (i.e., social proof) \* How extensive the library of assets is \* How well the library covers the types of features your app is likely to need \* The feature set included with the base application \* How easy it is to learn to use the system, and the level of support you can get \* How its design conventions fit to generally accepted standards ## About the author: Airdev [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md#h.6nxku2d514zc) Airdev (\[airdev.co\](https://www.airdev.co/)) is the original and largest Bubble development agency, and creators of Canvas (\[build.airdev.co/canvas\](https://build.airdev.co/canvas)), the #1 Bubble template and building framework. Headquartered in San Francisco, we have spent the past 7 years developing a unique process for bringing ideas to life using Bubble. This includes: \* A globally distributed network of the best Bubblers in the world \* A building framework (Canvas) that provides best-in-class design and functionality to every app at 10x the speed \* A custom process facilitated by our Bubble-built project management tool We have served hundreds of clients ranging from sole non-technical entrepreneurs to funded fast-growing startups to Fortune 50 enterprises. Our mission is to eliminate the technical barriers to bringing great ideas to life, and to provide great no-code careers to a new breed of product builders (see our \[Partners program\](https://www.airdev.co/partners)). --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/api-security/data-api-security.md). # Data API security {% hint style="info" %} This article covers the \*\*security\*\* aspects of using the Bubble Data API specifically. If you want to learn more about the Bubble Data API in general, you can check out the articles below: Article: \[The Data API\](/help-guides/integrations/api/the-bubble-api/the-data-api.md)\\ Article series: \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md) {% endhint %} The Data API allows external apps and systems to interact programmatically with the data stored in your Bubble app. It provides a set of endpoints for creating, reading, updating, and deleting data. Naturally, giving an external system access to your app's database can open up for potential vulnerabilities, and it's important to learn how to use it correctly. ## Guiding principles in Data API security ### The principle of least privilege As we've explored multiple times in our Security article series, \[the principle of least privilege\](#user-content-fn-1)\[^1\] also applies strongly to the Data API. We'll now go over how you can plan and execute to adhere to this principle when you set up the Data API. > In a bank, not every employee has the keys to the vault. A teller can access the cash drawer but doesn't have the authority to authorize large wire transfers. Conversely, the bank manager might have that authority but doesn't necessarily need access to every single safety deposit box. ### Authentication and authorization In our Introduction to APIs article we explored the two sibling concepts of \*authentication\* and \*authorization.\* ![](https://manual.bubble.io/files/oCZlIIkyP1nvgenu3XOl) Authentication identifies **who** the client is and authorization determines **what** they should have access to. The way this logic is structured is no different than in real life: before you let someone in through your front door, you would want to know who it is. In that way, they \*authenticate\* (you recognize their face), and this allows you to \*authorize\* what they have access to (step into your house). The same pattern of identification and authorization is applied in countless real-life scenarios: \* Airports: (who is the passenger? What plane do they have access to) \* Cinemas: (does the person have a ticket? To what movie?) \* Banks (who is the customer? What bank accounts do they have access to) The reason for highlighting this in real-life scenarios is to emphasize the authentication/authorization way of thinking to your security planning. When you are planning security for your Data API, you can ask the question in exactly the same way: \* \*Who\* is the client trying to access my app's database? \* \*What\* should this client have access to? When you combine this way of thinking with the principle of least knowledge, we have some very helpful rules of thumbs to guide your thinking: \* \*Who is the client trying to access my app's database?\* \* \*I need to know in order to apply the principle of least knowledge\* \* \*What\* should this client have access to? \* According to the principle of least knowledge – only as much as they need and not an inch more Having established those principles, let's look at what that means in practice as you develop your app. ## Authentication The first step in any secure transaction is that of knowing who the client is. For the Data API, this follows a range that we can split into three categories: \* No one has access (the Data API is disabled) \* Some clients have access (the Data API is enabled, but requires authentication) \* Everyone has access (the Data API is enabled, and requires no authentication) ### No one has access Before you make any decisions regarding your app's Data API, you need to determine whether anyone should have access at all. The Data API is disabled by default, but can be enabled in the \*Settings\* – \*API\* section of your app by checking \*Enable Data API\*. ![](https://manual.bubble.io/files/EX5JcjBVFbRQmkBWUEOW) If your app doesn't need any external app or system to access the database, you can safely keep that checkbox unchecked. This keeps the Data API completely disconnected and no other security measures are needed. ### Some clients have access The second level in our access range is to give one or more clients access, but not everyone. This is where most apps with an enabled Data API will be, and it means we need to authenticate ("check the ID") of every system that wants access to the database. There are two ways to authenticate an external app or system without giving everyone access. To learn how to set up each one, following the article link listed below: \* \*\*Authenticating as a user\*\* essentially means to "log in" to your app in the same way as a regular user would. This means that you can apply Privacy Rules to control what that user has access to. This is an access level that gives you a high degree of control over what that user can and can't do in your database.\\ \\ Article: \[The Data API - authenticating as a user\](/help-guides/integrations/api/the-bubble-api/authentication/as-a-user.md)\\ \\ Using this authentication method, you will usually continue to set up rules for who can access what. Or in other words, authorization. Follow this link to continue setting that up. \* \*\*Authenticating as an admin\*\* means to use Bubble's built-in API token system to give access. This automatically gives them full administrator access, which means the same access level as you have as the app's developer (not to be confused with any admin role you set up in your app). This access level grants extensive permissions, allowing the reading, modification, and deletion of all data in your app. Ensure it's used only with external apps or systems you trust implicitly.\\ \\ Article: \[The Data API - authenticating as an admin\](/help-guides/integrations/api/the-bubble-api/authentication/as-an-admin.md) ### Everyone has access In this option, we disregard the authentication step altogether: the door is open and anyone can walk in. The logic then follows that since we're not checking \*who\* walks through the door, we can't determine what each visitor should have access to. Everyone is treated the same. This method should only be used when you are determined to give free, public access to your database. Keep in mind this can not only affect your security, but also the amount of workload\[^2\] that your app consumes (as API requests will spend server resources, adding to your total workload). To learn how to set up your Data API to offer everyone access, see the article below:\\ \\ Article: \[The Data API - no authentication\](/help-guides/integrations/api/the-bubble-api/authentication/no-authentication.md) ## Authorization Returning to the bank metaphor: a person who registers as a customer in a bank needs to have access to their own account, but most would find it strange if they were given access to \*all\* accounts. The same logic applies to an app where you don't want to share \*all\* data even to people that are authenticated to use the app in the first place. We've taken care of the authentication (who is the client), and now it's time to explore how we determine the \*authorization\* for those client (what the client can access). This is done in two ways: ### Enabling data types The first step to protect data is to enable only the data types that you want to expose. Keep in mind the following: \* Unchecked data types are \*\*not\*\* available in the Data API regardless of how the user authenticates \* Checked data types are exposed, but adhere to the privacy rules in combination with the client’s authentication. We'll look at data types in the next step. ![](https://manual.bubble.io/files/EX5JcjBVFbRQmkBWUEOW) When you enable the Data API, you will see the list of of data types that you want to show. ![](https://manual.bubble.io/files/YBl0GqBkcLJUP6Nxyo0l) Click the image to see a larger version. The data types that are \*not\* enabled (unchecked) will not be accessible by anyone. In the example above, we have a data type \*Product\* that we want to share with another app. Following the principle of least privilege, we'll \*only\* activate that one, and keep all other data types unchecked. This setting takes care of the overarching authorization: what data types any client has access to. In the next step we'll look at privacy rules: they provide the fine-grained control ### Privacy rules After enabling the data types we want to expose, it's usually a good idea to use privacy rules to control \*which fields\* on those data types can be accessed, and \*what kind of actions\* can be performed. Just like in your regular app, privacy rules are set up on a user-basis. In other words, which user you authenticate determines the level of access they have to: \* Find in searches \* What fields and uploaded files to expose \* Make changes to \* Create \* Edit \* Delete For more in-depth instructions on how to set up the privacy rules for a data type exposed in the API, check out the article below: Article: \[The Data API - Setting up Privacy Rules\](/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules.md) ## Data API security checklist With the methods above in mind, let's go over the tools that secure your Data API. \* \*\*Keep the principle of least access in mind\*\* (\[link\](#the-principle-of-least-privilege)) \* \*\*Decide who has access (authentication)\*\*\\ First, decide who has access to the data API: \* No one (\[link\](#no-one-has-access)) \* Selected clients (\[link\](#some-systems-have-access)) \* All clients (\[link\](#everyone-has-access)) \* \*\*Decide what they have access to (authorization)\*\* \* Enable only the data types you want to expose (\[link\](#enabling-data-types)) \* Use privacy rules for fine-grained control over fields and editing rights (\[link\](#privacy-rules)) \[^1\]: \*The principle of least privilege\* means giving just enough access needed for a task and nothing more.\\ \\ Article section: \[The principle of least privilege\](/help-guides/security/api-security.md#the-principle-of-least-privilege) \[^2\]: \*Workload\* is a measurement of 12 different activity types that together make up the total amount of work performed by Bubble to keep your app running. It's a core element of Bubble's pricing plans.\\ \\ Article series: \[Pricing and workload\](/account-and-marketplace/account-and-billing/pricing-plans.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/api-security/data-api-security.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules.md). # Protecting data with privacy rules {% hint style="info" %} This section takes a long-form look at what privacy rules are.\\ \\ To see the more concise and technical documentation you can check out our \[core reference entry\](/core-resources/data/privacy.md). {% endhint %} {% hint style="danger" %} Privacy rules are an essential part of your app's security. Any database data that is private or sensitive needs to be protected with Privacy Rules to be considered secure. Always stay on top of your app's Privacy rules to let your users safely entrust their data to your app. {% endhint %} Privacy rules are conditions that you set up on each data type in order to protect the data from being viewed and edited by unauthorized users. ## What are privacy rules? All the data that you store in the database is hosted on a server. Privacy rules are rules that instruct the server to only send data to the browser or write to the database if certain conditions are met. For example, we could allow our Products to only be viewable by people who are logged in. The privacy rule in humanly readable terms would be: \`\`\` Only return the data if the current user is logged in \`\`\` The logic in this case would be that we \*ask\* the server for some information by using a data source such as \*Do a search for\* and an operator like \*Name\* to show a Product name. If the privacy rule above is active, Bubble will \*only\* return the data if the query came from a user that is logged in. The reason this is so essential to app security is that it's stopped on the \*server-side\*, and the data remains in an encrypted state in the database instead of being sent to the browser where it could be viewed. ![](https://manual.bubble.io/files/PU801MpGFyrziwCgYvgx) As illustrated above, the privacy rules make up a sort of firewall for your data – every request to the database goes through a process of \[authentication and authorization\](#user-content-fn-1)\[^1\] before it's completed or rejected. ### Client-side data Before we explore privacy rules, it's important to understand that all data that reaches your user's device is by definition no longer secure. As a developer, you need to be aware that the as long as the data has been downloaded to the user's device – even if it's not displayed anywhere in your app – the user of that device can access it by looking at the data traffic being sent to and from the Bubble server. This is fairly technical subject – suffice it to say that the only way data remains truly inaccessible is ensure it is not sent from the server in the first place. And privacy rules are the way to do that. It's also important to stress that in most cases, we \*want\* the data to reach the device. If not, we wouldn't be able to work with data at all. The important task is to ensure that only the intended information is sent and no unauthorized data. In an eCommerce store we would likely find data in the database that has different security requirements: \* All \*\*Products\*\* should be viewable by anyone (if not, no one will be able to buy anything) \* All \*\*Shopping carts\*\* should only be viewable by the user who created it (to keep the user's purchase history private) The Products are known as \*public data\* and the Shopping cart is \*private data.\* ## How privacy rules work {% hint style="info" %} \*\*Bubble API:\*\* Using the Bubble API introduces some new settings in the privacy rule tab. You can read more about those special settings in the article below. Article:\[ Data API privacy rules\](/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules.md) Article: \[Workflow API privacy rules\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules.md) {% endhint %} {% embed url="" %} Bubble features a privacy rule editor that lets you control the privacy settings on all your data types in one central place. You access this by going to the \*Data\* tab and then clicking \*Privacy\*. Privacy rules protect your data types in the following ways: \* You can stop specific \*\*fields\*\* from being viewed \* You can stop the data type from being \*\*found with \*\*\*\*\*Do a search for\*\*\* \* You can stop users from viewing \*\*uploaded files\*\* \* You can stop users from making changes with \*\*auto-binding\*\* {% hint style="danger" %} \*\*Caution:\*\* Privacy rules do not update automatically on the page if the privacy rules impacting a user change while the user is on that page. For example, if a user has a page open where they can see a Thing, then they click a button on that page that changes which privacy rules apply to them such that they can no longer see that Thing, this new privacy rule outcome will \*not\* reflect on the page until the page is refreshed. {% endhint %} {% hint style="info" %} Managing the security of \*\*private files\*\* requires configuring specific settings within both the privacy rules and the element responsible for uploading the file. You can learn more about this in our dedicated guide below: \* Article: \[Files\](/help-guides/data/files.md) \* Article section: \[Uploading private files\](/help-guides/data/files.md#uploading-private-files) {% endhint %} Privacy rules are built using two pieces of information: \* What are the attributes of the database thing \* What are the attributes of the current user By combining the attributes of these two, we can flexibly set up rules that determine \*\*who\*\* the user is and \*\*what\*\* the user is trying to access. Let's look at another rule written out as a sentence to illustrate: \`\`\` Only return the data if the thing's Creator is the current user \`\`\` Here we are involving both the \*thing\* in question and the \*current user\*. If the current user and the creator of the thing is the same, then Bubble will return the data. If they are not, the data stays securely on the server. ### Privacy rule settings Each privacy rule consists of different settings, and the easiest way to understand how they work is to simply read them from left to right like you would an English sentence: ![](https://manual.bubble.io/files/uldrxeLYs07hQdOBVr7h) The sentence above says 1. "\*When the current user is logged in...\* 2. \*...users who match this rule can...\* 3. \*...view all fields.\* The settings and their labels are meant to be taken literally. For example, \*View all fields\* means \*\*View\*\* all fields – it does not stop making \*changes\* to the field in a workflow. Likewise, \*Find this in searches\* applies to \*Do a search for\* specifically – but the record can still be fetched in other ways. We recommend playing around with the settings and viewing the results on a page to learn how they affect what users can see and do. #### Multi-level data references and searches There's is an important limitation to be aware of when conditions reference related data \[\*more than one level deep\*\](#user-content-fn-2)\[^2\]. Privacy rules can evaluate fields that belong directly to the data type, but they can't traverse multiple layers of relationships to grant \[search access\](#user-content-fn-3)\[^3\]. If a rule uses a chained reference, such as accessing a field on a related thing and then another field beyond that, Bubble can't use that rule to grant search access. ![](https://manual.bubble.io/files/qDOvi3QDEGFPwgK3qljz) To avoid this limitation, structure your data so that the fields required for privacy checks only need to access one level in its expression: ![](https://manual.bubble.io/files/JE5gAigOT2ZyZxWRx3DW) In the example above, instead of checking the Cart's Creator's X, we're checking the Current User, reducing the levels from 2 to 1. ### Privacy rules and workflows Do privacy rules affect your app's workflows? The answer is \*yes and no\*. \* \*View all fields\* does not stop you from \*Making changes to a thing\* and updating that field in a workflow. However, it \*can\* stop you from correctly checking a condition if the current user is unable to view the field on which the condition is based \* \*Do a search for\* does not stop you from making changes to a thing, but it can stop you from getting the search results that you want in a workflow. In other words, if you are using the \*Do a search for\* data source in a workflow, the search will only return the data that the current user has access to. \* \*Allow auto-binding\* stops the user from making changes through auto-bound elements – but it does not stop them from making those same changes in a workflow. There are two important lessons we can take in: \* You need to view the workflow as being \*run by the current user\* – the same restrictions will apply to the workflow as in any other scenario in your app \* To protect workflows from performing tasks you don't want it to, you'll need to use \*conditional expressions\* in the \*Only when\* field on the workflow or specific action #### Can I override privacy rules in a workflow? Sometimes you'll have a need to override privacy rules when a user takes a specific action. For example: 1. User 1 does not have permission to search for any other users 2. When User 1 runs a specific action, you may need to perform a search for all other users to make a change In other words, you need to override the privacy rule that stops User 1 from searching for other users. This is done by using an API Workflow and checking \*Ignore privacy rules when running the workflow.\* This lets you run workflows that perform an important task with full access to data, without compromising your security by opening up the access for the current user. The operation is performed purely server-side, meaning that your users cannot see it or even know that it's running. ![](https://manual.bubble.io/files/1PnP0GGVdCI9U8lS6IMc) \## Examples ### Example 1: Shopping cart We have a custom data type called Shopping Cart. This type should only be found in searches and viewable by the person who created it. But wait: if no one else can see the order, how are we to deliver the product? Someone else needs to be able to see it, but it must be restricted. We'll set up a custom field on each user called \*Admin\* (yes/no), which grants access to see anyone's cart. On the cart, we can use the already existing and automatically populated \*Created by\* field. The User should look like this: ![](https://manual.bubble.io/files/UqDX80iUA0U0gf810y3r) We set up a simple yes/no field to separate admin users from regular users. Note that we have set the default value to _no_ to make sure that new users are _not_ an admin by default. This setup requires that we set up three privacy rules: 1. The first gives access to search for and view fields on the cart \*if\* you are the one who created it 2. The second gives access to search for and view fields on the cart \*if\* your admin field is set to \*yes\* 3. The third is the automatically generated \*Everyone else\* rule: this states that everyone else should have \*no access\* ![](https://manual.bubble.io/files/DM6jfMQKi81SWa6sQAdg) Pay especially close attention to the \*bottom\* rule. This is the one that determines what happens to \*everyone else\*. We've unchecked all the boxes in this example, making sure that \*only\* admins and cart owners get access. A good way to think about privacy rules is that \*the most generous rule –\* the one that gives the broadest access – will always override any other rules you set up. > With privacy rules, you don't \*prohibit access,\* you \*\*grant it.\*\* Following that logic, our two top rules are \*granting\* access to the cart 1) if you are the cart's creator, or 2) if you are an admin, as specificed by the \*Admin\* yes/no field. ### Example 2: Sharing tasks In this example, we'll look into how properties on the data type to which the privacy rules are applied can further grant access under certain circumstances. Let's imagine we have a task management app, where access to tasks follow two simple rules: 1. The creator of the task has full access to their tasks 2. The creator can invite other users into a specific task, granting them access In that case, we need some way to determine whether a user has been invited to a specific task. Keep in mind, we want to add that permission only to certain tasks, not all of them. We can solve this by adding a new custom field on the Task data type that contains a list of all Users who have been invited to it. The database structure can look like this: ![](https://manual.bubble.io/files/qaoE7HBHlWlll2u72Jfa) Whenever we want to give someone access to the Task, we add their name to the list using workflow: ![](https://manual.bubble.io/files/jr1Dsg36uRBJiu1juaQh) Since the \*Invited users\* field is set to be a \*\*list\*\*, Bubble lets us use the \*add\* function that will add that single user to the list of Invited Users (if we wanted to add a list of users we would use the \*add list\* function). Now, to set up our privacy rule, we will again need three rules: 1. The first states that if the current user is the \[Creator of the task\](#user-content-fn-4)\[^4\], you should have access 2. The second states that if the current user is in the list of invited users, you should have access 3. The third (\*everyone else\*) states that no one else should have access In the privacy rule editor it will look like this: ![](https://manual.bubble.io/files/Son9F7mureVzmy109dLO) The task's creator and any invited users can see all fields. To everyone else, the task is inaccessible. Again we can see that the two rules \*\*grant\*\* access under special circumstances, while the bottom does \*\*not\*\* grant the permission to everyone else. ## Ending notes Privacy rules are the most important safeguard you have to protect your user's data, and we strongly encourage that you get to know them well and make a habit of setting up data to be secure from day one. Privacy Rules act on the server-side, making it impossible for data to be stolen, tampered with or accidentally leaked, since the information never leaves the server Bubble has strong security features in place, but we don't enforce them. It's up to you as the developer of the app to use them in the right way to make sure your user's private data stays private. ## Other ways to learn Video lessons \* \[Setting up privacy rules\](https://youtu.be/1-meIeBUXPY) Books \[The Ultimate Guide to Bubble Security\](https://www.amliesolutions.com/the-ultimate-guide-to-bubble-security/) by Petter Amlie \[^1\]: \*Authentication\* is the process of determining \*who\* a user is.\\ \\ \\&#xNAN;\*Authorization\* is the process of determining \*what\* that user has access to. \[^2\]: In this context, a \*level\* refers to accessing a field on a related thing, and then accessing another field beyond that. For example, in the expression \*This Blog posts’s Creator’s Admin is yes\*, \*Creator\* is the first level of reference, and \*Admin\* is one level deeper than Creator. \[^3\]: The \*Find this in searches\* property that applies to the data source \*Do a search for\* in your app. \[^4\]: The Creator task is a built-in field that's automatically populated. It can't be changed.\\ \\ If you want to be able to set a dynamic owner (for example to transfer ownership from one user to another), you may want to set up an additional field that you can manipulate directly. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md). # Project Management Apps \*By Airdev, creators of the Canvas building framework\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Project management applications help teams coordinate their efforts to get more done together. The classic setup involves breaking projects into individual tasks, each of which has an owner and deadline. Team members can update and track task statuses as they work toward completing everything on time. More complex setups can involve goals, milestones, subtasks, and other more sophisticated structures. The category has proven to be a natural fit for a web application, since multiple team members need to access and update the same information. Popular examples include Asana, Monday, JIRA, Trello, Wrike, and ClickUp. Though the content below focuses on the data structure that supports the application under the hood, the user experience for a project management app is generally meant to be less linear (e.g., like an ecommerce website) and more free-flowing as users toggle between projects and tasks to collaborate and get things done. The app may include some of the following pages: \* A homepage and supporting marketing pages to entice and inform potential users \* A login page where users can enter credentials to access their portal \* A personal dashboard, where users can manage their profile, teams, and get an overview of the tasks they are assigned (i.e., their to-do list) \* A team workspace, where users can manage a team’s settings, members, and projects \* A project board, where users can manage the tasks under a project (usually as a list, board, or table) \* An account settings page, where users can update their credentials and technical settings \* An admin dashboard, where app owners can access key metrics, users, and other key data objects to manage their platform ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.8gkrwvp3rqds) The primary data object in a project management tool is the Task, which is something that needs to be done by someone (i.e., a User) by a deadline. In order to help Users find, organize, and complete tasks on time, project management tools typically organize them into distinct Projects, each of which has a set of Tasks. Projects can also exist within Teams, each of which has a set of member Users and Projects. Thus each User can see their own Teams, the Projects within them, and the Tasks within those. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.m4tvd4srqrfj) An individual team member who can login to access their projects and tasks. #### Suggested fields on this type \* Email (text): the email address the user signs up with \* Name (text): alternatively, you can separate first and last into two fields, and have a third representing full name \* Profile picture (image): a nice mugshot to be displayed with their profile \* Role (Role, an option set): role within the application (member, admin) \* Teams (list of Teams): a list of teams the user is a part of (i.e., who’s projects they can access) #### Suggested privacy rules on this type \* Users on the same team can access one another’s info \* Admins can access any user’s info \* Everyone else can’t find or access any user info (since each team is a closed system) ### Team [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.4yzr9inemsxf) A group of individual users who work together on a set of projects and tasks. #### Suggested fields on this type \* Name (text): each team can have a name (e.g., Dunder Mifflin) \* Owner (User): the team member who can edit the team, add/remove team members (this might start with the team’s creator, but the distinction could be transferred to someone else) \* \\\[Members (list of Users)\]: this is optional since each User has a list of teams they are a part of – sometimes it’s helpful to \[link both ways\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) to simplify search expressions in the app, as long as you keep both directions in sync (try a database trigger for that) \* \\\[Projects (list of Projects)\]: another optional linkage, since each project has a team #### Suggested privacy rules on this type \* Users can access teams they belong to \* Admins can access any team’s info \* Everyone else can’t find or access any team info (since each team is a closed system) ### Project [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.lmrl4548gc40) A single initiative (represented by a collection of tasks) to be completed by a team. #### Suggested fields on this type \* Name (text): each project can have a name (e.g., Public Launch) \* Team (Team): the team that is working on the project \* Owner (User): this might be helpful for tracking (i.e., where do Michael Scott’s projects stand?) \* \\\[Tasks (list of Tasks)\]: this is an optional linkage, since each task has a project \* \\\[Completed tasks (number)\]: sometimes it’s helpful to pre-calculate a count of tasks for the project to make it easier to download project data and display metrics without lots of search expressions \* \\\[Total tasks (number)\]: see explanation above – completed / total allow you to calculate percent completed #### Suggested privacy rules on this type \* Users can access projects within teams they are a part of \* Admins can access any project’s info \* Everyone else can’t find or access any project info (since each team is a closed system) ### Task [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.r830msjb20w4) A single action item within a project, assigned to someone from the team, with a deadline and status that can be tracked to completion. #### Suggested fields on this type \* Title (text): the high-level name of the task (e.g., “Purchase party hats”) \* Description (text): a long-form description of the work to be done \* Attachments (list of files): any images or files relevant to the task \* Assignee (User): the team member responsible for the task \* Deadline (date): when the task is due \* Status (Status, an option set): the current stage in the process the task is in \* Project (Project): the initiative the task is a part of \* \\\[Team (Team)\]: this is an optional linkage because the task’s project will be associated with a team, but sometimes it’s easier to create the direct link to make privacy rules easier \* Watchers (list of Users): any team members who want to be notified of changes to the task (e.g., the assignee’s manager) \* Tags (list of Tags, an option set): any labels the task fits into (makes filtering tasks easier) #### Suggested privacy rules on this type \* Users can access tasks within teams they are a part of \* Admins can access any task’s info \* Everyone else can’t find or access any task info (since each team is a closed system) ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.krr8nsqafyt) \### Role (users) [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.bg3ynyl2vbxo) \* Member \* Admin Having an option set for high-level application roles is useful for any application. In this case, it helps to separate standard users from administrators. This will affect what data the user has access to, and whether they work within their team workspace or an admin dashboard. Note: this is different than team-based roles or project-based roles. In this MVP setup, we’ve assumed each has a single owner, but you could use a separate option set to define roles at those levels. ### Status (tasks) [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.k8yzmuof2eq) \* New \* To do \* Doing \* Done Assuming you want to use the same set of task statuses across the application, it will be easiest to use an option set. This makes it easier to adjust the list later without disrupting existing data. Note: if you want to allow for custom statuses by team or project, you would move these to a data object so they can be edited on the fly from within the app. ### Tag (tasks) [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.pdwk2emdn898) \* Urgent \* Bug \* Feature \* etc. Assuming you want to set the tags that tasks can be labeled with across the application, it will be easiest to use an option set. Note: if you want to allow for custom tags by team or project, you would move these to a data object, for the same reason as for statuses above. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.jge3g9i9dho3) \* On the personal dashboard, searches may include: \* My tasks: Search for Tasks where Assignee = Current User and Status <> Done, Sorted by Due Date (ascending). This will start with overdue tasks (i.e., with due dates in the past) and proceed to nearest upcoming tasks. \* My teams: With the data structure above, this can be done directly as Current User’s Teams (using the list field). Alternatively, it can be done as Search for Teams where Members includes Current User (this condition isn’t strictly needed since privacy rules will only allow a user to see their own teams, but it can be helpful anyway). \* On the team dashboard, searches may include: \* Projects: This can be done directly as This Page’s Team’s Projects (using the list field). Alternatively, it can be done as Search for Projects where Team = This Page’s Team. \* Members: This can be done directly as This Page’s Team’s Members (using the list field). Alternatively, it can be done as Search for Users where Teams includes This Page’s Team. \* A selected Project’s tasks: This can be done directly as Parent group’s Project’s Tasks (using the list field). Note: “Parent group” assumes you’re showing the list within a group that has a data type = Project, which you change the value of when a user selects a project. If you are using a board/Kanban view, you may have a repeating group of lanes/statuses, where the data type is the Status option set and each cell has a search for tasks with that status. ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.ptfy1mlmwmwy) Project management software can get very feature-rich in order to satisfy the needs of the broadest range of teams and projects. In addition to the basic structure above, below are a few common features you may want to include in your database structure: \* The ability for users to post comments within a task to collaborate \* Custom fields on a task, either at the team or project level \* A history of updates for a task (e.g., status changes, edits to name/description, reassignment, deadline shifts) \* Custom statuses / tags for each team or project (as described above) \* Subtasks (i.e., the ability for tasks to be nested under one another) Project management tools are sometimes white-labeled, so each team can have their own copy on their domain. Bubble supports this through their “sub-app” feature. If you take this approach, you can create the app assuming just one team, and create a copy for each team. ## About the author: Airdev [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md#h.6nxku2d514zc) Airdev (\[airdev.co\](https://www.airdev.co/)) is the original and largest Bubble development agency, and creators of Canvas (\[build.airdev.co/canvas\](https://build.airdev.co/canvas)), the #1 Bubble template and building framework. Headquartered in San Francisco, we have spent the past 7 years developing a unique process for bringing ideas to life using Bubble. This includes: \* A globally distributed network of the best Bubblers in the world \* A building framework (Canvas) that provides best-in-class design and functionality to every app at 10x the speed \* A custom process facilitated by our Bubble-built project management tool We have served hundreds of clients ranging from sole non-technical entrepreneurs to funded fast-growing startups to Fortune 50 enterprises. Our mission is to eliminate the technical barriers to bringing great ideas to life, and to provide great no-code careers to a new breed of product builders (see our \[Partners program\](https://www.airdev.co/partners)). --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md). # Dashboards \*By Robert Brooks, Founder & CEO, MVP.dev\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} In this guide, we will be creating a dashboard for a sales team inside a learning management platform. The dashboard will be in the Customer Relationship Management (CRM) platform that was built in Bubble.io. This is a central place where sales reps can see their performance and manage their sales activities. The dashboard has different charts and graphs that give insights into the sales process and help reps stay on track with their goals for the day. Bubble is a great platform for quick dashboard generation. With a good selection of charting plugins, you can easily have your own dashboard stood up for your platform in no time at all. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.30j0zll) The CRM stores common sales data, such as Users, Contacts, Deals, Sales Made, and Chart Data ### Users [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.1fob9te) The users data type stores information about the users of the system – in this case, sales reps, but could include others such as sales managers, SDRS, etc. #### Suggested fields on this type \* Email - text \* First Name - text \* Last Name – text \* Role – Roles: Option set that defines the access level the user has to the CRM; privacy rules on many data types will be influenced by this \* Manager – User: This sales reps manager \* And any other fields that might be relevant for platform users #### Privacy rules for this data type \* Each user can view all fields for their own data relevant to their own profile, as well as find in searches, and view attached files \* Users with the Manager role can: \* View all fields except the following: \* Slug \* Created Date \* Modified Date \* Find this in searches \* View attached files \* Users with the Admin role can view all fields for all users, as well as find in searches, and view attached files ### Contacts A CRM contact is a customer or potential customer who is associated with a CRM account. CRM contacts typically have detailed information such as name, contact information, and account history. #### Suggested fields on this type \* Contact Type – Contact Types: Option set that defines the type of contact this record represents \* First Name - text \* Last Name – text \* Company - text \* Phone Number – number \* Email - text \* Title – text \* Address - geographic address \* Owner - Users: Determines which sales rep owns the record \* Notes - text #### Privacy rules for this data type \* Users with the Sales Rep and Sales Manager roles can: \* View all fields for their own data or direct reports data except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Deals [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.3znysh7) A CRM deal is a type of customer relationship management software that helps businesses manage their customer data. It can be used to track customer interactions, sales, and marketing campaigns. CRM deals can be found online or through software providers. #### Suggested fields on this type \* Contact – Contacts: contact record for this deal \* Name - text \* Description – text \* Amount – number \* Stage – Stages \* Date - date #### Privacy rules for this data type \* Users with the Sales Rep and Sales Manager roles can: \* View all fields for their own data or direct reports data except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Sales Made A completed transaction in the CRM platform that resulted from a deal #### Suggested fields on this type \* Deal – Deals: Deal that generated the sale \* Amount – number \* Date - date #### Privacy rules for this data type \* Users with the Sales Rep and Sales Manager roles can: \* View all fields for their own data or direct reports data except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Chart Data Data to be displayed in the charts on the dashboard. This is usually aggregated data of some sort; sales per month, lost deals this quarter, etc. We store this aggregated data in its own data type so that it’s easier to retrieve this for a chart, instead of having to do the aggregations and calculations when setting up the individual charts. #### Suggested fields on this type \* Chart Information – Chart Information: An option set showing the type of data represented by this record \* Number – number \* Date – date \* User – Users: the user this data represents. #### Privacy rules for this data type \* Users with the Sales Rep and Sales Manager roles can: \* View all fields except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.2et92p0) \### Roles [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.tyjcwt) \* Sales Rep \* Sales Manager \* Administrator Sets the access level the user has to the platform ### Contact Types [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.3dy6vkm) \* Lead \* Client \* Partner \* Other Determines the type of contact the records applies to. ### Stages \* New \* Proposal \* Won \* Lost Determines the stage the deal is currently in. ### Chart Information [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.1t3h5sf) \* Sales \* Leads \* Proposals \* Won \* Lost Determines the stage the deal is currently in. ## About MVP.dev [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md#h.4d34og8) At \[MVP.dev\](https://mvp.dev/), we help business owners harness the power of no-code technology to bring their vision to life in weeks through a high-touch proven process. Rather than holding your tech hostage through a drawn-out and mysterious process, we’re passionate about partnering and collaborating with you every step of the way — from idea to design to development to delivery. We lean on your vision and our experience to create a truly unforgettable experience and product. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md). # Online Store / Ecommerce Apps \*By Petter Amlie, Amlie Solutions\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} In this guide we’re building an online store, similar to something like Amazon or Shopify: a place where Users can add Products or Services to a Shopping Cart and go through a checkout process where they pay for the items. For an eCommerce store, no matter what you are selling, there will be a mix of public and private data. For example, Products need to be public, because Users must be able to search for them and add them to their Cart. But a User’s shopping history must only be visible to that User, and to the employees who are fulfilling the order. For this, we’ll use Privacy Rules, and you’ll see that you have full control over who can see what in your application. We’ll also take into account that you need to retain some historical records at the time of purchase. This is to make sure that Products that may change over time (such as the price being adjusted) does not affect past purchases. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.8gkrwvp3rqds) There will be four major Data Types involved in our online store. The User is of course built into Bubble already, but we’re making some key changes to them to make sure we can separate different types of Users from each other. The second is the Product. This one is a public data type that people can search for and review its details before adding it to our third data type: the cart. The cart is the container that holds Products while the User is shopping, and it allows the User to pay for all items at the same time, as well as maintaining the Users purchase history by showing each Cart as a separate order. Finally, we’re setting up a Cart item Data Type. We use this item to store information after the purchase has been made to make sure we know what each item cost and how it was described at the time of purchase. Let’s have a look at the details. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.3pxvwyrme17k) Your app will of course consist of Users. In our case, there will be two types of Users that we need to think about: \* Regular Users (users who have registered an account in your application) \* Admins Users (users who have access to your application's back-end to fulfill orders) #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.mxa3kiqcv1oa) \* Name - text \* Phone number - text (if relevant to your app) \* Shopping cart - Shopping cart: This field will be used to store the currently active Shopping cart that the User can add Products to \* Admin - yes/no: This field will be used to determine whether the User is an administrator or not. You can set this field’s default value to “no” #### Privacy rules for this data type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.7wkvul7c2kic) In most online stores, we do not want Users to be able to see each other’s cart and we also want to keep it hidden that a User is registered at all, except to the User themselves and Administrators. Our first rule will let Users see and edit their own information: If this User is Current User, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: \* Name: Yes \* Phone number: Yes \* Cart: No \* Admin: No As you can see, Users can now edit all their own information except for a few key fields: The Admin field (since otherwise that would make any User able to set themselves up as an administrator) and the Cart field (since the platform needs to be programmatically in control of that field as the User navigates the shopping process). Ok, so the User is all set up to handle their own info. As we discussed, we also need a kind of Administrator User that maintains the platform and fulfills orders. We set up the admin field to handle separate those Users, so let’s set up the Privacy Rule as following: If Current User’s admin is yes, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes With this rule, we’ve made sure that admin Users can find, see and edit all information on all Users, and even assign the Admin role. Finally, the most important rule is the one that dictates what every User not covered by the previous rules can see and do. In our case, we want to restrict their access. Everyone else: \* View all fields: no \* Find this in searches: no \* View attached files: no \* Allow auto-binding: no ### Product [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.t63d7m1v1lek) As your Users navigate your Online Store, they’ll need to be able to find and view Products. You can of course add as many details to this Data Type as you need. For this example, we’ll set up just a simple product with a name, image, price and a short description. To illustrate how you can use Privacy Rules to hide only specific fields on a database Thing, we’ll also add a field called Profit margin. This is a field that should be available to Administrators, but it should be invisible to everyone else. You may not need this in your app, but we’ll set it up just to learn how it’s done. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.kays0wu0umwb) \* Name - text: the name of the Product, such as “Coffee mug” \* Image - image \* Price - number \* Description - text \* Profit margin - number #### Privacy rules for this data type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.j2b3iuwpa70j) First, we need to make sure that Users can see all the Products - if not, it wouldn’t be much of a shopping experience! But keep in mind what we discussed earlier: we don’t want the Users to be able to see the Profit margin unless they are an admin. Also, regular Users should not be able to edit the Products in any way. We don’t actually need to set up a specific field for Users that are not admins, since in this case, we’ll cover that with the everyone else rule. First, we’ll set up the admin, and then everyone else. Admins should be able to find and edit all Products, and they also have access to the Profit margin field: If this User’s admin is yes, this User can: \* View all fields: no \* Name: Yes \* Image: Yes \* Price: Yes \* Description: Yes \* Profit margin: Yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: Yes \* Name: Yes \* Image: Yes \* Price: Yes \* Description: Yes \* Profit margin: Yes Everyone else: \* View all fields: no \* Name: Yes \* Image: Yes \* Price: Yes \* Description: Yes \* Profit margin: no \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: No ### Shopping cart [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.w4bnuaetoew4) This is the container that we’ll use to store every Product that the User adds to it both before the purchase is made and after. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.tu4mmmmv7fyo) \* Products - list of Products: Make sure to check the “This field is a list” on this field to make sure it can contain more than one Product \* Total cost - Number: This is where we’ll store the total amount for all Products in the cart \* Cart items - list of Cart items: Make sure to check the “This field is a list” on this field to make sure it can contain more than one Cart item \* Fulfillment status - Fulfillment status (option set): This field is used internally to determine how the order is moving in the system. You can set the default value for this to “Received” (see notes on the Option Set further down) #### Privacy rules for this data type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.os65471nuph0) Like the User itself, the Cart is a very private field: no one except for the customer and the staff managing your app should be able to see it. First, we’ll set it up so that the User can see their own Cart. We’ll use the built-in Created by field for this. There are no fields that are auto-bound on the Shopping cart, since we’ll be relying on Workflows to add and remove items. If this Shopping Cart’s Created by is Current User, this User can: \* View all fields: Yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: No Now for the admins that fulfill the order: If Current User’s admin is yes, this User can: \* View all fields: Yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes \* Fulfillment status: yes \* Total cost: No \* Products: No \* Cart items: Yes As you can see, not all fields are editable, even by an admin. As the total cost is calculated based on the Products inside, we don’t want anyone to be able to edit it directly. Now again, for the most important rule: what everyone else can see: Everyone else: \* View all fields: no \* Find this in searches: no \* View attached files: no \* Allow auto-binding: no ### Cart item [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.3o36xg4qckzr) The Cart Item is basically a clone of the Product at the time of purchase. This lets us store a permanent record of what the item cost and how it was described when it was bought, so that we can make changes to a Product without it affecting already completed carts. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.tnt2wbc21ue4) \* Shopping cart - Shopping cart: The Shopping cart to which the cart item belongs. \* Product - Product: First, we’ll link to the original Product \* Price - number: This number we’ll copy from the original Product when the User checks out \* Name - text \* Description - text #### Privacy rules for this data type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.e7cnwt1w3q5s) The Cart items should behave just like the Cart its in: visible to Users and Admins, and invisible to everyone else. If this Cart Item’s Created by is Current User, this User can: \* View all fields: Yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: No Now for the admins that fulfill the order: If Current User’s admin is yes, this User can: \* View all fields: Yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: no Keep in mind that we may allow Admins to delete items in the Cart, but for that we’ll rely on workflows - not auto-binding. That’s why we keep auto-bind disabled for now. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.krr8nsqafyt) \### Fulfillment status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.ei5k9uqv3tsr) \* Received \* Processing \* Sent This Option Set is used to determine where in the system the order currently is, so that you can see which orders have been fulfilled or not. You can of course rename or add as many options as you see fit for your business. ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.8zfpl9lbgo9s) Keep in mind for this guide that it takes a very general approach to Shopping Carts: you may have entirely different needs depending on whether you are selling t-shirts, takeaway food or hotel stays: but the principle remains the same. You need a cart for the User to organize whatever they are buying, and you need to maintain some historical data for what exactly they bought. You are of course free to use the guide as a basis for your own system and add whichever fields you think makes sense. But keep in mind that privacy is key, and that Privacy Rules are the only way to truly keep data secure. ## About Amlie Solutions and Petter Amlie [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md#h.5ksov1duconc) This guide is written by Petter Amlie. Petter is the founder of \[Amlie Solutions\](https://www.google.com/url?q=https://www.amliesolutions.com/\\&sa=D\\&source=editors\\&ust=1649034899453164\\&usg=AOvVaw1Omdl7h4ooYIAgruAtYNQh), a no-code expert, public speaker and author of two books on \[Bubble: The Ultimate Guide to Bubble Performance\](https://www.google.com/url?q=https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-performance/\\&sa=D\\&source=editors\\&ust=1649034899453585\\&usg=AOvVaw1QAHmz6vJ4osXDOwB3dFlb) and \[The Ultimate Guide to Bubble Security\](https://www.google.com/url?q=https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-security/\\&sa=D\\&source=editors\\&ust=1649034899453939\\&usg=AOvVaw11XrgeTAjc98SGiUlWjCeV). You can find a growing number of free guides, video courses and in-depth articles on his website. ## Other ways to learn Articles \* \[eCommerce and payments\](/help-guides/getting-started/building-your-first-app/ecommerce-and-payments.md) - this article series covers different ways in which you can monetize your app and use Stripe to collect payments Core reference: \* \[Stripe plugin\](/core-resources/bubble-made-plugins/stripe.md) - list of all Stripe plugin features External documentation \* \[Stripe Docs\](https://docs.stripe.com) \* \[How Stripe Checkout works\](https://docs.stripe.com/payments/checkout/how-checkout-works) \* \[Stripe Checkout demo\](https://checkout.stripe.dev/) \--- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md). # Gallery Apps \*By Zeroqode Team\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Speaking about gallery type of apps will surely lead you to apps like Instagram, Facebook, Pinterest, and many others. Gallery apps often come with features like image management by categories, comment threads for each image, likes/dislikes from other users, and others. We can use Instagram as an example of such an app. The following article will show the recommended data types and option sets that can be a good starting point when developing the database of your gallery application. An app built with such data types will allow users to efficiently upload, manage and share images in a user friendly way. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.8gkrwvp3rqds) The key data type is GalleryImage, which corresponds to the type of item being displayed in the gallery. Users upload GalleryImages, sort them into Categories and can create Comments on anybody’s Images. ### GalleryImage [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.a6xt1t8tg7zl) The key data type that is used in this kind of application. Images can be stored both within the app itself or on third-party storage (to lower the database storage costs). #### Suggested fields on this type \* image (image): most important field, where the image file itself is stored \* title (text): a title can help other users better understand the image \* description (text): in addition to the title, a short description can be useful too \* categories (list of Category): stores one or multiple Categories that the image is attributed to Optional \* favorite (yes / no): lets a user mark certain of their own images as favorites, e.g. so that they can be displayed at the top of that user’s profile page \* Note: if you want to build the feature to allow other users to “like” another user’s image, that would most likely be its own data type and is beyond the basic starting point of this guide; see \[this documentation\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) for guidance \* views (number): saves how many times the image has been viewed by users #### Privacy rules for this data type Assuming this is a public gallery, where anybody can see the images in the gallery, we might not need any privacy rules on image since none of the fields are particularly sensitive. You may want to consider allowing the creator of an image to use auto-binding to modify some of the fields within their control, like the title, description, categories or favorite. ### Category [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.2jksxnbzf7b1) For better image management and UX, our app will be able to assign one or more categories to an image. This is conceptually similar to an “albums” feature or a “tags” feature. #### Suggested fields on this type \* name (text): the category’s name \* images (list of images): stores the images assigned to this category \* Note: here we are choosing to both save the assigned categories on an image as well as save the assigned images on a category; this is effectively double-writing the data and this decision comes with its own advantages and disadvantages; see \[documentation\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) to learn more #### Privacy rules for this data type Since this is not sensitive information, we likely do not need privacy rules on this data type. ### Comment [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.lkw2dboczarw) Publicly available images often come with a comment thread where any user can leave a comment. This data type stores each comment as its own thing in the database. #### Suggested fields on this type \* contents (text): stores the comment text \* galleryimage (GalleryImage): attributes the comment to a specific image in the database \* hidden (yes/no): a useful field to have in case you want the ability to moderate comments #### Privacy rules for this data type Generally our assumption is that all comments can be viewed by anyone, so again we probably do not need privacy rules here. If you want to build a moderation feature, you can create a privacy rule to not find any Comments in searches if ‘hidden’ is yes. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.vszptx8flr9k) All apps come with the User data type. We’ll assume that there are different ‘levels’ of users in this app with different privileges #### Suggested fields on this type \* displayname (text): stores the name the user wants to be publicly seen as \* role (User Type): stores whether the user has special permissions like moderator or admin rights #### Privacy rules for this data type User information tends to be sensitive, so privacy rules are a good idea here. You likely want to create privacy rules so that only the user can see their own email address, for example, while the displayname field is what’s public to everyone. If you want admins to be able to see users’ emails too, that would be another privacy rule on User to allow that. You likely also want to hide the role of the user from anybody except themselves, moderators and admins. Note that if you have the role here, you can create privacy rules on previous data types we’ve seen (e.g. the hidden field on Comment) so that moderators and admins can update that field as needed. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.krr8nsqafyt) \### Category [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.3idpj0auikcb) \* Fashion \* Cars \* Sport \* Health You can extend this list to include any categories that fit your app and audience. It is also a decision you have to make as the app creator whether to have Categories as an option set or a data type - \[here\](https://manual.bubble.io/help-guides/structuring-an-application/option-sets#options-vs.-custom-types) is some documentation to help you with that choice. ### User Type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.r2y793v6o46v) \* Admin \* Moderator \* User This option set is used to define the available user types. Different user types can have different permissions in the app. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.jge3g9i9dho3) \* On the homepage of the app, you could show all images in the gallery by using a \[repeating group\](https://manual.bubble.io/core-resources/elements/containers#repeating-group) doing a simple search for GalleryImage with no filters. \* For each user’s profile page, you can fill a repeating group with a search for all GalleryImages with the filter that the creator is the \[page’s user\](https://manual.bubble.io/help-guides/working-with-data/displaying-data#defining-a-pages-thing) \* When you ‘click into’ a GalleryImage, you might have \[a page that just features that one GalleryImage\](https://manual.bubble.io/help-guides/working-with-data/displaying-data#defining-a-pages-thing) with a repeating group that is filled with a search of all Comments where the galleryimage is the GalleryImage of the page ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.87dub4ais1xl) To make your app attractive, it would be nice also to integrate the possibility of image editing, adding short videos like Tik Tok, as well as receiving push notifications and following/unfollowing other users. The suggested data types and option sets are just a recommendation, so feel free to build your app in your own style! ## About the author: Zeroqode [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md#h.dao7w15pbi47) BTW, good examples of ready-made gallery Bubble apps are the\[ Clonegram\](https://zeroqode.com/template/clonegram---images-like-instagram-template-1509722383555x389657806226849800) and \[Flicky\](https://zeroqode.com/template/flicky---image-hosting-like-flickr-template-1501857333788x490438978221113340) templates from\[ Zeroqode\](https://zeroqode.com/). They also have built a great range of 🔌\[ Plugins\](https://zeroqode.com/plugins) to boost the development of your Bubble app, as well as 🎓\[ Lab\](#suggested-fields-on-this-type-1) courses to improve your Bubble skills. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md). # Documentation/ CMS Apps \*By Rico Trevisan from Refactoring NoCode\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Documentation: that thing we should all be making more of, we are always lacking from others, and we never read enough of it. The challenge of creating a system for documentation is how complex a "simple" thing can be. Luckily, Bubble allows you to grow your system as your needs grow because it's easy to refactor in Bubble. In this guide we will create a simple blogging system that is beautiful in its minimalism, yet powerful and easy to upgrade. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.8gkrwvp3rqds) Here are the data types I recommend: \* Page (or you could call it Post or Article or Document) \* Block \* Block Type (option set) \* Published Status (option set) A Page is an individual blog post (or a piece of documentation) which is composed of multiple Blocks. Each of these Blocks have different types which are determined by Block Type. Each Page has a certain Published Status to allow you to have multiple drafts and only publish the ones that are ready. ### Page [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.3pxvwyrme17k) Page is the anchor of our system. Everything will be built around it. It needs to be "light" enough to make searching through all posts quick. This means the Page has no body; instead, the body is made up of a \[repeating group\](https://manual.bubble.io/core-resources/elements/containers#repeating-group) of Blocks instead, as we’ll see below. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.odv2zklvu6rp) \* Title (text): This is the title of the post. It will be used in the landing page with the list of posts, on the page of the post itself, and it will be what search engines will see. \* Slug (text, built-in field): slug is the title transformed into a URL-friendly text field. \* Description (text): The 2 to 3 sentences that give the reader a sneak peak of what's in the post. \* Published Date (date): A date of when the post has been published or of when it is scheduled to be published. \* Status (Published Status, an option set): What controls the visibility of the Page. \* Author (list of Users): Making this a list allows you to have co-authors !\[\](/files/h1ROv8YyBE82ycpvr2VD) #### Privacy Rules [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.s12vnafckn5) A rule for when “This Page's Status is published” should allow anyone to view all fields and find this in searches. !\[\](/files/LWcFtMtsZqqdYhNnZGvQ) Otherwise (the default rule), it should not be visible. !\[\](/files/iqJvwiIIuTQ6yOAh1Ktq) ### Block [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.16h8hzhjg7ku) This is the body of each Page. If we were to create a single gigantic Page with one field called body that houses the entire blog post, each Page would be too heavy to be able to quickly search through them and we would not have a lot of flexibility in how to display the content. Instead, we think of each Page as a listing of all the Blocks that make up the Page’s contents. We do that by using a Repeating Group that searches for all Blocks that relate to that Page, sorted by the Index. !\[\](/files/ERPoYVUT1bkczpE91D99) Each row of that repeating group contains all the different ways that Blocks can look, depending on the field called ‘Type’. All these different looks are invisible and collapsed by default, and then only the one that matches that Block’s Type will show up as visible. !\[\](/files/qJhMYbauW1BNNzQa4Md4) Each block is marked as invisible and collapsed by default. !\[\](/files/QeiyQNYqWJtgeTigfdGN) The Block only becomes visible if the current Block Type matches it. !\[\](/files/IA3BrxgcOZJzq5AOUG5S) !\[\](/files/satCJS8ShhEerqvrB41k) This way we have the flexibility of styling each block differently while maintaining visual consistency for all Pages. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.5cnfta5nbsdq) \* Page (Page): This links this Block to its respective Page. \* Index (number): Since in this method you will create a bunch of blocks to create a Page, you need a way to order them. \* Content (text): This is the text that this Block will display. \* Image (image): If the block is of a type Image, this is where it will get the image. \* Image Description (text): Most blogs will have a text under an image either clarifying it or giving credit to the original owner. This field is for that. \* Type (\\\_block\\\_type, an option set): This is the field that sets how this block should look on the page !\[\](/files/BU1lGANu9f6b8WezblBo) #### Privacy rules [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.dmqro9rekhag) We can keep it simple and have this type without many restrictions. The only restriction that might be useful to apply is one that allows an admin to allow auto-binding. In a simple case, we can consider a logged in user as an Admin. !\[\](/files/763Bkmtdut8LXO0m8TIs) ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.krr8nsqafyt) \### \\\_block\\\_type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.ei5k9uqv3tsr) \* h2 \* h3 \* body \* image This is a small set that can get you started putting together content. You could add more visual flare by creating new ways to visualize blocks. Ideas that could help you expand your types of blocks: quote, a note block, an image + text, code block, YouTube video… the possibilities are endless. Why no H1? Well, the title of the Page should be your h1 and everything else will be children of it. ### \\\_published\\\_status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.dd15d02z5md4) \* draft \* scheduled \* published Simple set of status to manage each blog post. ## About the author: Refactoring NoCode [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md#h.5ksov1duconc) Refactoring NoCode is an educational and development agency. We create educational content to help experienced Bubblers improve their apps. We also work with solopreneurs by doing unlimited development & design on their apps. \[https://refactoringnocode.com\](https://refactoringnocode.com/) For example, we’ve created a documentation app based on these principles. Try it out yourself: \[https://docengine.io\](https://docengine.io/s/doc-engine?i=1642192173204x433476350563992000) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md). # Bubble as a backend \*By Robert Brooks, Founder & CEO, MVP.dev\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} In this guide, Bubble.io will be used as a backend service with an Arduino board to capture sensor data for a pump in a remote area. The module will monitor the pump and receive alerts if the pump fails or if the sensor data indicates a problem, and send the data back via satellite communication. The data captured by the Arduino board will be saved in Bubble.io using REST API calls, as well as storing configuration data. The module can also be used to remotely control the pump, turning it on or off as needed. Bubble is great in these sorts of backend as a service scenarios for quick proof of concept builds, or even production ready solutions. Create the data types and making them available via API is extremely quick and easy ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.30j0zll) The Bubble backend solution will be storing configuration information, pump status data, as well as time series data for the historical record of each pump. Data types will be Users, Pumps, Configurations, Alerts, and Pump History ### Users [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.1fob9te) The users data type stores information about the users that have access to the Bubble platform to make configuration changes, turn the pumps on and off, monitor alerts, and view historical data. #### Suggested fields on this type \* Email - text \* First Name - text \* Last Name – text \* Role – Roles: Option set that defines the access level the user has to in the database and app; this will be used for the privacy rules of many other data types \* And any other fields that might be relevant for platform users #### Privacy rules for this data type \* Users can: \* View all fields except the following: \* Slug \* Created Date \* Modified Date \* Find this in searches \* View attached files \* Users with the Admin role can view all fields for all users, as well as find in searches, and view attached files ### Pumps A pump is the unit being controlled in the field to monitor pumps, send commands, and capture alerts. #### Suggested fields on this type \* Name – text \* Location – text: lat/long coordinates of the pump; alternatively, this could be stores as a geographic address if that’s granular enough for our use case \* Status - text \* Active – yes/no #### Privacy rules for this data type \* Users with the Pump Tech and Pump Admin roles can: \* View all fields except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Configurations [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.3znysh7) Configuration settings for each pump. Though this could be included in the Pumps data type, we’re using a separate data type so that a group of pumps can have the same configurations and for learning purposes. #### Suggested fields on this type \* Name – text \* Pumps – List of Pumps: A list of pumps to which these configurations apply \* Schedule – date range: time the pump will turn on and off \* PercentOpen – number: number from 0-100 to determine how much the pump may be throttled \* Threshold – number: fault tolerance before an alert is triggered \* Active – yes/no #### Privacy rules for this data type \* Users with the Pump Tech and Pump Admin roles can: \* View all fields except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Alerts Info about alerts triggered by a pump are stored here. #### Suggested fields on this type \* Pump – Pumps: The pump that generated the alert \* Description – text \* Alert Type: Alert Types: Option set for the type of alert triggered \* Severity: number: A range of 1 – 5 that is sent by the Arduino controller that measures the severity of the alert #### Privacy rules for this data type \* Users with the Pump Tech and Pump Admin roles can: \* View all fields except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ### Pump History Pumps are polled hourly and the information is stored here for future reference. #### Suggested fields on this type \* Pump – Pumps: The pump this record belongs to \* Title – text \* Description - text: This stores whatever information you want to log each hour #### Privacy rules for this data type \* Users with the Pump Tech and Pump Admin roles can: \* View all fields except the following: \* Created Date \* Modified Date \* Find this in searches \* View attached files ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.2et92p0) \### Roles [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.tyjcwt) \* Pump Tech \* Pump Admin \* Administrator Sets the access level the user has to the platform ### Alert Types \* Pump On \* Pump Off \* Pump Failure \* Pump Warning List of alerts the pumps can generate ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.3dy6vkm) There are unlimited scenarios and use cases for using Bubble as a backend. From API Management, to BLE RFID data storage, to unmonitored task execution, the possibilities are only limited by your imagination. ## About MVP.dev [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md#h.1t3h5sf) At \[MVP.dev\](#h.1t3h5sf), we help business owners harness the power of no-code technology to bring their vision to life in weeks through a high-touch proven process. Rather than holding your tech hostage through a drawn-out and mysterious process, we’re passionate about partnering and collaborating with you every step of the way — from idea to design to development to delivery. We lean on your vision and our experience to create a truly unforgettable experience and product. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md). # SaaS Apps \*By Gaby Román, Co-Founder of Coaching No Code Apps\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} SaaS app data structures are unique in that almost all of the data needs to be organized under an account hierarchy. For example, every user that signs up might represent a company, so they may have a team, customers, and other resources that should all link back to that parent company. The following data structure is recommended for companies that need a project management tool for internal operations. Users of the app can create and organize projects with related tasks. For example, a manufacturing company with product design and marketing teams would be able to manage the various to-do items within their departments while company managers can track company-wide project statuses and assignments. Overall, this would streamline communications between teams, better visualize company metrics, and help management make more intuitive business decisions. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#id-8gkrwvp3rqds) These data types are designed from the perspective of one company. Every company that signs up to your app will have a single “Company” record in the database, one or more “Users” (team members, managers, etc.), and related resources that are unique to the Company, such as “Customers,” “Projects,” and “Tasks.” The “Subscription” and “Plan” data types will help you manage each Company’s subscription with you, the app owner. The more Companies that sign up, the more records are created, but the key is to relate Company specific records like Customer or Project back to the parent Company for data security. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#u11tp6psyxte) This is Bubble’s only built-in data type. Anyone who needs to be able to log into the app should have a User record. #### \*\*Suggested fields on this type\*\* \* First Name (text) \* Last Name (text) \* Related Company (Company): This field is important for knowing which data the user has access to and can be leveraged in many different privacy rules. \* Privacy rule example under Customer: “When This Customer’s Related Company is not the Current User’s Related Company” > disable all checkboxes \* Role (User Role, an option set): By assigning users with specific roles, you can control their access to pages, visual elements, and workflows. For example, a User whose Role is Company Admin can have the ability to create other Company Members, whereas Company Members themselves cannot. #### \*\*Privacy rules for this data type\*\* The User’s “Role” and “Related Company” will be the starting point for creating privacy rules both for the User data type itself and all other Company-specific types. For the User data type, we suggest creating a rule that only allows users to access other user records within their same company, not other companies. You can do this with the following rule: “Current User’s Related Company is This User’s Related Company.” You can break this down one step further by only giving Company Admins the ability to view more fields and/or edit other Company users; in addition, allowing the current user to have full access to their own record: \* Current User’s Related Company is This User’s Related Company and Current User’s Role is ‘Company Admin’ > view all fields, allow auto-binding \* Current User’s Related Company is This User’s Related Company and Current User’s Role is ‘Company Member’ > view selected fields, don’t allow auto-binding \* Current User is This User > allow everything ### Company [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#e8apxoydszsh) This is a very important data type for SaaS structures because it’s the most parent entity that will help you segment the rest of your app’s data in a single application. \[Sub-app\](https://manual.bubble.io/help-guides/customizing-an-application/sub-apps) structures don’t require this as much if each sub-app is created per company, in which case, they’re already given independent databases. Whether this data type represents a “Company” or an “Account,” make sure all other data types whose records are unique to their parent have a field that ties back to this record. #### \*\*Suggested fields on this type\*\* \* Name (text) \* Admin (User): While this field isn’t necessary (as long as you can identify Users by their role and related Company), it’s a very handy “shortcut” to the Company’s Admin, especially if you need to reference that user often. \* Related Subscription (Subscription): This is a reference to the custom Subscription record created for this Company. It’s another shortcut field that is typically helpful if you have multiple pricing plans that tier off features. Having quick access to the “Company’s \*Related Subscription’s Plan” can make it easier to create conditional expressions.\* #### \*\*Privacy rules for this data type\*\* Users should only be able to access their own Company’s record, which you can do with the following: Current User’s Related Company is This Company > allow full access If you have a User Role for a System Admin (i.e. yourself, the app owner), then you can create a more global rule to give you access to all Companies, like this: Current User’s Role is System Admin > allow full access The default “Everyone Else” rule should have all access options disabled. If the user is not a part of the Company nor a System Admin, then they cannot access the Company record in question. ### Plan [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#id-6qu28i5l5qqb) This is a helpful data type to organize all your subscription plan levels. Our example includes an ID field for a payment gateway (e.g. Stripe, PayPal, etc.) so you have an easy reference to the equivalent entity on the gateway’s side. Note that this is not unique to a Company. #### \*\*Suggested fields on this type\*\* \* Name (text) \* Description (text) \* Amount (number): This would be the amount charged for every billing cycle. E.g. 50 if frequency is set to “Month” vs 500 if frequency is set to “Year” for a discounted annual plan. \* Frequency (Plan Frequency, an option set) #### \*\*Privacy rules for this data type\*\* This data type doesn’t need a privacy rule because it’s not tied to any specific Company and holds no sensitive information. It’s a general system table that describes Subscription Plan options. These need to be available to everyone, including logged out users. ### Subscription [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#kn3k2h1gxv26) This record saves the unique combination of a selected plan for a Company and any details about the Subscription itself such as the active date and status. #### \*\*Suggested fields on this type\*\* \* Related Company (Company) \* Related Plan (Plan) \* Active Date (date) \* Canceled Date (date) \* Status (Plan Status, an option set): This is a helpful field to keep track of which Companies are active or not and what kind of access they should have. \* Payment Gateway ID (text) #### \*\*Privacy rules for this data type\*\* Create rules that give the System Admin and Company Admins access to this record: \* Current User’s Role is System Admin > allow full access \* Current User’s Role is Company Admin and Current User’s Related Company is This Subscription’s Related Company > allow full access ### Customer [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#id-3d4g95k0h4j5) This is an example of a Company resource they might need in a SaaS app. Each Company would have their own Customers to build out their CRM. Again, don’t forget to include the “Related Company” field so that Company users can only have access to Company Customers. #### \*\*Suggested fields on this type\*\* \* Related Company (Company) \* First Name (text) \* Last Name (text) \* Phone Number (text): While it might be tempting to create this as a number, you’ll be able to format phone numbers better for different countries if it's text. Plus, you never need to do math with phone numbers, so you’re not losing any capability. \* Email Address (text) \* Notes (text) #### \*\*Privacy rules for this data type\*\* Only System admins and Company users should be able to access Customers that are tied to their same Company: \* Current User’s Role is System Admin > allow full access \* Current User’s Related Company is This Company > allow full access If you want to split up access to fields and auto-binding by Company Role, you can create separate rules per Role to break that down. ### Project [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#unskwdb4ag3j) This is another company-specific resource record. #### \*\*Suggested fields on this type\*\* \* Related Company (Company) \* Title (text) \* Manager (User): This is a shortcut field to the Company User (whether their role is Admin or Member) that is responsible for this specific project. \* Team Members (list of Users): This is a shortcut field to any Company Users that might be assigned Tasks for this Project. \* Due Date (date) #### \*\*Privacy rules for this data type\*\* Follow the same rules you created for the Customer data type. ### Task [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#sqhngyfjchqo) This is another company-specific resource record and is seen as a “child” of the Project data type. Meaning, a Project is made up of a list of Tasks, but notice how we didn’t include a List of Tasks field under the Project data type. Since a Project could be long-term and potentially have hundreds of tasks, it’s better to have a one-way relationship on the Task side for performance. See \[this article\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types). #### \*\*Suggested fields on this type\*\* \* Related Company (Company) \* Related Project (Project) \* Title (text) \* Due Date (date) \* Completed Date (date) \* Assigned To (list of Users): Here, we chose to make this a list in case a Task should have the ability to be assigned to more than one person. #### \*\*Privacy rules for this data type\*\* Follow the same rules you created for the Customer data type. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#krr8nsqafyt) \### User Role [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#y7pyiuymkkp7) \* System Admin \* Company Admin \* Company Member If your application offers different roles where access to data, pages, or even workflows are specific to that role, an option set is a great way to identify who the users are. ### Plan Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#die4oudnrzy8) \* Active \* Inactive ### Plan Frequency [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#id-8w65ubdtlqqy) \* Month \* Year ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#jge3g9i9dho3) \* Viewing Projects Assigned to Me \* Once the user logs into the app and opens up their “dashboard” page, they should be able to see a list of projects with tasks that are assigned to them. \* The following search expressions can be used to show the user relevant projects: \* Search for Projects (Team Members \*contains\* Current User) \* Search for Tasks (Assigned To \*contains\* Current User) ‘s Related Projects \* Viewing My Tasks filtered by Completion status \* The user should be able to see Tasks assigned to them and filter the list to view which ones are completed, which ones are due, and which ones are overdue. \* The following search expressions can be used to show the user their tasks with various filters: \* Completed Tasks: Search for Tasks (Assigned To \*contains\* Current User; Completed Date \*isn’t empty\*) \* Upcoming Tasks: Search for Tasks (Assigned To \*contains\* Current User; Completed Date \*is empty\*; Due Date > Current Date/Time) \* Overdue Tasks: Search for Tasks (Assigned To \*contains\* Current User; Completed Date \*is empty\*; Due Date < Current Date/Time) ## About the author: Coaching No Code Apps [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md#yekgzloqmodg) Your database structure creates the entire foundation for your app as a whole, and because of its importance, it's one of the first things we focus on with our own clients before moving onto broader functionality. For help putting all the right pieces into place and creating a scalable app using Bubble, join a free workshop focused on scoping, building, and launching your no code app at . --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md). # Applicant Tracking System (ATS) Apps \*By Tinkso\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} You’ll build an app that helps recruiters manage candidates & track the various steps in the hiring process in a scalable way. An Applicant Tracking System (ATS) includes job postings that can also be publicly available and shareable with potential candidates. Depending on your type of ATS, we will build a foundation that will allow you to create more complex features on top of it. Most ATSs have a built-in notification and communication system that allows recruiters and whole teams to manage large numbers of candidates. Popular ATS examples are: Jobvite, SmartRecruiters or Workable. While we’ll focus on data architecture, this type of app is usually made of these elements: \* Forms allowing you to create a new job posting and candidate profiles \* Display and filter a list of applications as well as candidates \* Application detail page containing job details and funnel around current candidates that applied to that position ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.8gkrwvp3rqds) Users - who we can think of as recruiters - will be creating Talents (a person who is a candidate for a job) and Job postings. We will automatically create an Application when Users associate a Talent to a Job. Users are grouped into Companies. Each Company can have one or more users and many Talents and Job postings. Note that a Talent can only belong to one Company - if the same real-life person applies to two separate companies, each Company would have its own Talent record for that candidate. The Application data type allows us to track multiple Talents throughout all the stages of the hiring process. This structure enables you to assign a Talent to multiple Job postings without the need to copy unnecessary data. ### Company [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.327bye5z0rn0) The Company data type keeps all Talents, Users and Applications neatly organized in a way that Users from one Company cannot see other Companies and all the data they create. All Talent, Applications and Jobs will be grouped per Company. This will allow us to create an application that can be used by multiple unrelated companies. #### Suggested fields on this type \* name - text \* logo - image \* phone - text #### Privacy rules for this data type Current User’s Company is this Company: this user can see all information connected to that Company. This allows a user to see the information about their own Company, but no other Company (the default rule should not show anything). ### Talent [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.zdme0zd3z2lh) A Talent is a profile of a given candidate for a given company. It contains all the necessary details about the applicant. #### Suggested fields on this type \* firstName - text \* lastName - text \* fullName - text \* contactEmail - email \* phoneNumber - text \* aboutMe - text \* CV - file \* Tags - list of texts \* Notes - text: additional information from the recruiter about the candidate. \* TalentStatus - option set: when first creating talent we can default to Available. If this talent will be hired, we can update it to Hired status. This field will allow us to manage Talents which have applied to multiple Job positions, and filter that data appropriately. \* Company - data type: Company to which the Talent belongs. In our system, one Talent cannot apply to more than one Company; if the same real-life person applies to more than one Company, they would need separate Talent records for the sake of keeping the data between Companies separate #### Privacy rules for this data type Company data type on the Talent will allow us to create a Privacy Rule: When this Talent’s Company is Current User Company. All of the Talent information should only be accessible to Users to which this privacy rule applies. ### Job [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.hcjog4r23y75) Job is a job position to which a candidate applies. It contains all necessary information for the recruiter and candidate if the Job position information is made public. #### Suggested fields on this type \* Position - text \* Description - number \* Notes - text: information that should stay confidential, for recruiters only. \* JobStatus - option set: job status will allow us to filter data and manage all the Jobs within the ATS. \* Hired - Application: only one candidate can be hired per position, and when that happens we will update this field with the right Application. \* Company - data type: Company to which the Job posting belongs. \* Optional: Hired Talent - talent data type: you can also store hired talent on the Job to enable database searches like Display list of Jobs connected to this Talent. #### Privacy rules for this data type If your ATS creates job postings which are publicly accessible, you might not want to disclose some information e.g. the Hired field, to non-logged in Users or Users from a different company. You can set the privacy rules as follows: \* When this Job JobStaus is Open: following information is visible on the Job postings page: \* Position \* Description \* When Job’s Company is Current User Company: this user can see all information connected to that Job. ### Application [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.nsjb5csx95ex) Application combines some information about a Job and a Talent into one data type. It will allow us to track multiple candidates through a recruiting funnel. #### Suggested fields on this type \* Job - data type: an application can only exist if it's linked to a Job. Job details page will display all the applications connected to that Job. \* ApplicationStatus - option set: this will allow us to create a candidate pipeline and track all the applications through the recruitment stages. It can also be used to trigger different logic such as ‘Notify the candidate’ or ‘Change the Status of the Application’s Job to Hired. \* Talent - data type: talent that should be considered in this Job’s pipeline. \* Company - data type: for privacy reasons, we need to store to which Company this applications belongs. \* interviewDate - data: can be used to send notifications to a User and Talent. \* Notes - text: additional information from the recruiter about the candidate. \* Rating - number: multiple categories for rating can be created. A simple field that will allow the User to rate the candidate from 1-5 and later filter the applicants for that position to better match possible hires. #### Privacy rules for this data type When Job’s Company is Current User Company: this user can see all information connected to that Job. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.gyavu5ns4rom) Built-in Bubble app field. Application user. It’s the recruiter that manages job applications within the app. #### Suggested fields on this type \* firstName - text \* lastName - text \* fullName - text \* Email - text \* userType - option set: you can manage permissions within the app based on the userType (e.g. admin recruiter vs basic recruiter) \* Company - data type: company to which this User belongs #### Privacy rules for this data type \* When this User is Current User - see all fields. \* When this User type is Admin Recruiter and This User’s Company is Current User Company - see all fields. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.krr8nsqafyt) All of the option sets listed below create flexibility in managing the Talent, Job and Applications within the app. You can easily add new options to create an even better experience for the end-user and allow them to manage the process more granularly. ### Job Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.94gwdtfrmpr) \* Open \* Matching \* Hired \* Closed Job status will allow us to manage a large number of jobs and filter results in searches. ### Application Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.sa316atfhoib) \* Applied \* Interview \* Rejected \* Hired Application status will help us track the current state of recruitment for specific positions. ### Talent Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.atxkotfepyic) \* Available \* Hired \* Not-available Talent status will help us manage available talent within our application. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.jge3g9i9dho3) The main search of the app is based on the Application data type which has information from other data types. You can set up it up the following way: \* Remember to set the \[‘Ignore empty constraints’ \](https://manual.bubble.io/core-resources/data/search#ignore-empty-constraints)on the search. \* You can sort either by InterviewDate or Creation Date field. \* The layout of the repeating group will depend on your app’s design. We recommend going either with extended vertical scrolling or introducing pagination for a better User Experience. !\[\](/files/aOoijaXDmTURjvKMJc7c) ## About Tinkso [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md#h.37ci9znk065g) Tinkso (\[tinkso.com\](https://tinkso.com/)) is a pioneer and leader in professional no-code and low-code product development. Our unique approach allows our clients to run successful businesses, raise millions in funding and scale professionally. Our suite of tools consists of \[openBuild Framework\](https://openbase-template.bubbleapps.io/), \[openBuild UI Builder\](https://www.openbuild.io/?tab=Navigation%201) and a range of other tools, turns makers, freelancers and businesses in professional Bubble app builders. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md). # Messaging App \*by Rémi Fossembas from Apeable an official Bubble coach\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Instant messaging apps include ones like Messenger, Whatsapp or Slack. This is a chat application that enables users to instant message and connect with each other. Users send text messages, images, videos, links or files to each other, and other users can reply and react with emojis. This guide’s data structure and logic can be used: \* as a stand-alone app whose purpose is to connect people with each other. By pushing it to a new target population, you will be able to take a slice of the communication market \* or as an additional feature of your app. This module will ease communication between your users and make your app more fun These suggested data types and option sets should help you build common functionality for messaging apps in a way that keeps things scalable. Preview this messaging app’s data structure by following this link: \[Messaging app\](https://bubble-appmessage.bubbleapps.io/version-test/messaging\_app) ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.8gkrwvp3rqds) To connect with each other, users (USER) will create channels (CHAT-CHANNEL) with one another (or with groups). When a user presses the “Send” button a new message (CHAT-MESSAGE) is created to store the value of this message, which can be text, images, who has seen it, etc. Someone in the channel may want to react to this message by selecting an emoji which will create a (CHAT-REACTION) stored as a list into the message’s record. \\ We’ll also cover the feature allowing you to create a list of your favorite contact users (CONTACT). ### CHAT-MESSAGE [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.w9wi4proi6jw) CHAT-MESSAGE is where the visual information of a message is stored in the database. It belongs to a CHAT-CHANNEL so that you can perform a “Do a search for” all messages in a channel to find all of a specific thread. This data is protected by the field VISIBLE BY that allows only users in this list to search, view files and view fields of this message. Everyone else has no access to it. #### Suggested fields on this type \* Type (type, an option set): this field is used for identifying what kind of message content it is, also so that we can control how the message is rendered visually. For instance if the message type is “image” you won’t show the text element of the message. !\[\](/files/Blk6DuOqdY7eoa4jLVbi) \* Value-text (text): this is the content of the message when this message has Type = text. For instance this field will be empty when your message Type = image, but if Type = text it could be “Hello John”. You could also set Type = link to use BBcode, a special way of storing text that allows for rich text content like links or formatting, for example, “Look at this nice car: \\\[url=. \* Value-image (image): this is the content of the message if this message’s Type is image (or link with a preview). \* Value-file (file): this is the content of the message if this message’s Type is file. The value of this field can be displayed as a link in the text element of the message. \* CHAT-CHANNEL (CHAT-CHANNEL, another data type): is the reference of the thread this message belongs to. !\[\](/files/0UXBVSdZVdnPHR9hoTkb) !\[\](/files/vpE0lL3NpFj1esxGRaMf) \* VISIBLE BY (list of USERS): is set for privacy purposes: only users of this list can view this message. Every time a message is created, set this list of users to all users that belong to this chat channel. When a user is added to the channel, add this user to all previous messages. \* OWNER (USER): is often the Current User but that field allows you to create messages on behalf of someone else. It can be useful if you need automated messages sent by a bot for instance. \* SEEN BY (list of USERS): is set to Current User when the message is created, then users are added when they have read the message. This allows for helpful features like displaying the number of unread messages a user has: Perform a “Do a search for” CHAT-MESSAGE: count, with Constraints: \* CHAT-CHANNEL = XXX \* SEEN BY doesn’t contain Current User \* VISIBLE BY contains Current User (not needed if previous Privacy Rules is set properly) !\[\](/files/NsqgIask5gAxwYCvW0an) !\[\](/files/X1NExwOhnb4NmftjM1Kz) \* CHAT-REACTIONS (list of CHAT-REACTIONS): allows users to react to a specific message with Emojis or Likes. !\[\](/files/eDxfvAhmGIsxfeCfscZA) !\[\](/files/OpgAIWrE66Znh0fJBA2y) \* CHAT-REPLY (CHAT-MESSAGE): stores the reference of a message that this one was a reply to. In the case where a user wants to reply to a message, you need to store that relationship somewhere. Let's say the original message is A and the reply is B, then save in message B's CHAT-REPLY the message A's value. !\[\](/files/lNSy06HRugc2K9OaV5wT) !\[\](/files/ApG8vaP4CaHIJhWG4Nrb) #### Privacy rules for this data type \* Make this data type private by default: uncheck all the boxes under “Everyone else (default permissions)” \* Create a rule: \* When: This CHAT-MESSAGE’s VISIBLE BY contains Current USER, they can “View all fields”, “Find this in searches” and “View attached files” ### CHAT-CHANNEL [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.6ty78c2ynl3u)\ This Data Type is the primary way to keep messages organized by threads. #### Suggested fields on this type \* Name (text): especially useful if threads are organized into channels with a list of Users. \* PARTICIPANTS (list of USERS): is set for privacy purposes: only users of this list can view this channel. Add users to this list so they can see the thread and participate in the conversation. !\[\](/files/7eArlspB1IdGwuHmkiEa) !\[\](/files/rjOdyWAa4oaMBRR2TMIN) \* ARCHIVED BY (list of USERS): allows each PARTICIPANT of the channel to archive a thread but can still unarchive the thread if desired. This data type isn't mandatory for the messaging system to work, but it's an option that allows each user to mute threads and no longer receive notifications. #### Privacy rules for this data type \* Make this data type private by default: uncheck all boxes under “Everyone else (default permissions)” \* Create a rule: \* When: This CHAT-CHANNEL’s PARTICIPANTS contains Current USER, they can “View all fields”, “Find this in searches”, and “View attached fields” ### CHAT-REACTION [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.mtzpmp3yvvsd)\ This Data Type allows users to react to a message with some Emojis. This is a separate Data Type instead of a field on CHAT-MESSAGE because multiple users might react to the message, each with a different reaction (emoji). Because we need to store at least two pieces of information about each reaction (the person reacting and their emoji), we can’t store it simply as one field on CHAT-MESSAGE and instead have to use a new Data Type. #### Suggested fields on this type \* OWNER (USER): is the creator of this reaction \* CHAT-MESSAGE (CHAT-MESSAGE): the message that the reaction belongs to \* Emoji (Emoji, an option set): this will have choices like 👍 👎 😂 💙 #### Privacy rules for this data type \* Since this data type alone will not contain information that is too sensitive (since the CHAT-MESSAGE’s contents are not stored with each reaction, just a pointer to the relevant message), we could just leave this visible to everyone ### CONTACT [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.1wjkbpgg3oe1)\ This Data Type allows users to have a list of contacts. #### Suggested fields on this type \* OWNER (USER): is the creator of the contact list. \* CONTACT (USER): is the user added to this list. #### Privacy rules for this data type \* Make this data type private by default: uncheck all boxes under “Everyone else (default permissions)” \* Create a rule: \* When: This CONTACT’s OWNER is Current USER, they can “View all fields”, “Find this in searches”, and “View attached fields” ### USER [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.9dza5rizw2gu)\ Standard built-in Bubble app User. #### Suggested fields on this type \* First name (text) \* Last name (text) \* Profile picture (image) \* Email (built-in field) #### Privacy rules for this data type \* Make this data type private by default: uncheck all boxes under “Everyone else (default permissions)” \* Create a rule: \* When: Current User is logged in, they should be able to view “First name”, “Last name” and “Profile picture” fields if you want all users to be able to see each others’ information. “Find this in searches” should also be checked if you want users to be able to find each other, such as by name. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.krr8nsqafyt)\ \### Type (of CHAT-MESSAGE) [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.z8zuvd6h0oy6)\ \* text \* image \* link \* file \* video This option set is used for saving what format a message is. This helps when it comes time to build what the page looks like, and you want to render different formats of messages differently. For instance if a message Type is “image” you won’t show a text element of the message. ### Emoji [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.n3g1y243ouw7)\ \* 👍 \* Text: \\👍 \* 👎 \* Text: \\👎 \* 😂 \* Text: \\😂 \* 💙 \* Text: \\❤ You can of course add as many emojis you want. You can display them in a text element using the option set’s Display or in a HTML element using the text’s value. If you want to allow your users to create their own list of reactions, you would use a new Data Type instead of an option set. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.jge3g9i9dho3)\ \* Display the list of channels the Current User belongs to: You actually don't need to apply a constraint filter when doing a search with the current user because the privacy rules already ensure that a user can only see channels they are a member of. !\[\](/files/FiVbOiGQZwkZMq2afnIe) \* Display the list of messages of a specific Channel. In the screenshot below, the value of the CHAT-CHANNEL is given by the Parent group that this Repeating Group is in. !\[\](/files/D7TunemkBwKZ1T5URnG5) \* Display the list of reactions to a specific Message. In this case, the value of the CHAT-MESSAGE is given by the Parent group that this group is in. !\[\](/files/eYSLUoPizxMlqs4LkTKM) ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.8zfpl9lbgo9s)\ You might want to allow your users to bookmark some specific messages, like you can on Slack or on Bubble forum, so they can easily access a list of bookmarked messages at any time without having to go through all the threads to find them. To do so, follow similar logic to how we set up CONTACT, namely a new data type for storing just this information: \* OWNER: (USER) is the creator of the bookmarked message. \* MESSAGE: (CHAT-MESSAGE) is the bookmarked message the owner wants to add to his list. ## About the author: Rémi Fossembas [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md#h.56fc4fdvwt7b)\ Rémi is from \[Apeable\](https://www.google.com/url?q=https://apeable.co/\\&sa=D\\&source=editors\\&ust=1649034621764923\\&usg=AOvVaw1HLl9Q\_vfrfMSIAX4ysWoD) and is an \[official Bubble coach\](https://www.google.com/url?q=https://bubble.io/coaching?coach%3Dremi\\&sa=D\\&source=editors\\&ust=1649034621765209\\&usg=AOvVaw0quSfR4\_oRJ4oyIm6W88id) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md). # CRM Apps By Petter Amlie, founder of Amlie Solutions {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} In this example, we are building a CRM or Customer Relationship Management software. This is used by organizations to keep track of their clients, vendors and contacts. Well-known CRM examples are Salesforce, Insightly, Zoho CRM and SuperOffice. We’re going to set up a CRM that allows multiple clients to work in the same software without seeing each other’s data (typically called a SaaS model), and this will be reflected in some of the ways we structure the Data and Privacy Rules. What this means in practice is that I, as a paying client, will only have access to see and make changes to my own data, and I can trust that nobody else has access to my data. Additionally, the way we set it up allows for multiple Users for each client, since the client will typically be a company itself. This way, an account owner can invite their team into your CRM platform to collaborate on sales processes and customer management. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.8gkrwvp3rqds) We’ll be working with a fairly simple set of Data Types to show the principles behind the multi-client CRM model. This could easily be extended with more Data Types (such as Deals, Projects, Tasks and Meetings) using those same principles. Most Contacts and Companies added to the platform will start their life-cycle as a Lead, that then becomes a Contact and/or Company as it moves through the sales process. ### ParentOrganization [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.gj3zbuele19z) The ParentOrganization is the organization that your app’s Users belong to. For example, I might register as a company called Acme Inc. and add all my 25 employees to that ParentOrganization. Those 25 employees will then have access to only data that belongs to their ParentOrganization, and nothing else. To make this happen, we need to add the ParentOrganization to all other Data Types and set up Privacy Rules for each of them. The ParentOrganization is created when the first user in that organization registers in your application, and then that User invites their team to that organization. In principle, this organization only needs a name; we can set up the Data Type as below: #### Suggested fields on this type \* Name (text) \* Owner (User) - this will be the User who first registered the account and is the owner, or admin, of it #### Privacy Rules [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.tc8d8z3ta91v) As we explored earlier, the ParentOrganization makes up the primary security “fence” of your application: all Users should only be able to access data that belongs to their ParentOrganization. This also means that we need to keep the ParentOrganization itself private: Users outside of my organization shouldn’t even know that we have an account. So let’s set that up like this: If this ParentOrganization is Current User’s ParentOrganization, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: no Ok, so that Rule lets only Users who belong to that ParentOrganization to see its details, but note that we’re blocking access to edit it. But remember, when the Organization is first set up, we also set up a field for Owner. That particular User should be able to make changes to their own organization. That would look like this: If this ParentOrganization’s Owner is Current User’s ParentOrganization, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes Notice the last rule in bold: since this User is the owner of the ParentOrganization, we’ll allow that User to make changes to it. ### Company [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.g4k1ykhh3l9n) Now we move on to the actual data that your Users will store in the CRM. A Company is any organization that you add to your CRM that’s not your own. A Company can be both a Client and a Vendor, as separated by the Company type field. We have added a few standard fields like phone number and address, and you can of course add as many more as you need to store more information. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.yip3zvhoprgt) \* ParentOrganization (ParentOrganization) - connects this to the entity who owns this data and thus should be allowed to see it; see \[this article\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) \* Name (text) \* Address (Google Maps address) \* Phone (text) \* Website (text) \* Type (list of Company Types, an option set) - note that this is a list of Company Types. If you add just Client to that list, then the Company can be sorted as a Client, and the same if you add Vendor. However, since we’re using a list here, you can add both Client and Vendor, allowing a Company to be both. #### Privacy rules [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.qw2p8xf8nv7m) Since we set up our ParentOrganization in the last step, we now need to make sure that the Company type we’ve created is only available to Users who belong to the Organization to which it was added: If this Company’s ParentOrganization is Current User’s ParentOrganization and Current User’s ParentOrganization is not empty, this User can \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes So, our rule says that the Company belongs to a ParentOrganization, and so does the User: as long as these two match, that User can see and edit the Company. Take note of the second condition we’ve added: and Current User’s Organization is not empty - this is an extra level of security that will stop Users from seeing Companies if both the ParentOrganization of the Company and the User is empty (in which case they will technically match). This should never happen, of course: but since software bugs do occur sometimes, this gives us an extra layer of security even in the unlikely case that both the User’s ParentOrganization and the Company’s ParentOrganization is somehow lost or deleted. ### Contact [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.wjgu541sn5zd) In many cases when you add a Company to your CRM, you’ll also want to add Contacts to that Company. A Contact needs to contain information similar to what you would save in your phone’s phone book. A Contact doesn’t have to belong to a Company, but if they do we can use that field to filter and sort Users in our platform: #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.p1k9641hecf) \* ParentOrganization (ParentOrganization) \* Company (Company) - the custom Data Type above \* First name (text) \* Last name (text) \* Phone (text) \* Email (text) \* Address (Google Maps address) \* Date of Birth (date) \* LinkedIn Profile (text) #### Privacy Rules The Privacy Rules for a Contact are similar to a Company: Users should only be able to see Contacts that belong to their own ParentOrganization. Let’s set it up like this: If this Contact’s ParentOrganization is Current User’s ParentOrganization and Current User’s ParentOrganization is not empty, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes ### Lead [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.v2p8sh47ur62) A Lead is a bit different from Contacts and Companies in that they are more temporary. They are basically potential clients: you don’t know whether they will convert to an actual client yet, and your Users may not want to store them as a Contact just yet to avoid overflooding the database with irrelevant Contact and Company records. A Lead can typically come into contact with your Client using a contact form: they’ll provide their contact information, but it’s too early to say whether they’re serious about doing business If a Lead does convert into business, we’ll convert it into a Contact and/or a Company. At this point we’ll create the Contact/Company record based on the information saved in the Lead. Optionally, we can delete the initial Lead at that point (unless you want to keep it around) We’ll introduce a slight change to this Data Type to illustrate what’s possible with Privacy Rules: we’re going to assume that if this Lead was created by an employee, we want only that employee to be able to edit it. We’re going to use the built-in Created by field for that. #### Suggested fields on this type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.bbuqa876l4rj) \* ParentOrganization (ParentOrganization) \* First name (text) \* Last name (text) \* Company name (text) \* Phone (text) \* Email (text) \* Comment (text): if you are generating leads from a contact form, a comment field is a great way to save what kind of interest the lead has in your company. #### Privacy Rules For this one, we’re actually creating two Privacy Rules. One is to make the Lead visible to all members of the same ParentOrganization (like we did with the other Data Types), and the second rule is to let the Lead’s Creator be the only one allowed to make changes to it: If this Lead’s ParentOrganization is Current User’s ParentOrganization and Current User’s ParentOrganization is not empty and this Lead’s Created by is not Current User, this User can \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: no If this Lead’s ParentOrganization is Current User’s ParentOrganization and Current User’s ParentOrganization is not empty and this Lead’s Created by is Current User, this User can: \* View all fields: yes \* Find this in searches: yes \* View attached files: yes \* Allow auto-binding: yes Note like in our ParentOrganization that the only difference is in the final Rule. In plain English, we’re saying that if the Current User created this Rule, then that User should be able to edit it (by allowing auto-bind). \## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.tb2mcrvxrjy0) For any data that’s shared between all Users of the platform and remains fairly static, we can use an Option Set. Option Sets load faster than data in your database, but they’re not meant to hold any private information. In our CRM, we’ll use it to store the two types of Companies in our database. ### Company Type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.fooboa731ota) \* Client \* Vendor The Company Type Option Set is used to separate Client and Vendor companies. We’re storing the Company Type as a List, which makes it possible to make a Company both a Client and a Vendor. ## About the author: Amlie Solutions [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md#h.v5gdvh36m1v6) This guide is written by Petter Amlie. Petter is the founder of \[Amlie Solutions\](https://www.amliesolutions.com/), a no-code expert, public speaker and author of two books on \[Bubble: The Ultimate Guide to Bubble Performance\](https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-performance/) and \[The Ultimate Guide to Bubble Security\](https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-security/). You can find a growing number of free guides, video courses and in-depth articles on his website. … --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md). # Portfolio Apps \*By Tinkso\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} You’ll build an app that allows people to showcase their work and self-promote their projects. Portfolio apps consist mostly of showcasing your work but many similar apps also serve as a networking site for professionals. Most of the users use it for inspiration so almost all of the data will be publicly available. Popular examples of portfolio apps are: Dribbble, Unsplash or Behance. While we’ll focus on data architecture, this type of app is usually made of these elements: \* Form to create a new project \* Search and display a list of projects \* Project detail page \* Personal dashboard listing the projects you have created, liked or bookmarked ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.8gkrwvp3rqds) A Project, which is the main data type, is created by a User. A user is able to create as many projects as she/he wants, each of them linked to that creator. \\ The challenge of this kind of app is to show visitors the projects that match their search, so the filter fields related to the projects are crucial. To keep consistency you might want to prohibit adding Categories, while you allow the creator of a project to create as many Tags as she/he wishes. These Tags will become new filters available to everyone, also available when creating future projects. A logged in user will be able to like a project, which will create a new Like record. Likewise, it will be possible to build a library of projects using the Bookmark data type. ## User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.1jfmbilc2ej8) Built-in Bubble app data type. The user can create a Project, bookmark a Project, and like Projects. #### Suggested fields on this type \* First name - text \* Last name - text \* Email - text \* Profile picture - image \* Company name - text \* Company logo - image \* Location - geographical address \* Website - text \* Bio - text \* Slug - text: using Bubble’s built-in feature. This helps create some clean shareable profile page links. #### Privacy rules for this data type Since the purpose of the app is to show a user’s work and allow them be contacted, all users' fields are public and without privacy rules. Note that this also means your users’ emails are public too - you may want to make it known to users that this is the case, or later tweak your app to make emails private but still allow the outreach functionality. ### Project [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.6gqau9i9g13s) Project is where all the information for a project is stored. You can add as many fields as you want to further filter the projects on the “search for inspirations” page. #### Suggested fields on this type \* Owner - User: is the creator of this project. We don’t use in-built Bubble’s “creator” field as you may want to transfer the project to another user - Built-in Bubble fields don't allow you to edit them. \* Title - text \* Images - list of images \* Tags - list of Tags: this example assumes you want to allow your users to create and grow the number of tags and so we use a custom data type for these, as highlighted below. \* Made with - option set: on the contrary, use option sets if you do not want to let users modify the list in order to keep the choices ordered. Option sets can be faster when loading pages. \* Download with - option set \* Category - option set \* Main color - text \* Description - text \* Number of views - number: this field allows you to display how many times this page has been seen. Run a workflow each time the page is opened that increments this field: Current page Project’s Number of views + 1. \* Slug - text: using Bubble’s inbuilt feature. This helps create some clean shareable profile page links. #### Privacy rules for this data type For the same reasons as for the previous data type, Project has no privacy rules. ### Tag [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.3jx63byizfzt) After being created, users shouldn’t be able to delete this data as long as at least 1 project contains this record. #### Suggested fields on this type \* Name - text #### Privacy rules for this data type Public data type. ### Like [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.aw6k98pssz0m) This data type allows users to like projects. By creating a specific data type for it, it allows you to display the list or the count easily from either a project’s or a user’s point of view, e.g. how many users like a project or how many projects a user has liked. #### Suggested fields on this type \* Creator - User - Bubble built-in field that automatically captures the Creator of a data type. You don’t have to do anything in order to set this field when creating it. It’s fine to use the built-in field here because we aren’t planning to let users ‘transfer’ their like to another user. \* Project - Project - The project being liked. Use this field as a constraint to count the number of likes associated with a specific project. #### Privacy rules for this data type Public data type. ### Bookmark [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.36pjk2dc0isg) Similar to a Like, users can have their own list of bookmarked projects. #### Suggested fields on this type \* Owner - User - Bubble built-in field that automatically captures the Creator of a data type. You don’t have to do anything in order to set this field when creating it. Use that field as a constraint when wanting to display to this user his own bookmarked projects. \* Project - Project #### Privacy rules for this data type You can choose either to make it public so that you can display users' collections, or to make it private so that only the user who this list belongs to can see it. (Apply the following privacy rules if you want to make it private)\\ \\- This Bookmark’s Owner is Current User: ☑View all fields ☑Find this in searches ☑View attached files ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.krr8nsqafyt) All these options have only one purpose: to be able to filter the projects on the search for inspirations page. Create as many set options as you want then add a field with this set option in the PROJECT data type. For instance, these are inspired by Dribbble’s list of options in its search capabilities. ### Made with [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.m25qh61xwixp) \* Figma \* Sketch \* Unsplash \* Adobe XD ### Download with [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.g6k0n9ckxctz) \* Figma \* Sketch \* Unspash \* Adobe XD ### Category [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.my95bcluragd) \* Animation \* Illustration \* Branding \* Web Design \* Mobile ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.jge3g9i9dho3) \* Show and filter projects: Do a search for Projects and add as many constraints as you need. Make sure to tick the box “Ignore empty constraints” in order to display items even when inputs are empty otherwise the list will be empty. Sort the list by descending Created date (Bubble in-built field) to show newest projects on top. !\[\](/files/XeM2rFrIEbmZmNP7NgGz) \* Display each project’s number of likes. !\[\](/files/AfI62V9jMDWqlvXDS6hm) \* Display Current user’s bookmarked projects. If you choose to make bookmarks private with privacy rules, you don't even need to add a constraint. !\[\](/files/Ndp8PDKmcNbG5YSs43rf) ## About Tinkso [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md#h.1jd8pg8yj8x2) Tinkso (\[tinkso.com\](https://tinkso.com/)) is a pioneer and leader in professional no-code and low-code product development. Our unique approach allows our clients to run successful businesses, raise millions in funding and scale professionally. Our suite of tools consists of \[openBuild Framework\](https://openbase-template.bubbleapps.io/), \[openBuild UI Builder\](https://www.openbuild.io/?tab=Navigation%201) and a range of other tools, turns makers, freelancers and businesses in professional Bubble app builders. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md). # Blog Apps \*By Jason K (Founder of\*\[ \](https://www.google.com/url?q=http://www.nocodeminute.com\\&sa=D\\&source=editors\\&ust=1648861627990219\\&usg=AOvVaw3AZRLxUK-hJ1591tn2JD4F)\[\*www.NoCodeMinute.com\*\](https://www.google.com/url?q=http://www.nocodeminute.com\\&sa=D\\&source=editors\\&ust=1648861627990551\\&usg=AOvVaw0ckcz5vI3MhmPLcI9hPveX)\*)\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Many websites use a blog to promote their product, keep their users engaged and display updates about their business. If you are new to Bubble, and web developing in general, you might be struggling to put together the database for it. In this article, we will discuss a few different options to match your skill level and scale requirements. Building a blog with complexity might be more difficult than you might think. Let’s check out some options to help you on your no-code journey! We will go over two options for your data structures for two different levels of how complex your blog will be - we will call them Basic and Scalable. You can choose which data structure you will want to follow according to your needs. There is always more than one way to do something. Here are just a few ideas. ## Data types recommended - Basic example [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.8gkrwvp3rqds) This example is for a basic blog that doesn’t go into much detail. This is not recommended at scale for large blogs but will be fine for a small blog if you are just starting out. Simple design and easy to set up. Great for beginners if you are trying to just set up your first blog. As a site owner you will add your blog information into this main data type allowing for it to be displayed on a blog page. ### blogPost [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.g9w8fpacz6vd) This will be your main data type. This will hold the majority of your data and will normally be displayed in a repeating group on your page. Notice how we don’t pluralize the name here since each one (each “thing”) will be a singular blog post. #### Suggested fields on this type \* title (text): This will be the title of your blog post. \* summary (text): This will be the summary of your article that will be displayed underneath the title \* byLine (text): The name of the person who wrote the article \* content (text): The content of your blog post; here we can use the Rich Text Editor plugin to add images and formatting, but even the resulting rich text can be stored as a “text” by Bubble \* visible (yes/no): This will allow you to turn posts on or off from being visible on your blog #### Privacy rules for this data type We will assume that you want the Blog to be public, so we will keep the data type and all its fields public. When creating the data type, make sure not to check the box to make it private. Similarly, after creating it, there will be no need to create privacy rules for it. ## Data types recommended - Scalable example This example is for an intermediate blog where posts can have more detail and flexibility. As an example, this allows for each blog post to have a different structure to it instead of one standard structure. This should allow for better scaling. This is great for more experienced users if you are trying to just set up a more professional blog. This data type allows you to break out the blog post and blog post content separately. The site owner will create a blog post and then add the blog content as a \[repeating group\](https://www.google.com/url?q=https://manual.bubble.io/core-resources/elements/containers%23repeating-group\\&sa=D\\&source=editors\\&ust=1648861627993289\\&usg=AOvVaw3pxBPBMIFlC-6Oq0iWZ3VU) within that blog post. This allows for different blog structures as your users view the different blog posts. ### blogPost [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.ve12sdax6a9w) This will be your main data type. This will hold the majority of your data and will normally be displayed in a repeating group on your home page. Notice how we don’t pluralize the name here since each one will be a singular blog post. #### Suggested fields on this type \* title (text): This will be the title of your blog post. \* summary (text): This will be the summary of your article that will be displayed underneath the title \* byLine (text): The name of the person who wrote the article \* blogContentList (list of blogContents): This is a list of your blogContent data type (see below) \* visible (yes/no): This will allow you to turn posts on and off from being visible on your page #### Privacy rules for this data type We will assume that you want the Blog to be fully public so we will keep the data type public, similarly to the Basic example. ### blogContent [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.uppdxua4vj7p) This is your content for the blog post. It will hold the body and images of each post’s content. This allows for the flexibility of different structures in the blog content: this data type enables you to store each section of the post’s content as an individual blogContent, which then lets you display the different sections with different formatting. For example, perhaps you want one paragraph (which would be its own blogContent) to be formatted left-aligned, whereas you want the following paragraph (which would be another blogContent) to be formatted right-aligned for emphasis. If you wanted to make your blog even more flexible, you could build on top of this data type to store additional fields like “order” to set the order in which different chunks of content appear on the page, or “expiration” to set a time before/after which that particular chunk of content should appear. #### Suggested fields on this type \* parentBlogPost (blogPost): this is how each blogContent knows which blogPost it belongs to \* blogContentType (blogContentType): this is the option set that will help you distinguish which type of content this will be, an image, text of a certain styling, or something else (see below). Having this field allows you to customize how this chunk of blogContent shows up on the page - the page can display this thing differently depending on its blogContentType. \* text (text): this is where your body paragraphs will go. Each will be in its own blogContent \* image (image): this is where an image in your post can be stored #### Privacy rules for this data type We will assume that you want the Blog to be fully public so we will keep the data type public, similarly to the Basic example. ### blogLikes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.dhtm2bvjj21h) This data type is if you want to have users ‘like’ a post. We could save the list of ‘like’ing users as a list on each blogPost, but this list might be very large eventually and would slow down your app at scale. Hence, we’re creating it as a different data type. (\[Here\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) is a lot more background on this choice.) #### Suggested fields on this type \* parentBlogPost (blogPost): this stores which blogPost actually got the ‘like’ \* creator (User): this is who liked the post (built in already) #### Privacy rules for this data type This could have privacy rules on it to not share exactly which user(s) liked a post publicly. In this case, we may want to rely on privacy rules on the User data type - we always recommend having privacy rules on User, given it likely stores sensitive information like email addresses. At minimum, one such privacy rule could be when ‘This user is current user’, they can see their own data but their own data should not be public to anyone else. You only need to be publicly allowed to search this data type to get the count. ## Option sets recommended ### blogContentType [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.gri81lvslx9n) \* text \* imageSmall \* imageLarge \* textAlignLeft \* textAlignRight \* textAlignCentered This option set, used in our Scalable example, gives you the ability to describe what a particular section of blogContent is. In this example, this flexibility then allows you to align different section of a blogPost differently, or display an image in a large vs small format. You could add other options in this set if you want even more different ways for a chunk of content to appear. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md#h.jge3g9i9dho3) \* Do a Search for BlogPosts - This would help you display your main blogPosts on your home page when this query \[powers\](https://manual.bubble.io/core-resources/elements/containers#data-source-1) a repeating group. For a result in this list - each of which would be one cell of a repeating group - the user would likely be able to click on a link to be taken to that particular blogPost with all of its blogContent. \* Do a Search for BlogContent where parentBlogPost = Current Page’s blogPost - On a \[page that’s showing a particular blogPost\](https://manual.bubble.io/core-resources/elements/page-element), this query will pull up all the blogContents for that blogPost, which can then be displayed in a repeating group on the page. Since we are also saving the blogContent as a list on the blogPost, you can access it by saying Current page blogPost’s blogContentList as well. ## About the author: Jason K These are just two options for building a blog on Bubble. Setting up an app’s database structure can be very tricky for new developers, so we hope this helps. Need more help? Check us out at\[ \](https://www.google.com/url?q=http://www.nocodeminute.com\\&sa=D\\&source=editors\\&ust=1648861628000291\\&usg=AOvVaw3o7voroPjYZaumynAL3t2b)\[www.NoCodeMinute.com\](https://www.nocodeminute.com/) for one-on-one coaching and the eLearning Hub where you can find more video tutorials, lots of free content, and a blog like the example above. 😊 !\[\](/files/Z15anH1QAB3Gf5UYeemX) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md). # On-demand Apps \*By Zeroqode Team\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} The on-demand type app can be easily associated with startups like Uber, Instacart, BloomThat, etc. Overall, on-demand apps generally contain capabilities for ordering, delivery, and tracking functionality via a map. Customers can order something from the platform and wait for a courier to deliver the items from a restaurant, for instance. Think UberEats, as one example. The following guide will give some recommendations for data types and option sets when setting up the database of your on-demand app. The target Bubble app will allow users to have a platform where it is possible for restaurants to list their menu with different meals, and for customers to add menu items to a shipping cart and place orders. The drivers will pick the order and deliver it to the customer. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.8gkrwvp3rqds) The main data type is User, of course. Users are picking different Menu Items from a menu to add to their shopping cart in the form of Cart Items, then placing an Order in order to confirm the payment. Meals come from a specific Restaurant. After completing the payment and receiving the Order, the customers are able to leave a Review for the Restaurant they ordered food from. ### Restaurant [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.r8pfh9l7ttx) This data type contains all the details about a restaurant registered on the platform, ranging from its name to its location. It contains all the list of Menu Items the restaurant offers. As the platform begins running, this data type will also track the Orders that users make from this restaurant. #### Suggested fields on this type \* name (text): the name of the restaurant, as displayed in the app \* description (text): to store the restaurant description for customers \* approved (yes / no): to store whether or not the restaurant has been approved by the platform, in case you want to hide the un-approved ones \* location (geographic address): to store the geographic location of the restaurant so that it can be displayed on a map \* menu items (list of Menu Items): to store the list of all menu items that are available to buy from this restaurant \* orders (list of Orders): to store the list of orders related to this restaurant \* owner (User): to store the restaurant owner’s information; note this assumes that every restaurant owner is also a user on your platform, but we can show owners of restaurants different pages or information relative to users who are purely shoppers on the platform \* reviews (list of Reviews): to store the list of reviews related to this restaurant, so customers can see the feedback #### Privacy rules for this data type You can create privacy rules to allow only the restaurant’s owner to see certain fields on their restaurant. If the owner has a page to edit their restaurant’s information, you can also \[enable auto-binding\](https://manual.bubble.io/help-guides/working-with-data/protecting-data#defining-permissions) for the fields they’re allowed to edit. ### Menu Item [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.qfqrff9cswmp) This data type stores information about the individual item from a Restaurant’s menu, which can be added by a user to their cart. A Menu Item comes from a specific Restaurant, and for simplicity’s sake, we can implement logic at the workflow level (i.e. not shown in this guide) to make it so that all the Cart Items in a given cart must come from the same Restaurant. #### Suggested fields on this type: \* restaurant (Restaurant): to store the Restaurant that offers this menu item \* name (text): to store the name of this menu item, so it is possible to display it \* description (text): to store a description of this meal (optional, but may be handy) \* picture (image): to store a picture of this menu item \* price (number): to store the price of this meal #### Privacy rules for this data type All these fields are ones that aren’t particularly sensitive, so they would likely be visible to all users. However, one nice feature for Restaurant owners might be to enable autobinding for any fields on a Menu Item that is associated with their Restaurant. ### Cart Item [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.psazzm1f0n1x) This data type is used to add meals to the shopping cart. It stores the information such as the Menu Item (related to a Restaurant) being added to the cart, the total price, quantity, etc. All the Cart Items in a user’s cart will be added to an Order prior to payment. You can also think of a Cart Item like one line item in the user’s ultimate receipt for an order. #### Suggested fields on this type \* menu item (Menu Item): this is the item that the user adds to the cart; the user chooses which Menu Item, then the other fields below dictate the quantity they want of that item and the price that comes out to \* quantity (number): to store the quantity of the menu item added to the shopping cart \* total price (number): to store the total price of the chosen quantity of the Menu Item; storing this is useful in case the restaurant changes the price of the item in the future; if it’s stored here, the app will remember how much the item(s) cost at the time of purchase #### Privacy rules for this data type Since users’ shopping carts will be private to themselves, we would create privacy rules to only make any Cart Item findable in searches and all of its fields visible to the creator of the Cart Item. ### Order [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.ifzsnu5y5hg) This data type stores information about orders created on the platform. It contains information about the Cart Items that the user added to their cart, and we can assume that an Order is created during the (successful) checkout process. This data type also will store various information about how the payment works, including the fee the app will take and the amounts that will be paid out to the different parties of the transaction (the restaurant’s cut, driver’s cut, etc.). #### Suggested fields on this type \* cart items (list of Cart Items): to store the list of the cart items that are being purchased as part of this order \* restaurant (Restaurant): to save the Restaurant that the meal was ordered from \* delivery address (geographic location): to store the address this order should be delivered to \* courier (User): to store who will deliver this order; note that this means we assume all couriers on our platform will also be Users in the app \* order total price (number): to store the total price for this order \* app revenue (number): to store the platform's cut for each order transaction \* courier fee (number): to store the payment amount taken by the courier as their cut \* restaurant payout (number): to store the total payment amount received by the restaurant for the order \* current status (Status): to store the status of this order; this will be an option set of pre-determined options (see below) \* payment ID (text): if you’re using a platform like Stripe to manage payments, this field can store the unique ID of this payment \* order ID (text): to help all parties manage a particular order, it can be helpful for your app to generate a unique order ID for this order, which would be stored here #### Privacy rules for this data type Orders should only be visible (i.e. findable in searches) to the parties of the transaction - the Users who are either the ones placing the order, who are the couriers delivering the order, or who are the restaurant owners fulfilling the order. Moreover, sensitive fields like payment IDs and the various prices and payouts should have privacy rules set such that only the relevant party can see them. ### Review [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.zd1uotqt9yki) After the order is completed, users who placed the order can leave a Review. We’ll assume that Reviews are about a particular Restaurant. #### Suggested fields on this type \* reviewer (User): to store the User who is writing the review \* restaurant (Restaurant): clarifies which restaurant this review is about \* rating (number): we can use a 0 to 5 scale for ratings \* text (text): any free-form content the user wants to leave as part of the review #### Privacy rules for this data type Reviews for a Restaurant can generally be left public, i.e. they can be found by any User. For the privacy of those writing the reviews, you may want to specifically hide the reviewer field from the public. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.5raxf9srocgi) This data type contains information about the users on the platform. As we have seen above, there are different kinds of Users on our platform - customers, Restaurant owners and couriers. So for now, our User data type will have fields that relate to any of those three types of users; this means that more Users in the database are unlikely to have all the fields filled out, since they are unlikely to be a customer, Restaurant owner and a courier all at the same time. #### Suggested fields on this type \* first name (text): self-explanatory; it’s useful to save the user’s first name as its own field so you can easily do things like incorporate their first name into a confirmation email’s greeting \* last name (text): self-explanatory \* is admin (yes / no): it’s often useful to create a field on User to determine whether that user has special privileges with the platform; for example, this can be used to control whether the user can see an admin panel to help manage all orders (useful for your customer support team) \* address (geographic address): to store the address of the user so it can be pre-filled for future orders \* favorite restaurants (list of Restaurants): to store the list of restaurants a customer likes, if you want to build this feature into your platform \* cart (list of Cart Items): this is how we build a ‘shopping cart’ feature - this field stores the list of items added to the shopping cart by the customer, which can then be referenced when the user goes to checkout; after a successful checkout, you can clear this field on User so that they start from an empty cart on their next visit \* driver license number (text): to store the number of the driver’s license for courier users \* driver license picture (image): to store the photo of the driver’s license for courier users \* orders (list of Orders): to store the list of orders the customer made, as an order history \* owned restaurant (Restaurant): to store the Restaurant object in case the current user is a restaurant owner #### Privacy rules for this data type As with many apps, our User data type contains sensitive information that generally should not be available to the public, e.g. last name, address, driver license information, etc. Any such sensitive field should be hidden from view for anybody except the user themselves and perhaps any admin users on the platform. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.krr8nsqafyt) \### Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.orsksh8755l6) \* New \* Accepted \* Found a courier \* Picked up \* Delivered \* Canceled This option set is used to define the available statuses of an Order. As the order goes through different stages of its life-cycle, various workflows would advance the status of the Order as various updates happen. ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.jge3g9i9dho3) Let’s assume that our app, now called Eaty, has an admin page where a member of the platform’s team can see all orders: !\[\](/files/GJo8nLClbWX2kFJG2azI) The main repeating group on the page shows a query of all Orders by default, but note how the other horizontal tabs on the page would show a list of Orders with filters for different Statuses. For each Order on the page, we see various fields about the Order. ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.8zfpl9lbgo9s) After building the basic functionality of an on-demand app, you may want to consider more advanced features. For example, on-demand apps often benefit from a chat feature with the other parties in the order, push notifications to alert users about order status changes, and a live map to track the delivery. Moreover, you may want to create some mobile-optimized pages for those using the app on the go, such as your couriers. Luckily, all these features and more are possible with Bubble. ## About the author: Zeroqode [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md#h.pfe1wzms19f3) A good example of a ready-made on-demand Bubble app is the \[Eaty\](https://zeroqode.com/template/eaty---food-delivery-like-uber-eats-template-1525767038595x917710033754259500) template from \[Zeroqode\](https://zeroqode.com/). They have also built a great range of 🔌 \[Plugins\](https://zeroqode.com/plugins) to boost the development of your Bubble app, as well as 🎓 \[Lab\](https://lab.zeroqode.com/) courses to improve your Bubble skills. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md). # Directory & Listings Apps \*By Gaby Román, Co-Founder of Coaching No Code Apps\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Directory apps are typically designed as user-friendly databases that make it easy to find a specific listing or profile. For example, TripAdvisor is a directory of businesses that can be easily searched, where search results appear in a list or map format. Users can then select a business and view more details about it. The following data structure is recommended for applications where users are generating listings or profiles for other users to find. These listings or profiles can help users hire for services, purchase products, book reservations, network with others, etc. Typically, these listings or profiles can be reviewed and rated by other users. Popular examples of this type of app include: Yelp, Airbnb, TripAdvisor, Amazon’s product search, LinkedIn, etc. These suggested data types and option sets should help you build common functionality for directory apps in a way that keeps things scalable. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.8gkrwvp3rqds) These data types will allow users to create their own listings, categorize them, and upload images. The app’s front-end design would dynamically display this content in a single layout. Users would first search for listings with any relevant filters, select one from the results, and then view the full details of their selection. The layout would look the same for all listings, but the content would be different. Users can also create reviews of any listing they see. The listing or profile page would then display all related reviews with an aggregated score or star rating. Search is typically a core feature for an app like this, so the following types and option sets create powerful filtering flexibility. Users should be able to select multiple filters in different combinations to find the exact results they’re looking for. This is possible by relating listings to specific categories, aggregating their review ratings, and saving helpful properties like location, dates, statuses, etc. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.l2xv5sqk28qg) This is Bubble’s only built-in data type. Anyone who needs to be able to log into the app should have a User record. #### Suggested fields on this type \* First Name (text) \* Last Name (text) \* Favorite Listings (list of Listings): This is a \[relationship field\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) that links the User to a list of Listing records, which are organized under a separate “Listing” data type. \* Type (list of User Types, an option set): Users can be more than one type of user, which will help you create conditions and/or privacy rules around what data or features they have access to in the app. \* For example, a “Listing Owner” should have the ability to manage their own listings whereas “Consumers” can only search, view, and review listings. \* Airbnb has Hosts and Guests. While a user can technically be both, it’s important to know what kind of interaction they’re coming to the app for. Hosts have the ability to create listings, whereas Guests have the ability to book listings. Hosts can view payments received, whereas Guests can view payments made, etc. \* System Admins typically refer to you, the app builder, to create global access to all parts of the app. \* See how this field influences privacy rules for the Listings data type, below #### Privacy rules for this data type This type of application is structured to make Users and/or separate Listings easy to find, so there isn’t as big of a need to restrict this type. With that said, we do have a few minimum recommendations: only allowing the user to auto-bind on their own record and “view” their own sensitive field values. System admins may get these abilities as well. \* Current User is This User > all access \* Current User is not This User and Current User’s Type doesn’t include System Admin > find in searches, view all fields except sensitive fields (home address, emergency contact, etc.), no auto-binding \* Current User’s Type includes System Admin > all access ### Listing [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.bphdr04pkc1u) This is the heart of a directory app. Users will search all Listings, so make sure you include fields for any details that need to be displayed to the user or which can help filter search results. #### Suggested fields on this type \* Title (text) \* Description (text) \* Location (geographic address) \* Owner (User): While Bubble has a built-in “Creator” field for all data types, having a custom Owner field like this will allow you to change owners. If you make this a list of Users, then you can create multi-owner / multi-editor capabilities. \* Categories (list of Categories): This field will help any search functionality filter Listings by Category.‘ \* Featured (yes/no): This field can help you sort results by showing any Listings where “Features = yes” at the top of the list. \* Status (Listing Status, an option set) \* Average Rating (number): This value can be re-calculated every time a new review is created for the Listing. It will also help users filter their searches based on a rating minimum and/or sort by rating. #### Privacy rules for this data type Given that this is the heart of the application, you can create many rules around the type to specify access rights. Here are some suggested rules that allow Listing Owners to modify their own Listing, System Admins to access everything, and Users unrelated to the Listing to view but not edit it: \* Current User is This Listing’s Owner > find in searches, enable auto-binding on all fields except the “Status” and “Featured” fields since those are reserved for the System Admin to update. \* Current User’s Type is System Admin > all access \* Current User is not This Listing’s Owner and This Listing’s Status is Published > find in searches and view all fields ### Review [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.k6yhjop6celf) Reviews are common in directory apps to help users find the most popular entities by seeing how other Users have rated them. #### Suggested fields on this type \* Related Listing (Listing): This field ties the Review back to the Listing it’s about. \* Rating (number): Whether review ratings are on a specific scale or not (e.g. 0-5 stars), saving any kind of number to each review will allow you to calculate Listing Review averages by aggregating on this field. \* Comment (text) \* Images (list of images): If it makes sense to allow consumers to upload images alongside their review (think Amazon product reviews), then this field will support that. #### Privacy rules for this data type Reviews should only be modified by the user who created it. This also applies to the System Admin to maintain integrity: \* Current User is This Review’s Creator > all access \* Everyone Else (Default Rule) > find in searches, view all fields, no auto-binding ### Image [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.7ft6ipmyzj1w) Depending on how important images are for your directory app’s Listings, you may want to store any related images in a separate data type. For example, Airbnb listings contain many images for the accommodation, and organizing those in a separate data type allows you to save separate captions per image or indicate which ones should be the featured image; as opposed to an internal company staff directory where the only image might be the person’s headshot which can be saved directly to the Listing itself. #### Suggested fields on this type \* Related Listing (Listing): This field ties the Image back to the Listing. \* File (image): This is the uploaded image itself. We’ve labeled it “File” so that your expressions can read “Image’s File” even though technically the field type is an image and not a file. \* Caption (text) \* Featured (yes/no) #### Privacy rules for this data type Images should follow nearly the same set of rules as their parent listing to allow creators to manage them only: \* Current User is This Image’s Creator > all access \* Everyone Else (Default Rule) > find in searches, view all fields, no auto-binding ### Category [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.n09tgl272zhf) If your users should be allowed to create categories or you plan on having dozens or even hundreds of categories, use a separate data type to organize them. Otherwise, if your app’s category list is more contained and users can’t create new ones, then an option set might be more convenient. #### Suggested fields on this type \* Name (text) \* Parent Category (Category): This field will help you create an infinite hierarchy of categories and sub-categories. Any Category without a parent will tell you that’s the top of its hierarchy. Any Category with a parent will tell you it’s a sub-category of another Category. #### Privacy rules for this data type The privacy rules here can vary depending on how much control you want your users to have over them. Let’s assume that while users can generate categories, they can only modify their own. Some of the logic around editing conditions may need to be set up within the workflows and element design. For example, users can only edit if there are no listings attached to their category. \* Current User is This Category’s creator > all access \* Everyone Else (Default Rule) > find in searches, view all fields, no auto-binding If the System Admin is the only person who should be able to edit Categories, then these rules are more appropriate: \* Current User’s Type includes System Admin > all access \* Everyone Else (Default Rule) > find in searches, view all fields, no auto-binding ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.krr8nsqafyt) \### Listing Status [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.lyakjb4uw0gg) \* Draft \* Under Review \* Published \* Archived Many directory or listings applications will have content creators (in this case, listing owners) create the entity as a draft first and then submit it to the platform for review. If accepted, the platform will change the status to Published so that only Listings where “Status = Published” appear in search results. ### User Type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.7by0x6goyq61) \* System Admin \* Listing Owner \* Consumer If your application has different types of users where access to data, pages, even workflows are specific to that type, an option set is a great way to identify who the users are. By making the “Type” field under the User data type a list, Users can be more than one Type (if necessary). ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.jge3g9i9dho3) \* Search for Listings within 10 miles of a selected location \* If this app is meant to connect a user with home renovation professionals, then they may want to do a search with a location constraint (and sort by best rated). \* The following expression can generate the appropriate listings in a repeating group: \* Search for Listings (Status = Published; Location is within radius input’s value of location input’s value; Categories includes category dropdown’s value; sorted by Average Rating) \* Search for Listings that are at least 4 stars or above and are the newest in the system \* Search for Listings (Status = Published; Average Rating >= 4; sorted by Creation Date) ## Additional notes [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.8zfpl9lbgo9s) Keep in mind that your directory app will have customizations not covered here. Whenever you need to store a unique combination of values, consider creating a new data type. For example, the Review data type is the unique combination of a User (consumer), a Listing, and the User’s rating for that Listing. You might also notice that we don’t have very many list fields to create one to many relationships. We recommend using list fields when the number of items in the list is going to be relatively small. For example, a Listing may have up to 5 Categories whereas it could have hundreds of Reviews. So, for better performance, we chose not to have a list of Reviews under the Listing data type. Instead, as long as the Review has a “Related Listing” field, we have everything we need to find that Listing’s Reviews. ## About this author: Coaching No Code Apps [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md#h.yekgzloqmodg) Your database structure creates the entire foundation for your app as a whole, and because of its importance, it's one of the first things we focus on with our own clients before moving onto broader functionality. For help putting all the right pieces into place and creating a scalable app using Bubble, join a free workshop focused on scoping, building, and launching your no code app at . --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md). # Professional Services Apps \*By Chris Strobl, Founder & Co-CEO of No Code Germany\* {% hint style="info" %} \*Various members of the Bubble ecosystem contributed these use case-oriented database guides. There's always more than one way to do something in Bubble, but the advice here can help you get started if you're new to Bubble!\* {% endhint %} Professional services experts spend 80% of their time on back-office tasks. The digitization of business processes around project- and client management, forms & templates, invoicing, scheduling, automation and reporting allows professional services experts to focus on revenue and profitability. This guide suggests a database setup for an application for professional services firms that handles basic booking and invoice needs. In detail, this app helps manage the lifecycle of an engagement and lets users manage projects, book clients, sign contracts online, send invoices and handle payments. ## Data types recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.8gkrwvp3rqds) A Project represents some unit of work for the professional services firm. Projects are related to Clients that the firm has. The first step in a Project is usually receiving an Inquiry. ### User [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.gwag42rje0qz) Every Bubble app comes with the concept of a User. In this case, we assume that the tool is mostly going to be used by employees of the professional services firm, meaning the app is an internal tool for the firm. #### Suggested fields on this type \* Name (text): the name of the person \* Admin (yes/no): whether this person is an admin of the tool #### Privacy rules for this data type Since this is an internal tool, in general for all data types, you will want to create a privacy rule so that only users who are logged in can find any data in searches or view any of the fields. This way, nobody external to the company who doesn’t have an account with the tool will be able to see the data. Since this is an internal tool, the app should not have a publicly accessible signup page; instead, for any new employee who needs access to this system, you can manually create an account for them via the App Data tab of the editor. ### Project [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.hhati0erkxkv) Whether it is the design of an advertising campaign, the development of an app or the implementation of a consulting project, the core activity of a professional service firm is the implementation of projects. #### Suggested fields on this type \* Project name (text): the name of the project \* Hourly rate (number): pricing for invoices \* Client (Client): which Client this project relates to; see \[documentation\](https://manual.bubble.io/help-guides/structuring-an-application/data-structure#connecting-types) on connecting data types \* Inquiry (Inquiry): the original Inquiry that this project came from \* Project stage (project\\\_stage): the status of this project, out of a set of options #### Privacy rules for this data type As noted above, you will want a privacy rule to only allow logged in users to find this data type and view its fields. If one of the fields is particularly sensitive (like hourly rate), you could consider creating another privacy rule to only show that to users who have the ‘admin’ field set to ‘yes’. ### Inquiry [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.ci1hwibje4ld) Prior to starting a project, the client submits an Inquiry via an online form that governs the specifications of the project. #### Suggested fields on this type \* Project description (text): you can use a “multiline input” element to give the prospect more space to describe their business problem \* Project type (project\\\_type): one out of a set of options to consider (see below) \* Target budget (number): useful information for you to know as you assess whether to take the project \* Inquiry date (date): information on when the Inquiry was submitted. #### Privacy rules for this data type As noted above, you will want a privacy rule to only allow logged in users to find this data type and view its fields. ### Client [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.jopphd9ft40x) Master data about the client is the foundation for a good customer relationship. You can keep building out new features in this app to eventually turn it into a CRM! #### Suggested fields on this type \* First name (text) \* Last name (text) \* Email (text): note that Bubble’s database does not automatically enforce uniqueness (i.e. nothing is stopping the app from having two Clients with the same email, yet), but you can implement uniqueness through workflow logic \* Company name (text) \* Number of employees (number): To get a feeling about the budget and service level \* Phone number (text): because this is just stored as text, you may want to do some data sanitization and even validation in the workflows that save this field \* Billing address (text) #### Privacy rules for this data type As noted above, you will want a privacy rule to only allow logged in users to find this data type and view its fields. If any of the fields are particularly sensitive, you could consider creating another privacy rule to only show those to users who have the ‘admin’ field set to ‘yes’. ## Option sets recommended [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.krr8nsqafyt) \### Project\\\_stage [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.bbr1o471gs5r) The client relationship can be divided into different stages. This is especially relevant to keep track of activities such as invoicing. The methodology of each Professional Services firm guides the customer along the Project Stages. \* Inquiry \* Qualification \* Proposal sent \* Contract signed \* Project Kick-Off \* Project Delivery \* Project Hand-over \* Invoice sent ### Project\\\_type [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.d60qs1nncrjc) An option set for project type helps to organize the portfolio of work of a professional services firm. \* Marketplace \* Social Network \* Productivity Tool \* CRM System \* Analytics Tool \* Something Else ## Example uses in your app [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.jge3g9i9dho3) You will likely have a page (for logged-in users) that shows all current active projects. This page would have a repeating group with a data source that’s a search for all Projects where the project\\\_stage is or isn’t certain stages that you do or don’t want to consider “active”. With such a list, you may also want to build the capability to filter by certain project\\\_stages or project\\\_types. If you have dropdowns for these, you can update the repeating group’s data source to include a new filter on project\\\_stage or project\\\_type depending on the value of those dropdowns. ## About the author: Chris Strobl [](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md#h.8zfpl9lbgo9s) I’m \[Chris Strobl\](https://www.linkedin.com/in/chris-strobl/), Founder and Co-CEO of my own company \[No-Code Germany\](https://www.nocodegermany.com/). We have a free Youtube channel for Bubble tutorials and provide IT consulting. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/web-app/containers.md). # Containers {% hint style="info" %} This section takes a long-form look at what containers are and how you can use them in different situations.\\ \\ To see the full list of settings available on container elements, you can check out our more concise \[core reference entry on containers\](/core-resources/elements/containers.md). {% endhint %} ![](https://manual.bubble.io/files/giLHZKHIX1Q5PwaPNapE) Containers can hold elements like the form in the example above. Here we're using a [_group_](https://manual.bubble.io/pages/0InSA6TX3K40sT0u4F83) element. All elements\[^1\] on your page are part of a hierarchy with the page as the top parent. Containers are used to contain elements and control how they behave on the page. You can place elements inside of a container, making it the parent and the element(s) its children. The \[element tree\](#user-content-fn-2)\[^2\] will display the hierarchy of the parent-child relationship. Bubble has six container types that behave in different ways. Knowing how the different types behave is the key to mastering design in Bubble, so we recommend spending some time getting to know their behavior. Click on each container type for more information and a link to the full article: Groups – placed directly on the page to build the page hierarchy Groups are the most basic container type and can be placed directly on the page to build a hierarchy of parent-child relationships. They are used to contain elements, control responsive behavior, navigation and to hold data. Article: \[Groups\](/help-guides/design/elements/web-app/containers/groups.md) Repeating groups – used to display lists of things in a flexible design Repeating groups are similar to groups, but will repeat its content once for each item in a list of things such as database records. Repeating groups are used to display lists such as (but not limited to) a list of users, a search result, product cards and photo masonry grids. A repeating group allows you to design lists in a flexible way, and the table element (below) lets you set up a more structured table with fixed row/column headers.\\ \\ Article: \[Repeating Groups\](/help-guides/design/elements/web-app/containers/repeating-groups.md) Table element - used to display a list of things in neat rows and columns Table elements are similar to repeating groups in that it shows a list of things, but unlike the repeating group container a table can have fixed row/column headers and is useful for setting up more strict table-like structures. Article:\[ The Table element\](/help-guides/design/elements/web-app/containers/table-elements.md) Popups – display a group above all other elements (i.e. a message or signup form) The \*Popup\* group type is a a group that is displayed above all other elements and is centered on the screen regardless of the scrolling position of the page. They can be set up to hide or blur the page below. As such, they are a useful way to bring an important message or forms to the user's attention immediately. Article: \[Popups\](/help-guides/design/elements/web-app/containers/popups.md) Floating groups – hovers above page attached to a screen edge (i.e. navigation bar) Floating Groups are a group type that can be set up to hover above other elements on the page and they can be attached to any side of the screen and stay there regardless of whether the user scrolls up and down. Article: \[Floating Groups\](/help-guides/design/elements/web-app/containers/floating-groups.md) Group focus – remains visible as long as it's in focus (i.e. dropdown menu) The Group Focus has two main characteristics: \* It will remain visible only for as long as it is in focus. \*Focus\* in this context means until you click anywhere else on the page. \* They are displayed relative to another element by a set number of pixels This makes the Group Focus very useful for things like dropdown menus, contextual menus and tooltips. Article: \[Group Focus\](/help-guides/design/elements/web-app/containers/group-focus.md) \## Styling containers Containers can be set to be invisible, but they can also have a background style, roundness, borders and shadows, just like other elements. ![](https://manual.bubble.io/files/HnLIXBVtNQiXXzJzMhAX) Groups can be invisible, like on the left, or they can be styled. The right group has a white background color, rounded corners and a shadow. You access a group's styling settings by double-clicking it or by clicking on it in the element tree. ## Loading data into containers Containers are not just visual elements; they can also be used to hold different kinds of data. For example, if you are working on a form that lets you edit a user (with input fields for name, phone number and address), you can set the containers data source to \*User\* and load the user data into the container. The data loaded into the container is then made available to all of its child elements. This allows you to load specific data into parts of a page, such as in the example below where we are loading the data about a user into the container: ![](https://manual.bubble.io/files/O74DbiaJnTbI9sZNATEx) You can load data into a group to easily reference it in other elements and workflows. \### Referencing data in elements In the example above, we have loaded the current user into the container, and it lets us easily reference the user in the \[input elements\](#user-content-fn-3)\[^3\] in the form: ![](https://manual.bubble.io/files/CYmBttqQaLie77brhv3W) By loading data into a group we can reference that data in the group's child elements. In the example above we're loading the user's name into an input field. In the illustration above, the container is loading the current user, and we can use that information in the container's child elements. In the screenshot, we're looking at the settings for the input field. We're referencing the \*Parent groups's User's name\*. ### Referencing data in workflows The same can be done with workflows\[^4\]. In the example below, we want the \*Save changes\* button to save the data from the input fields to the database. By referencing the parent group's user, we can save it easily: ![](https://manual.bubble.io/files/9eUCB8Ihzwq8lW633MRk) If an element like a button is placed within a group that holds data, we can reference that data in workflows connected to that element. In the example above we're referencing the user loaded into the parent group of the button. {% hint style="info" %} Referencing the parent group's data in a workflow requires that the event that triggers the workflow is connected to one of the container's child elements. For example, a Save button inside of the container could trigger a workflow that saves changes from the form. {% endhint %} Referencing data in elements and workflows can be done on all group types, including the cells\[^5\] of a \[Repeating Group\](#user-content-fn-6)\[^6\]. ### Different ways of loading data There are two different ways to load data into a container: \* You can set the \*Data source\* of the container to load data. In the example above we are loading the \*Current user\*, but you can also fetch it in other ways, such as performing a database search using \*Do a search for.\* ![](https://manual.bubble.io/files/EngPjAIjzuQwO3xuS10Y) Setting the _Type of content_ to User and the _Data source_ to Current user instructs Bubble to load the data about the current user into the container \* You can use a workflow to push data to the container. This is useful when you want the loading of data to be the result of a user action. ![](https://manual.bubble.io/files/1VOSuCPgVUH67AV9K9b4) In this example we are using the _Display data in group/popup_ action to search for a user and load its data into the group. We'll then be able to reference the loaded user in elements and workflows contained within the group. The first method will load the data as soon as the page is loaded, while the second will await a trigger to execute the workflow. You could also use the latter method to allow the user to select which user they want to edit. ## Resetting a container You can reset a container to wipe the thing that is displayed in it. When you use a reset group action, the thing will be reverted to what was defined as the datasource. This is useful to note since reset doesn't mean \*empty\* – it means reset to its initial state. ![](https://manual.bubble.io/files/DSpwWnFmt3icgrusg3BA) Whenever you change the content of a container, it's effectively being reset and displaying the new thing. This means that all child elements (such as input fields containing text) will update their content to reflect the data being loaded into its parent container. Note that whenever the content of a group changes, the group effectively is being reset and a new thing is being displayed in it. ## Groups and responsive settings You can use groups to control the responsive behavior of the elements inside of it. For example, if you have three input fields that you want to never be more than 200 pixels wide, you can set the maximum width on the group that holds them. That way, the max width are applied to all of the elements and you don't need to apply it one by one. {% hint style="info" %} You can read more about responsive design in our Responsive design article series.\\ \\ Article series: \[Responsive design\](/help-guides/design/responsive-design.md) {% endhint %} Using groups to control responsive behavior is the key to efficiently set up a responsive design. ![](https://manual.bubble.io/files/qEwwfuEXIqVSrVxJMPI4) In this example, we have set the max width of the group to be 480 pixels. This way, we also control the width of the elements inside of that group. \[^1\]: Elements is the umbrella term for all the things you can place on a Bubble page such as text, buttons, images and groups.\\ \\ Article: \[Elements\](/help-guides/design/elements.md) \[^2\]: The \*element tree\* is the list of elements organized in a hierarchy that you can see on the left side of the Bubble design editor.\\ \\ Article: \[The element tree\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-element-tree.md) \[^3\]: Input elements are elements that accept some sort of data from the user, such as a string of text or a number.\\ \\ Article: \[Input forms\](/help-guides/design/elements/web-app/input-forms.md) \[^4\]: Workflows are the engine of your application – they are how you instruct Bubble to respond to what the user does, such as clicking a button, with a set of actions that can do anything from hiding/showing or animating things on the page to making changes in the database and make external API calls. A \*workflow\* is the combination of an \*event\* that triggers one or more \*actions\*. Article series: \[Workflows\](/help-guides/logic/workflows.md) \[^5\]: In a Repeating Group, each record displayed in the list is known as a \*cell.\* \[^6\]: A Repeating Group is a container type that lets you repeat the content of a group once for each record in a list of data.\\ \\ Article: \[Repeating Groups\](/help-guides/design/elements/web-app/containers/repeating-groups.md) Reference: \[Repeating Groups\](/core-resources/elements/containers.md#repeating-group) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/web-app/containers.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology.md). # Bubble API terminology As we've seen in the articles so far in our \[Introduction to APIs series\](/help-guides/integrations/api/introduction-to-apis.md), working with APIs you come across a comprehensive terminology that was not invented by Bubble but has been around for years or decades. You can find a list of some these in our \[API Glossary\](/help-guides/integrations/api/api-glossary.md). Bubble also introduces its own terminology to describe different parts of its API. To new users they may seem confusing and sometimes overlapping at first and this article will go in-depth in the different terms we use. ## Quick reference | | | | --- | --- | | Bubble API | Umbrella term for the Data API and Workflow API | | Data API | The part of the Bubble API that deals with direct requests to the database | | Workflow API | The part of the Bubble API that deals with requests to trigger API workflows | | API Workflow | The workflow itself that you create and manage in the backend editor | | Backend workflow | Umbrella term for the different workflows available in the backend editor (API Workflow, Database Trigger, Recurring event and Custom event) | \## What is the Bubble API? The term Bubble API describes the full suite of API capabilities that Bubble can offer to other applications. In other words, any \*\*incoming\*\* connection to your application is connecting to the Bubble API. ![](https://manual.bubble.io/files/6Mvuf6sp0utup7X0HYxX) Whenever a call reaches the Bubble API it is routed to the Workflow API or the Data API depending on the instructions in the request You can see the Bubble API as an umbrella term for the Data API and Workflow API. ### Why is the API Connector not considered a part of the Bubble API? The API Connector, which is used to establish \*\*outgoing\*\* connections to other applications is as such not a part of the Bubble API. We can illustrate the reason for this with an example moving outside of Bubble: Let's say you are initiating a connection with a Weather API to get updated weather information. That Weather API service may also use one or more APIs in order to function: for example, it could be using the Google Maps API to convert an address into map coordinates. That information, while it helps them deliver a better service, is completely irrelevant to you. As such, it's not a part of their API – it would not be presented in their API documentation and you would never know that it was involved in responding to your request. The same is true for Bubble whenever there's an incoming request: whether your app uses the API Connector to connect to other parties in order to complete a request is irrelevant to the third-party making the request. They simply want to connect to the Bubble API to get a response and what goes on behind the scene is hidden from them. ## What is the Data API? ![](https://manual.bubble.io/files/sEj6IHjuMpz30kKejPdg) The Data API is the part of the Bubble API that deals with direct access to the database. This allows a third party to send commands directly to your app's database and get a response it can recognize in return. If you open up for it, this lets an external application: \* Search for and read records in your database \* Create new records \* Make changes to records \* Delete records Of course this all doesn't happen unrestricted: as we'll see in later sections you have full control over what information and commands they have access to. ### How are these database operations different from workflows? In Bubble's terminology, a \*workflow\* is the combination of an \*event\* and a set of \*actions\* that should be run as a result of that event. That techie-sounding description is what happens whenever you design something in the workflow editor: ![](https://manual.bubble.io/files/7j9vCqLD7cpAOJ1L7qn9) A workflow can perform any set of Bubble actions. In the example above we're making changes to a User, creating a new database Thing and then sending an email. \### If the Workflow API can make changes in the database, why do I need the Data API? There are several reasons for why direct access to the database makes sense to use in most cases where you are working with data: #### It's already set up The Data API is set up to respond to different queries in a format that other APIs will recognize. It has built-in: \* Search for single records and get its data \* Search for records by criteria and get their data in a paginated format \* Create new Things \* Bulk create new Things \* Delete Things \* Change Things All of this is possible without spending any time setting up a single workflow. #### It's secure The Data API gives you granular control over the security of your database: \* By requiring \[\*\*authentication\*\*\](#user-content-fn-1)\[^1\] you can determine which client\[^2\] is making the query, to... \* \[\*\*authorize\*\*\](#user-content-fn-3)\[^3\] that client to perform certain actions \* Find Things \* Hide and show specific fields \* Create Things \* Modify Things \* Delete Things Since this is all controlled in one central place – your app's Privacy Rules – you can apply restrictions to a wide set of clients and circumstances in one central dashboard. ![](https://manual.bubble.io/files/OfWflLziZoHBQFlDX4wP) Using Privacy Rules you have a high level of control over the actions that a client accessing your database can make. \### When should I use the Data API? Whenever you want to give a specific app flexible access to your database. Let's go over a few examples to say when the Data API would be the more practical and secure API method: \*\*Case 1: Customer signup to lead\*\* Let's say you have built a CRM for your company in Bubble, but your website is in a different framework such as Wordpress. Each time a potential client signs up using the contact form on your website, you would like to create a lead in your CRM. By setting up Wordpress to send an API request to the Bubble Data API, you can create a new lead in the Bubble database using the \[Create a Thing Data API request\](/core-resources/api/the-bubble-api/the-data-api/data-api-requests.md#create-a-thing). \*\*Case 2: Project hours info to invoice\*\* This time, let's imagine you have built a project management in Bubble, but the invoices are handled by a separate accounting app. By opening up your database to that accounting app they can get an up-to-date list of work hour logs whenever they need to generate an invoice. In short, whenever you need to read or update information in the database and all the parameters needed are available when the request is sent, the Data API is usually the better choice. ## What is the Workflow API? ![](https://manual.bubble.io/files/grf6WHkJyDOQepfgt85T) As we explored in our last definition, the Workflow API allows external applications to trigger an \[\*\*API workflow\*\*\](#user-content-fn-4)\[^4\] in your app by \[sending a request\](#user-content-fn-5)\[^5\]. A workflow can perform any set of actions that you need to perform. Let's re-visit our example from earlier: ![](https://manual.bubble.io/files/7j9vCqLD7cpAOJ1L7qn9) Anything built in the workflow editor is known simply as a workflow - hence the name Workflow API In contrast to the Data API, the Workflow API can perform all sorts of actions with or without involving the database. Just like with workflows on your pages, you can set up a sequence of steps, each with unique conditions to determine whether to execute or not. You can see the Workflow API in the same way as a user visiting a page in your app: they can click a button (make a request) that instructs your app to perform one or more actions that are run in sequence. ### If the Data API can make changes in the database, why do I need the Workflow API? While workflows \*can\* perform database operations, a database operation is not necessarily performed by a workflow. There are many reasons for choosing the Workflow API over the Data API: #### It can perform actions not related to the database API Workflows can run any kind of \[server-side actions\](#user-content-fn-6)\[^6\] that Bubble (including plugins) can offer, such as sending emails, resetting passwords, submitting API calls and lots more. #### It can perform a sequence of actions Workflows often consist of more than one action that can be run in sequence, and each step can if needed rely on a previous step. The Data API will simply perform the requested action and respond with a preset response whereas the Workflow API gives full flexibility as to what kind of unlimited number actions you want to take. A Workflow can also trigger other workflows in your app. #### It can return a customized response The Data API sends a response back in a format that's recognized by many other systems, but if you need to customize what the response to a call looks like, you can use the Workflow API to set it up. ### When should I use the Workflow API? In short, whenever you need more flexibility in how data is manipulated, or when you need the API call to lead to executing actions that are not related to the database. \*\*Case 1: Follow-up steps\*\* Even when making changes in the database \*is\* what you're looking for, the Workflow API can be the right choice. For instance, an app may need to: \* Create a new Thing \* Count all Things of the same type \* Send an email to an address specified in the request with the total count In this case we are working with the database, but since we also want to perform a few specific actions that rely on the first step it would make sense to set this one up in the Workflow API. It might look something like this: ![](https://manual.bubble.io/files/F4AJ33Rbc4KpnHVrJo5f) While you could use the Data API to Create the Thing, any subsequent action would need to be set up in an API Workflow. \*\*Case 2: Using complex conditions\*\* In scenarios where you rely on conditions\[^7\] in order to determine whether an action should be performed the Workflow API also comes in handy. Let's say your app needs to: \* Create a new Thing \* But \*only\* if today is a Friday and a maximum of 3 Things have been created today A condition like that would involve checking the current day of the week and count the number of Things created today – this complex condition wouldn't be possible to set up in Privacy Rules and would need an API Workflow where you could place the condition in the \*Only when\* field. ![](https://manual.bubble.io/files/JNJqI36JxTeSEDeR2jv4) If creating this new Thing relies on a condition like the above, you can move from the Data API to the Workflow API to get the desired result. We could provide a lot of different examples, but the important point is that the Data API is used only to read/manipulate data and send a preformatted response, and the Workflow API is used to trigger a workflow that can be set up to run any actions you want. ### Why is it sometimes called Workflow API and other times API Workflow? While these two terms are indeed closely related, they mean different things. The \*\*Workflow API\*\* is the part of the Bubble API that handles workflows. ![](https://manual.bubble.io/files/gAaA4j77zmswJ0rFNj58) The Workflow API is the umbrella term for the part of the Bubble API that handles API Workflows. An \*\*API Workflow\*\* is the workflow itself that you set up in the backend workflow editor. As such the Workflow API consists of API Workflows, and API Workflows are part of Bubble's Workflow API. ## The backend workflow editor Bubble's \[backend workflow editor\](#user-content-fn-8)\[^8\] is the section of the Bubble editor where you create and manage backend workflows. ### What's the difference between backend workflows and API workflows? Backend workflows is the umbrella term for any type of workflow you can create in the backend editor. ![](https://manual.bubble.io/files/hgGJnLjP37RLVPwMvbat) Backend workflows offer four different kinds of events. API Workflows belong to the Workflow API while the rest are internal tools that serve other purposes. What they all have in common is that they run server-side. These are server-side workflows, meaning that they can run on the Bubble server without anyone visiting one of your app's pages. This includes, but is not limited to, API Workflows. ![](https://manual.bubble.io/files/AnGer68p0EXKBVqZqL9R) _Backend workflows_ is the umbrella term for the workflows you add in Bubble's backend editor. API Workflows is one of them. \[^1\]: Authentication is the process of determining \*\*who\*\* a client is in order to determine what resources they should be given access to. \[^2\]: The \*client\* is the one making an API call, as opposed to the \*server\*, who is the one to receive it and respond.\\ \\ Article section: \[The client/server relationship\](/help-guides/integrations/api/introduction-to-apis.md#client-and-server) \[^3\]: \*Authorization\* is the process of determining \*\*what\*\* resources a client has access to after they have been authenticated. \[^4\]: An API Workflow is a special kind of workflow that you find in Bubble's backend workflow editor.\\ \\ Article: \[API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md) \[^5\]: Sending a request in this context means that an external app is sending an API call to your app in order to perform some kind of action and get a response. \[^6\]: Server-side actions in this context means actions that can be completed on Bubble's server, as opposed to client-side workflows that are used to perform actions related to a Bubble page. \[^7\]: Conditions in the context of a workflow means that you can set up rules that govern whether a workflow or action is to run or not. Bubble will check this rule every time your app attempts to run it. \[^8\]: You can read more about accessing the backend workflow editor in the link below:\\ \\ Article section: \[Accessing the backend workflow editor\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md#accessing-the-backend-workflow-editor) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/creating-saving-and-deleting-data.md). # Creating, saving and deleting data Bubble comes with a range of different ways to work with the data in the database to: \* Create new things\[^1\] \* Make changes to existing things \* Deleting things Manipulating data in the database is done in three different ways: \* You can set up \[\*\*workflows\*\*\](#user-content-fn-2)\[^2\] that trigger on specific events, such as the user clicking a \*Save changes\* button \* You can use \[\*\*auto-binding\*\*\](#user-content-fn-3)\[^3\] to save changes in the database every time the user provides some input to an \[input field\](#user-content-fn-4)\[^4\] \* You can edit data directly in the database using the \[\*\*database editor\*\*\](#user-content-fn-5)\[^5\]\*\*.\*\* This option is only available to users who have that access in the Bubble editor ## Workflows A workflow is a collection of actions that run in sequence whenever an \*event\* happens. You can choose between many different types of events, such as a button click, an input field being updated or when a specific condition is true. ![](https://manual.bubble.io/files/hSA6ohISkg2sxudIaUFe) \### Actions There are few different actions that make changes to the database. You can click the links below to see the core reference entry for that action: \* \[Create a new thing\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#create-a-new-thing...): creates a new record of a specific data type and optionally saves information in the fields of that data type \* \[Make changes to a thing\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#make-changes-to-thing...): saves new information to a thing, replacing whatever was in the field before \* \[Make changes to a list of things\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#make-changes-to-a-list-of-things...): same as above, but works on multiple things at once. \* \[Make changes to the current user\](/core-resources/actions/account.md#make-changes-to-current-user): the same as above, but works directly on the user that started the workflow \* \[Delete a thing\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#delete-thing...): deletes a thing from the database \* \[Delete a list of things\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#delete-a-list-of-things...): same as above, but for multiple records \* \[Copy a list of things\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTujs88N9W-2FUmQGag#delete-a-list-of-things...): creates an identical copy of a list of existing thing with a new unique ID and updated \*Created date\* and \*Modified date\* fields. You can copy up to 50 things in one operation. By combining these actions in various ways, you can work with new and existing data in a flexible manner, and even include additional actions that are related or unrelated to the database. ### Example Let's say you have set up a form that lets a user edit their own profile. In that case we would have some different input fields that let the user provide information. We could then have a button that triggers the workflow: ![](https://manual.bubble.io/files/GOqtYH5xMz7y4HAfa4ZE) In this example, we have a list of input fields where the user can provide some information and then click the button element to save those changes. Click the image to see a bigger version. The setup above would mean that no changes are saved to the database until the user actually clicks the button. {% hint style="warning" %} Note that some information, like email and password, has to be changed using a different action from the \*Make changes to thing.\* Because of the sensitive nature of user credentials, it's necessary to handle them differently to ensure their security and protect user privacy.\\ \\ Article: \[User accounts\](/help-guides/data/user-accounts.md) {% endhint %} ![](https://manual.bubble.io/files/35pVl4tBLsEOBLFHZ4oc) Here we are combining the _An element is clicked_ event to trigger the _Make changes to the current user_ action. Together these two steps make up the workflow. Using workflows let you set up additional actions after the first one to perform other relevant tasks. For example, we could use the \[\*Alert\* element\](#user-content-fn-6)\[^6\] to display a message that the operation was successful: ![](https://manual.bubble.io/files/xJAXyyFvAI1pnp9N6drY) In this example we're setting up an additional step to show a message to our users that the changes have been saved. Note that there needs to be an _Alert_ element on the page for this action to become available. As we can see in this example, workflows are useful when you want the user to be able to decide \*when\* to save the changes, and if you need to chain more than one action in the workflow. ## Auto-binding Auto-binding means to bind an input element to a specific field on a data type. When this is set up, Bubble will automatically save any changes made in that element to the database. This means that you don't need to set up any actions to make the changes. Auto-binding is connected to a field, meaning that the data format of the input element and the data field must match: for example, a field containing a date must be connected to an input element that expects a date from the user. Also, auto-binding will only work if the parent of the input element has a \[data type loaded into it\](#user-content-fn-7)\[^7\] and it cannot create new things: only write to things that already exists. ![](https://manual.bubble.io/files/YefuT3NtxdWUz5yQAXYa) Auto-binding is set up in the element property inspector. By checking the _Enable auto-binding on parent element's thing_ you can select what field to modify and optionally to show an alert each time the operation is succssful. In the example above we have set up a \[text input element\](#user-content-fn-8)\[^8\] that automatically saves the input to the field \*Name\* on the user. The user is \[loaded into the parent\](#user-content-fn-7)\[^7\], which either a \[container element\](#user-content-fn-9)\[^9\] or \[the page\](#user-content-fn-10)\[^10\] itself. The data is saved whenever the element loses focus, meaning that the user has clicked or tabbed away from the input field. Bubble will display the loading bar for a brief time to show the user that the data is being saved. {% hint style="warning" %} \*\*Note:\*\* Auto-binding on an input will run immediately, rather than waiting for the "next step" when using the step-by-step feature in the debugger. {% endhint %} Video lessons \* \[Instantly modify data with auto-binding\](https://youtu.be/MamNYJmZjVY) \### Showing an alert on success When auto-binding is active you can show an alert to notify the user that it was successful. To use this feature, you need to first place an alert element on the page. Checking the \*Show an alert on success\* lets you select which Alert element to use and what message to show. ![](https://manual.bubble.io/files/7GiuhVHoWgopDEkrCSvP) In the screenshot above you see we have created an alert element and checked the \*Position the alert at the top\* box to make sure it's displayed as a full-width bar at the top of the page. ![](https://manual.bubble.io/files/xnJv8EvqsPljGSJGZC0q) On the input that has auto-binding activated we pick the alert element we just created. We also created a custom alert message that coincides with the field that was changed. ## Comparing workflows and auto-binding There are some key differences when choosing to work with workflows or auto-binding: ### UX The first is simply how it affects the user experience. In some forms it makes sense to let users review their information and not save anything until they click a button. In other cases it's more efficient to save the information as soon as the field has been edited. It's up to you as the developer to decide what's best in each case. ### Security Bubble handles security on actions and auto-bind a bit differently: #### Workflows Workflows are not affected by \[privacy rules\](#user-content-fn-11)\[^11\] and need to have their own conditional expressions set up to control who can do what. As an example, in the action below we have set up an expression that dictates that a user can only edit a profile if it's his own: ![](https://manual.bubble.io/files/jgSNWKvDoiYMBCgdmx9b) The expression above will check that the user being edited is the current user. This ensure that users can only save changes to their own profile. \#### Auto-binding Auto-binding has a dedicated privacy rule which dictates under what circumstances changes to the field will be saved. The field will still be editable, but when it loses focus it will generate an \[error message\](#user-content-fn-12)\[^12\] if the privacy rules doesn't allow for the user to save changes via auto-binding. ![](https://manual.bubble.io/files/exoSjlXXlNQc6JjTPjMa) In the screenshot above we have set up a privacy rule that allows the \*Name\* field to be edited \*if\* the user being edited is the same as the current user. If someone else tries to edit this user with auto-binding, it will generate an error message. ### Performance Workflows and auto-bind also has a slight difference in how they behave from a performance perspective: \* \*\*Workflows\*\* sends all the changes that need to be made in one big chunk to the server. This means you will have \*fewer\* slowdowns, but the one you have may be longer, depending on how much data is transferred \* \*\*Auto-binding\*\* sends the updated information to the server immediately when a field is edited. This means you will have more, but possibly shorter data transfers There's no right or wrong answer to what the right approach is. Also, it's important to note that the difference can be very small, often negligible. While the difference \*is\* there, it's important to weigh the pros and cons in terms of the total user experience to decide what method is best. ## The database editor Bubble also lets you edit data directly in the built-in database editor. This works both for the Development database and the Live database. You access the database editor by going to the \*Data – App data\* tab and selecting the data type you want to edit. You can search for specific things and edit them by clicking the edit icon. ![](https://manual.bubble.io/files/FbBiFNaZ460YL5pMNh9n) Clicking the pencil icon next to a thing lets you make changes to it. Editing directly in the database is useful when you need to make a quick update, but as a long-term solution we recommend setting up your own forms to edit data. Video lessons \* \[The data tab\](https://youtu.be/z0L8vFsCwkk) \## FAQ #### If I use auto-binding, can I still run additional actions when something is saved? Yes. You can set up a workflow using the \*An input's value has changed\* event and place additional actions there. It's worth noting that the auto-bind operation may or may not have finished in time for the action to register the change. In other words, if any of the actions in that workflow rely on the data having been saved to the database, you may want to save it in a workflow instead of auto-binding. That way you can ensure that the process has completed by using the \*Result of step X\* data source. #### Can I create new things with auto-bind? Auto-bind only works on existing things, and cannot create new ones. If you try to write something in a container that has no data loaded, the operation will fail without showing any errors. ## Other ways to learn Video lessons \* \[The data tab\](https://youtu.be/z0L8vFsCwkk) \* \[Instantly modify data with autobinding\](https://youtu.be/MamNYJmZjVY) \[^1\]: A \*thing\* is an individual record in the database, such as a specific \*user\*. \[^2\]: A workflow is a chain of one or more \*actions\* that are executed by an \*event.\*\\ \\ For example, the user clicking a button can trigger actions that save some changes in the database, and then show a confirmation message. \[^3\]: \*Auto-binding\* is a setting that you can set on an input field. Whenever the data in that field changes and the field loses focus, Bubble will automatically save the changes to a specific field in the database.\\ \\ For example, if a user is looking at a form where they can edit their user profile data, an auto-bind input field lets the user type in a new name, and it will be saved immediately.\\ \\ Optionally, you can show a confirmation message when this happens. \[^4\]: An \*input element\* is any kind of element that accepts input from the user, such as text, numbers, dates and addresses.\\ \\ You can then use the information that the user provide. For example, you can save it to the database for permanent storage.\\ \\ Article: \[Input forms\](/help-guides/design/elements/web-app/input-forms.md)\\ Reference: \[Input forms\](/core-resources/elements/input-forms.md) \[^5\]: The database editor lets you as an app developer make changes directly in the database without having to set up any forms or workflows.\\ \\ You'll find the database editor in the \*Data\* tab and going to \*App data.\* \[^6\]: The \*Alert element\* lets you flash a message to your users for a brief period of time, and is useful to show notifications, warnings, welcome messages and other stuff that you don't need to stay on the page for long. Reference: \[The alert element\](/core-resources/elements/visual-elements.md#alert)\\ Video: \[How to use the alert element\](https://www.youtube.com/watch?v=Die7FRWEsbY\\&embeds\_euri=https%3A%2F%2Fcdn.iframe.ly%2F\\&feature=emb\_imp\_woyt) \[^7\]: Container elements such as group can have a database thing loaded into them. This way, each child element can reference that data to display data, auto-bind input elements and in workflows.\\ \\ Article: \[The element hierarchy\](/help-guides/design/elements/the-element-hierarchy.md)\\ Article section: \[Loading data into containers\](/help-guides/design/elements/web-app/containers.md#loading-data-into-containers) \[^8\]: The \*text input element\* accepts text and numbers in different formats from the user.\\ \\ Article section: \[Text input elements\](/help-guides/design/elements/web-app/input-forms.md#text-and-numbers) \[^9\]: Containers are used to contain elements and control how they behave on the page. The most common container element is the \*group\*.\\ \\ Article: \[The element hierarchy\](/help-guides/design/elements/the-element-hierarchy.md)\\ Article series: \[Containers\](/help-guides/design/elements/web-app/containers.md) \[^10\]: The page is the top level of the element hierarchy and contains all other elements.\\ \\ Article: \[The element hierarchy\](/help-guides/design/elements/the-element-hierarchy.md)\\ Article: \[The page\](/help-guides/design/elements/web-app/the-page.md) \[^11\]: Privacy Rules let you define database rules to prevent users from seeing or modifying data they should not have access to. They are applied on the server-side.\\ \\ Article: \[Securing data with Privacy Rules\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md) \[^12\]: The default error message is "Sorry, you do not have permission to modify this."\\ \\ You can modify this text string in your app's \*Application texts and messages\* in the \*Settings - Language\* tab by locating the string called NO\\\_PERMISSION. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/creating-saving-and-deleting-data.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type.md). # Database structure by app type In this section you can browse different guides on how to set up your database structure and Privacy Rules, based on what kind of app you are building. These guides are written by highly experienced member of the Bubble community who have worked on a variety of projects and have been kind enough to share their experience. Use the navigation bar on the left to navigate the different categories --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/variables-and-styles/styles.md). # Styles Bubble lets you set up overarching \*styles\* for elements within your app to streamline the design process and promote consistency. By modifying a single style, you can effortlessly restyle all related elements, making it easy to set up and manage a cohesive look and feel in your app. Each style is connected to a specific element type and includes differerent properties that can be edited (depending on the element type), such as: \* Background color or image \* Border \* Shadow \* Font \* Transitions Apart from making the design process more efficient, Styles also improves your app's performance by storing styling settings in one central place as opposed to saving it on each separate element. Styles can be combined with \[Color variables\](#user-content-fn-1)\[^1\] and \[Font variables\](#user-content-fn-2)\[^2\] to set up a design system that's highly efficient and flexible. ## Defining styles The \*Styles\* section in the \*Global\* tab is where you edit the different styles that your app has. Editing styles is very similar to editing elements, you use the property editor to change the styling properties. You can define as many styles as you want. Styles are applied to one type of element, for instance Buttons, but you can have more than one style for Button. Try to name them in a way is easy to read, as you'll have to pick the style that you need for each button. You can also specify which style should be used by default when you insert a new element in this tab. You can create a from the \*Style\* section by clicking on 'New Style', or from an element itself. When you do so from an element, the current properties of the element will be used as a base for the newly created style. This is particularly useful when you find yourself using the same design for a few elements, but haven't thought about creating a style yet. Please note that when creating your own Styles, specialized labels such as \`H1\` for headers cannot be used. ![](https://manual.bubble.io/files/SYwNrYJiOyEMzvdUvbCU) \## Applying and removing styles ### Conditions on styles You can build some conditions on styles, but only for \*basic\* states, that is to say conditions that are about built-in, simple interactions with the element (hovered, focused, etc.) For instance, conditions using data, or properties on the user, will not qualify as basic. ## Applying and detaching styles When you apply a style to an element, its current properties that are included in the style will be deleted. On the other hand, when you detach a style from an element, the original properties of the style will be copied to the element. So effectively, when you detach a style from a button, the button's appearance won't change at first, so that you can modify the appearance. You can always undo such changes. Detaching a style does not change or deleted the style, it only detaches it from that specific element. !\[\](/files/-M5sc4ELfv7V6AOG0MEK) To detach a style, click the \*Detach style\* link underneath the Styles dropdown in the \[property editor\](#user-content-fn-3)\[^3\]. ### Style overriding Style overriding happens when you adjust the styling properties of an element that already has a style attached. Instead of changing the base style itself, you modify individual properties—like colors, borders, or fonts—directly on the element. ![](https://manual.bubble.io/files/xlPSh6ajygHLHeeqN4AZ) When you change styling properties to an element that already has a style attached, it will be displayed as _Overridden_ in the Style selector. These overrides apply only to that specific element and take priority over the shared style settings, allowing you to fine-tune its appearance without affecting other elements using the same style. To restore the element’s style to its default properties, click \*Reset\*, highlighted in red in the illustration above. ## Conflicts between conditions You can overwrite a condition that is included in a style at the element level; between a style's condition and an element's condition, if the same property is modified, the condition at the element level will win. ## Web and mobile styles ### Overview The Styles tab supports \*\*styles for web and mobile apps in the same project\*\*, allowing you to define and manage visual settings for both mobile and web components. With platform-specific filtering, compatibility indicators, and canvas previews, it's easy to build consistent designs across platforms while accounting for the differences between them. ### Platform filter ![](https://manual.bubble.io/files/ZZ8Mr9hXUE1RnfcrXZPr) A platform filter is available in the left sidebar of the Styles tab. This lets you view: \* \*\*All\*\* styles (web and mobile) \* \*\*Mobile\*\*-only styles \* \*\*Web\*\*-only styles Use this filter to focus on the styles relevant to the platform you’re designing for. ### Compatibility badges Each style includes a compatibility badge that shows where it can be used: \* A \*\*phone icon\*\* indicates the style applies to mobile-only elements \* A \*\*computer icon\*\* indicates web-only elements \* \*\*Both icons\*\* appear for styles that apply to elements shared between mobile and web These badges help clarify which platform each style supports. ### Style editor for shared elements Some elements, like \*\*buttons\*\*, are available on both mobile and web. For these shared elements, the style editor groups settings into: \* \*\*Shared properties\*\*, which apply across both platforms \* \*\*Platform-specific properties\*\*, which are unique to either web or mobile For example, shadows are handled differently between platforms. These differences are reflected in the style editor, with mobile- and web-specific controls shown where relevant. ### Canvas preview toggle ![](https://manual.bubble.io/files/9BYZtdDcwoKvFyaH4gSK) When editing styles for shared elements, the canvas preview includes a toggle that lets you switch between \*\*web\*\* and \*\*mobile\*\* views. This helps you see how the style will appear in each context. If a style applies only to one platform, the toggle is hidden and the preview reflects that platform by default. ### Creating mobile-only styles Styles can be created for mobile-only elements such as: \* \*\*App bars\*\* \* \*\*Tab items\*\* \* \*\*Sheets\*\* When editing a mobile-only style, the style editor shows mobile-specific settings and the preview reflects the mobile context. These styles won’t appear in web projects. ### Notes \* Mobile-only styles do not include the platform toggle or web-specific settings. \* Preview behavior for mobile elements may differ slightly depending on the element’s structure or layout properties. ### Element style support | Name | Type | | -------------------- | ----------------------- | | Text | Both | | Alert | Web | | Input | Both | | Multiline Input | Both | | Dropdown | Web | | Checkbox | Both w/ Different Props | | Radio Buttons | Web | | Date/Time Picker | Both w/ Different Props | | File Uploader | Web | | Popup | Web | | Button | Both | | Link | Web | | Icon | Both | | Image | Both | | Video | Web | | Shape | Both | | Slider | Web | | Group | Both | | Floating Group | Both | | Table | Web | | Group Focus | Web | | Repeating Group | Web | | Search Box | Web | | Map | Both w/ Different Props | | HTML | Web | | | | | Sheet | Mobile | | Tab Bar | Mobile | | Tab item | Mobile | | Top App Bar | Mobile | | Web View | Mobile | | Horizontal List | Mobile | | Horizontal list item | Mobile | | Short List | Mobile | | Short list item | Mobile | | Selectable list | Mobile | | Selectable list item | Mobile | | Vertical list item | Mobile | | Section header item | Mobile | | Swipe action | Mobile | ## Using Style Variables Style variables are used to store specific colors and fonts that can then be applied to elements and styles throughout your app. This ensures that your use of fonts and colors remains consistent and is easy to switch out later if needed: for example, replacing a color variable will update \*all\* styles that use this variable instantly. You can read more about \[color variables\](/help-guides/design/variables-and-styles/color-variables.md) and \[font variables\](/help-guides/design/variables-and-styles/font-variables.md) in our dedicated articles. ## Using styles in conditionals Conditionals can be placed on elements, to make them look and behave in a specific way. You can read more about that feature \[here\](/help-guides/logic/conditions.md). When you set up a condition, you tell Bubble to check for specific criteria and apply one or more properties when the condition is true. You can set each property individually, or apply a style to set multiple properties at once. Even when a style is applied, you can still adjust individual properties on top of it. \[^1\]: The Color Variables feature enables you to establish a palette of colors that you can apply throughout your app.\\ \\ Making changes in a Color variable automatically applies those changes to every Style and element connected to that variable. Article: \[Color variables\](/help-guides/design/variables-and-styles/color-variables.md) \[^2\]: The Font Variables feature enables you to establish a collection of fonts that you can apply throughout your app. Making changes in a Font variable automatically applies those changes to every Style and element connected to that variable. Article: \[Font variables\](/help-guides/design/variables-and-styles/font-variables.md) \[^3\]: The property editor is the main tool for configuring the elements on your page. When you double-click an element on the page or single-click it in the left-hand element tree, this draggable popup appears, displaying various fields for customization.\\ Article: \[The property editor\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-property-editor.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/variables-and-styles/styles.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/fitbit-plugin.md). # Fitbit plugin ## What is Fitbit? Fitbit is a health and fitness brand known primarily for its wearable devices that track physical activity, sleep patterns, and other personal metrics. These devices, alongside their apps, help users monitor and improve their health and fitness goals. Fitness is owned by Google's parent company Alphabet Inc. The plugin allows your end-users to log in with their Fitbit accounts, fetch their workout data, and update their subscription status through the web API. ![](https://manual.bubble.io/files/MSivxD23Az248Gvgs7NZ) 1\. First, open the \*Install new plugins\* screen in the Bubble editor. 2. To find this plugin, search for \*Fitbit\*. Optionally, you can check the \*Login service\* checkbox to further filter the results. You can also scroll to the bottom of the filters list, under \*Built by\* and select \*Official\* to single out official plugins. 3. Check that the Bubble logo is visible in the bottom-right, and then click \*Install.\* ### Setting up and configuring the Fitbit Web API External documentation To set up an account and generate and manage the Client ID and secret key, please follow the up-to-date directions provided in the official Fitbit Developer documentation. The plugin connects to the Web API. External page: \[Getting Started with the Fitbit APIs\](https://dev.fitbit.com/build/reference/web-api/developer-guide/getting-started/) The Fitbit API follows a common pattern of requiring two different keys to authenticate your app. \* \*\*Client ID:\*\* The Client ID (also referred to as the API Key in some contexts) is essentially the public identifier for your app. Think of it like the name tag your app wears when it talks to Fitbit. In this context, it's not to be confused with your secret access token: In fact, the Client ID doesn't need to be kept secret. \* \*\*Client Secret (access token):\*\* The Secret Key, on the other hand, is like a password. It's used to secure communication between your app and Fitbit's servers. Exposure of the Secret Key can lead to security risks, unlike the App ID. After you've installed the Fitbit plugin, the first step is to set up a developer account to obtain an OAuth key. If you already have a Fitbit account, you can use that login. With your developer account in place, the next move is to register a new app on the Fitbit developer portal. During the app registration process, you'll input various details about your app. Upon completion, Fitbit will provide you with a client ID and a secret key, which are essential for your OAuth 2.0 integration. Next, you'll need to transfer both the client ID and the client secret into the corresponding fields in your plugin settings on Bubble.io. Note that you can activate a generic redirect URL within the Bubble plugin settings. ## Setting up the Fitbit plugin After installing the plugin, you'll find it in your list of installed plugins and can click it to access its settings: ![](https://manual.bubble.io/files/CothmL8OZ4Bj08SciLye) \## Actions, elements and data sources To see the plugin's elements, actions and data sources, as well as their properties, please see the core reference article below: Reference: \[Fitbit\](/core-resources/bubble-made-plugins/fitbit.md) ## FAQ: Fitbit plugin #### What should I do if I accidentally expose my App ID? The App ID is a public identifier, and does not need to be replaced if it's exposed. #### What should I do if I accidentally expose my secret key? The secret key should be kept securely private, as exposure can lead to security risks. We strongly recommend revoking the exposed key and creating a new one immediately. Remember to deploy the changes in your app to Live after replacing the secret key. #### Can I use the plugin to connect to a Fitbit device? The plugin connects to the Web API, which does not give direct access to a device. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/fitbit-plugin.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/export-import-data/importing-data-csv.md). # Importing data (CSV) Bubble has a built-in feature to upload CSV files and import its data to the database. In this article, we'll cover how to perform this operation, as well as how to format the CSV file correctly to prepare it for uploading. Template file To speed up your import and make sure you have the correct formatting, you can download the template file below. You will need access to an app like Microsoft Excel, Google Sheets or Apple Numbers to open and edit it. The first row of each column must be changed to match the field you want to import. For more information about formatting, see the \[chart\](#formatting-the-file) below. File: \[Bubble CSV import template\](https://7061a23464c269152da77797cd07e457.cdn.bubble.io/f1702562561499x243890079131354530/import.csv?\_gl=1\*919bpe\*\_gcl\_au\*Mzc0NjczODcyLjE3MDA2NzI2ODA.\*\_ga\*MTIwNTgxOTU5MS4xNzAwNjcyNjc5\*\_ga\_BFPVR2DEE2\*MTcwMjU1NDI4Mi4xOC4xLjE3MDI1NjI1ODIuMzUuMC4w) {% hint style="info" %} This article explores the built-in CSV tool in the Bubble editor. If you are looking for how to allow your users to upload a CSV file in your app, see the core reference section below: Reference: \[Upload data as CSV\](/core-resources/actions/data-things.md#upload-data-as-csv) {% endhint %} {% hint style="warning" %} \*\*Import delays:\*\* The CSV import feature operates on the same scheduler\[^1\] that handles \[API workflows\](#user-content-fn-2)\[^2\]. As a result, if there is a high volume of scheduled tasks, the uploader may remain at 0% until it reaches its turn in the queue. {% endhint %} ## How to import a CSV file ### Formatting the file The file needs to be of type CSV (comma-separated values), which you can export from apps like Microsoft Excel, Google Sheets and Apple Numbers. To ensure Bubble accurately interprets the data in your file, it's important to format it correctly. Most fields follow standard formatting conventions, though certain complex types, such as date ranges and intervals, may require specific formatting to be recognized properly. The first row of your CSV file must be a header row containing the names of the fields for the data. | Field type | Example | Note | | --- | --- | --- | | date | Jan 1, 2030 9:00 AM | | | date interval | 86400000 | Milliseconds (i.e. 86400000 is 24 hours) | | date range | \[Jan 1, 2030 9:00 am, Jan 1, 2030 10:00 am\] | Comma-separated dates. The first must be before the second. Note the brackets. | | file | //7061a23464c269152da77797cd07e457.cdn.bubble.io/f1702555059736x137960774747504450/Bubble%20logo.svg | The URL to the file | | geographic address | 20 W 34th St., New York, NY 10118, USA | The address as formatted in Google Maps | | image | //7061a23464c269152da77797cd07e457.cdn.bubble.io/f1702555059736x137960774747504450/Bubble%20logo.svg | The URL to the image | | number | 123456 | | | text | Lorem ipsum | | | yes / no | yes | yes or no (don't use true/false) | | custom data type | 1702555073152x152492144645599780 | Unique ID of the thing you are linking to | Note that in the file you want to import, the rows and columns are transposed. {% hint style="warning" %} \*\*Metadata\*\* contained in the following fields is automatically created and updated by Bubble and is not possible to import from a CSV: \* Unique ID \* Creator \* Modified Date \* Created Date \* Slug If these fields are included, they will be automatically set to \*ignore this column\*. {% endhint %} ### Accessing the import feature The CSV import feature is found in the \*Data - App data\* section of the Bubble editor. After navigating there, click the \*Upload\* button. ![](https://manual.bubble.io/files/vCSNAE2FXKk3BBxm5I6H) Click the _Upload_ button in the database editor to start the import process. Remember to first select the correct data type in the left-hand list. \### The import popup {% hint style="warning" %} To successfully import the file, you need to keep the popup open until the file has \*\*uploaded.\*\* When the second progress bar (\*Processing file)\* is visible and starting to fill, you can close the popup and keep working in your app. {% endhint %} The import popup will be displayed, where you can set the correct settings for the import: ![](https://manual.bubble.io/files/VmREGFaxeKDAdMEDkYOh) 1\. First, \*\*select the data type\*\* that you want to import. Note that we have named the data type CSV in the example. 2. \*\*Pick the data delimiter\*\*. This is the character that separates the data, so that Bubble understands its rows and columns. The comma is the most widely used, but the delimiter can be one of the following: \* , \* ; \* tab \* | 3. \*\*Select the file to upload\*\* from your device (opens system file browser) 4. \*\*Map fields\*\*: Bubble will attempt to match the columns in the file with the correct field on the selected data type. In the example, we have named the fields according to their type of data. 5. \*\*Choose delimiters on fields\*\*: some fields, such as date ranges, need a valid delimiter. This is normally a comma, but the characters listed in point 2 are all valid. 6. \*\*Validate the data\*\*: the next step is to instruct Bubble to check the data in the file against the fields you have mapped. If successful, you will get a success message. If there are any errors, they will be listed after you click the \*Validate data\* button. ## FAQ: CSV import #### Can you upload more than one data type at a time? You can only upload one data type at a time. #### Can I create new fields on the data type based on columns in the file? No, all fields must be created and have matching names before they are uploaded. \[^1\]: In the \*Logs\* tab of your application editor, you can access the scheduler to view all upcoming scheduled workflows. Article: \[API workflow scheduler\](/help-guides/maintaining-an-application/scheduler.md) \[^2\]: \*API workflows\* are server-side workflows that you can schedule/trigger in your application and/or expose to be triggered from an external application or system through an API request. Article series: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/export-import-data/importing-data-csv.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/logic/navigation/single-page-applications-spa.md). # Single-page applications (SPA) A single-page application dynamically updates and displays content within a single page, without requiring page reloads. This is done by simultaneously hiding and showing containers on the page so that the content of one replaces the other. Single-page applications can be very quick to navigate and use, since you don't need to keep reloading the page. This also means that any data that you have loaded onto the page (such as a \*Do a search for)\* will remain in memory on that page until it's reloaded so that you don't need to load the same content repeatedly. If you build a very complex single-page app with hundreds or even thousands of elements and workflows, this can start slowing down the page, especially on page load. So while your app can be faster to navigate after page load, the initial loading can be a bit longer, since the page contains more code. There's no black and white answer for when to choose what, but many developers choose to go with combination of a single-page app and a multi-page app where they place all the app's most-used features on one SPA page, and move the lesser used features to other pages. This way, the daily use of the app will be snappy, and you avoid a long page load time. Keep in mind what your app is for: users of a tool like a project management or HR app may not mind that the initial page load time is a bit longer, while your users may be less forgiving if it's an eCommerce app or blog. ## The structure of SPAs A single-page application relies on \*containers\* to update their content, and the \*group\* container in particular. While the containers can be hidden and displayed using actions, they are more commonly set up to have \*conditions\* that determine whether the group is showing or not. ![](https://manual.bubble.io/files/sUTqyGR4XcVGLClgRoo8) The example above uses URL parameters to determine whether the group called \*Form 1\* is visible or not (we'll return to that method later in the article). The logical structure for most SPAs is that whenever the group is hidden, another group takes its place: Bubble switches their position instantly, and the user is unaware of the actual structure of the page; all they see is elements that instantly hide and show depending on the user's actions. {% hint style="info" %} To understand how containers replace each other by collapsing their own height and width, we recommend getting to know how the responsive engine works. If you are new to this, you may be interested in checking out the article below: Article: \[Responsive design\](/help-guides/design/responsive-design.md) {% endhint %} ## Setting up the page In a single-page application, the best way to set up your groups is to place them directly on top of each other. That way, when one group goes invisible and another takes its place, the switch seems instant to the user, and the page maintains a height relative to its visible elements. ![](https://manual.bubble.io/files/UnJAGg56lKiJLg0LhAio) In this example, we have two groups placed on top of each other. When one his hidden, it collapses its height and the other group takes its place. To the user, the switch is instant. For this to work, we need to ensure that some key settings on the elements are set up: ![](https://manual.bubble.io/files/Jakc7X0Iix3AJCKrZBPj) 1\. First, navigate to the Layout tab 2. Make sure that the \*Collapse when hidden\* box is checked. This instructs Bubble to reduce the height of the group to 0 pixels, so that the group below can take its place 3. Leave the \*Animate the collapse operation\* unchecked. If the change is animated, the switch will not be instant. Note also that \*This element is visible on page load\* is unchecked. This means that the group will be invisible by default, and we'll set up a condition to make it \*visible.\* ## Using conditions {% hint style="info" %} On pages that consist of a many groups, using conditions can be easier to keep track of. However, on pages that only have a few elements hiding and showing, actions can be quicker to set up. {% endhint %} Most apps will use of two options for navigation: custom states or URL parameters. Both are perfectly good solutions that come with their own pros and cons: \[\*\*Custom states\*\*\](#user-content-fn-1)\[^1\] are variables that you can save temporarily on an element and reference in a condition to show and hide elements. They are invisible to the user, meaning that your users will only see the result, as opposed to URL parameters where they will see a change in the URL. A custom state needs to either have a default value on page load, or be set using an action. \[\*\*URL parameters\*\*\](#user-content-fn-2)\[^2\] add a parameter to the URL of the page, and you can reference this parameter in a conditional expression. The user can see that the URL changes and use the browser's back button as if they were visiting a new page. Users can also use the URL (such as sharing the URL or bookmarking it) to visit the same section of your SPA's later, whereas a custom state must be set by an action in your app. There is no best practice for which method to choose, but we recommend getting to know each of them. If you want your users to be able to use the browser's back button (which is an expected behavior in Android apps) for example, you'll find it easier to set up using URL parameters. If you \*don't\* want your users to be able to go back in that way, or you don't want them to be able to manipulate the URL parameters, you are better off going with custom states. ### Custom states {% hint style="info" %} If this is your first time setting up a custom state, you may find our dedicated article useful: Article: \[Custom states\](/help-guides/data/temporary-data/custom-states.md)\\ Reference: \[The set state of an element action\](/core-resources/actions/element.md#set-state-of-an-element) {% endhint %} Custom states need to contain a default from page load or be set by an action. They are connected to an element of your choice. In this example we'll save the custom state on the page itself: \*index\*. #### Setting a default value To set a default value, follow the steps below: ![](https://manual.bubble.io/files/biybxPGuDMMj4gY5lpz3) 1\. First, open the element inspector of the page. 2. Then, click the small ⓘ symbol in the top bar of the inspector 3. If you don't have the custom state set up, click \*Add a new custom state\*, and give it a name\[^3\]. In the type dropdown, we'll leave it as \*text\*. 4. In the \[\*Default value\*\](#user-content-fn-4)\[^4\] field we'll set the string \*form1\*. #### Setting the value with an action Whenever you need to change the value of a custom state you use the \[\*Set state of an element\*\](#user-content-fn-5)\[^5\] action: ![](https://manual.bubble.io/files/57yrmRr2G3c93gltJRqC) 1\. First, add the \*Set state of an element\* action to a workflow of your chocie 2. Then, we'll chose which element the custom state is saved on. In this example, we placed it on the page, so we'll choose \*index\* 3. If you have already created the custom state in the last step, you can choose it here. If not, you can select \*Create a new custom state\*, set its type to \*text\* and give it the name \*nav\*. 4. In the value field, Bubble will ask for a \*text\* since this is the type we set for that custom state. You can then type in the value. In this example, we are assuming that the custom state had the default value of \*form1\* that we set in the previous steps, and we'll set it to \*form2\* so that this action switches visibility between the two groups. #### Reading the data in the URL parameter To set up the condition on the group element, we'll need to use a dynamic expression to check its value. ![](https://manual.bubble.io/files/7ZedklHRQDsoPhs48ePE) First, select the group element that you want to show with this condition. Double-click it to open up the element inspector. \*\*When:\*\* this is the condition that instructs Bubble \*when\* to style the element. We saved the custom state on the \*index\* element (the page), so search or click on \*index\* as the data source of the expression. With index selected you will see the \*nav\* custom state available as an operator. \*\*Properties:\*\* In the \*Select a property to change when true\* dropdown, we selected \*This element is visible\*. Note that the box is \*checked –\* this is because we set the group to be invisible by default, so we need the condition to make it visible. You'll need to set up the condition on each group element that you want to show/hide, and provide a different value to each of them, such as \*form2\* and \*form3.\* ### URL parameters Related articles If this is your first time setting up URL parameters, you may find our dedicated article useful: Article: \[URL parameters\](/help-guides/data/temporary-data/url-parameters.md)\\ Reference: \[The Get data from page URL data source\](/core-resources/data/data-sources.md#get-data-from-page-url) Let's look at how this would look if you set it up using URL parameters. URL parameters are pieces of data that you can place in the URL of the browser, consisting of a \*key\* and a \*value\*. #### Setting the URL parameter You can set a URL parameter by having it present in the URL when the page is loaded (by following a link for example) or by using the \*Go to page\* action. In this example, we'll do the latter: ![](https://manual.bubble.io/files/YQDuSJ6RjSMSExAagnSh) 1\. First, we'll add the \[Go to page\](#user-content-fn-6)\[^6\] action to a workflow. The event of the workflow can be whatever you need, such as a button or text being clicked. 2. We are setting the \*Destination\* to be the same as the page we are already on: the \*index\* page. 3. If you have multiple URL parameters and you want the existing parameters to remain in the URL, you can check \*Send current page paramerets\*. In the case of this example we only have one, so we'll keep this unchecked. 4. Check the box \*Send more parameters to the page\*. This is how you set one or more URL parameters. Click the \*Add another parameter\* button to create a new row. You will be asked for a \*key\* and a \*value\*. We'll set the key to \*nav\* and the value to \*form1\*. The string you provide in key and value do not affect how the URL parameter works, but keep in mind it will be visible to your users in the browser's URL bar. {% hint style="info" %} To ensure compatibility with all browsers, we recommend giving the key and value fields values that are \[URL encoded\](#user-content-fn-7)\[^7\]: lowercase strings with no special characters or spaces. {% endhint %} #### Reading the data in the URL parameter To read the URL parameter we just set, we'll set up a dynamic expression in the \*Conditional\* tab of the first group. Let's return to the screenshot from earlier and go over how it works: ![](https://manual.bubble.io/files/sUTqyGR4XcVGLClgRoo8) \*\*When:\*\* this is the condition that instructs Bubble \*when\* to style the element. We are using the \*Get data from URL\* data source, and the name (key) of the URL parameter is \*nav\*. You can use whichever name you want – just keep in mind that your users will see it in the URL bar. \*\*Properties:\*\* In the \*Select a property to change when true\* dropdown, we selected \*This element is visible\*. Note that the box is \*checked –\* this is because we set the group to be invisible by default, so we need the condition to make it visible. To summarize then logic, let's look at the condition as a humanly readable sentence: {% code overflow="wrap" %} \`\`\` When the URL parameter called nav contains the text form1, make this element visible. \`\`\` {% endcode %} To make this logic work on your other groups, simply set up the same condition on them, but change the \*value\* of the URL parameter, such as \*nav=form2\* and \*nav=form3.\* ## Using actions You can also show and hide elements using actions. The result to the user will be the same, so we are simply using a different method to reach the same goal. {% hint style="info" %} On pages that consist of a few groups, using actions can be quicker to set up. However, on pages that have a lot of elements hiding and showing, conditions can be easier to keep track of. {% endhint %} #### Using the show/hide an element actions To instruct Bubble to show or hide an element we have two actions to choose from \[\*Show an element\*\](#user-content-fn-8)\[^8\] and \[\*Hide an element\*\](#user-content-fn-9)\[^9\]. Note that these are separate actions and not the same one: ![](https://manual.bubble.io/files/wxAZo6eNnQI9I68kRGao) 1\. First, add the \*Show an element\* action to a workflow of your choice 2. Then, select the element that you want to show. In this case we want to show the group called \*Form 1.\* #### Using the toggle an element action If you want the same action to toggle the visibility of the element, you can use the \[\*Toggle an element\*\](#user-content-fn-10)\[^10\] action. This will do exactly the same as the show/hide an element actions, except you only need one action: ![](https://manual.bubble.io/files/fsb9xoaZd8b5C02PObGE) 1\. First, add the Toggle an element action to a workflow of your choice 2. Then, select the element to toggle. In this case we want to toggle the group called \*Form 1\*. ## Other ways to learn Video lessons \* \[How to use the toggle action to show/hide elements\](https://www.youtube.com/watch?v=gDqAc9hj6Mc) \[^1\]: Custom states are variables that you can save on any element on the page, including the page itself. They let you store data temporarily that is reset when the page is reloaded. This is useful when you need your app to remember some information that you don't need to store permanently in the database. Article: \[Custom states\](/help-guides/data/temporary-data/custom-states.md) \[^2\]: A URL parameter is a piece of information that you place in the browser's URL. They follow a key-value-pair\\\[^11\] structure and can hold many different types of data. Article: \[URL parameters\](/help-guides/data/temporary-data/url-parameters.md) \[^3\]: The name and value of a custom state is not visible to your app's users, but can still be revealed in your app's source code, which is downloaded to the user's device when the page loads. As such, be mindful of the name and value you provide: never store any sensitive information in either field. \[^4\]: The default value of a custom state will be set on page load. Note that whenever you clear the value of a custom state in an action, it will return to this default value, rather than be cleared. \[^5\]: The \*Set state of an element\* action sets a value to one or more custom states on a given element.\\ \\ Article: \[Custom states\](/help-guides/data/temporary-data/custom-states.md) Reference: \[The Set state of an element action\](/core-resources/actions/element.md#set-state-of-an-element) \[^6\]: The \*Go to page\* action serves two purposes: it can take the user from one page to another (just like a link), or it can make changes to the current page by loading a new page thing or making changes to URL parameters. In the case of the latter, the page will not reload, but instantly apply the changes. Reference: \[Go to page\](https://manual.bubble.io/help-guides/logic/navigation/pages/-MTujrgFLiHe7MfwSBOF#go-to-page-...) \[^7\]: URL encoding means to convert special characters and spaces in a URL into a standardized format, using percent signs followed by two hexadecimal digits. This is to ensure that the URL will be compatible with all browsers.\\ \\ Bubble has a built-in operator for URL encoding a string.\\ \\ Reference: \[Format as: URL encoded\](https://manual.bubble.io/help-guides/logic/navigation/pages/-MTpydODwo34mk5NucJy#formatted-as-...) \[^8\]: The \*Show an element\* action will instantly show any element on the page. Reference: \[Show an element\](/core-resources/actions/element.md#show-an-element) \[^9\]: The \*Hide an element\* action will instantly show any element on the page. Reference: \[Hide an element\](/core-resources/actions/element.md#hide-an-element) \[^10\]: The \*Toggle an element\* action will set an element's visibility to the opposite of its current value: if it's visible, it will become invisible, and vice versa. Reference: \[Toggle an element\](/core-resources/actions/element.md#toggle-an-element) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/logic/navigation/single-page-applications-spa.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides.md). # API guides In this article series, you'll find step-by-step guides to connecting to popular API services through the API Connector. Use the left-hand navigation to find the article you are looking for. The resources below may help you get started if you are unfamiliar with APIs. {% tabs %} {% tab title="API Connector" %} The API Connector is the plugin we'll use to authenticate and sell requests to ChatGPT. You can find our documentation for the API Connector plugin below. Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md)\\ Article series: \[APIs\](/help-guides/integrations/api.md)\\ \\ Video: \[Bubble Academy\](https://bubble.io/academy) | \[Intro to APIs & The API Connector\](https://bubble.io/video/intro-to-apis--the-api-connector) {% endtab %} {% tab title="API glossary" %} This article series includes several terms and expressions that are common in the broader tech field, particularly those used by API providers, which are not unique to Bubble. To understand these terms better, we recommend referring to our dedicated API glossary, which provides clear explanations for many of these technical concepts. Article: \[API Glossary\](/help-guides/integrations/api/api-glossary.md) {% endtab %} {% endtabs %} --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/javascript.md). # JavaScript For those accustomed to working with JavaScript, transitioning to Bubble will in many ways feel similar. This article will explore the transition from JavaScript to Bubble specifically, but since several programming languages like Python, Ruby, and PHP share many commonalities with JavaScript, you may find it useful if you come from a different language as well. Before diving into the specifics, it's helpful to understand Bubble's philosophy: it is designed to empower anyone to build and launch fully functional web applications without writing any code. This is important when transitioning from a traditional coding background like JavaScript, as it highlights a crucial aspect of the platform: while Bubble is often called a no-code platform, its core feature set extends far beyond the absence of written code. Bubble offers a way to create designs and workflows using a graphical interface, but it also hosts your app’s database, manages CSS-like styles, provides its own client-side and server-side workflow engine, supports a robust inbound and outbound API system, and includes comprehensive tools for user authentication, data privacy, and app deployment. Bubble strives to provide an all-in-one visual platform; essentially, the less users have to worry about the intricacies of the underlying hosting infrastructure, the more they can focus on building their applications. For seasoned JavaScript developers, Bubble’s holistic approach can initially feel different. JavaScript development traditionally involves hands-on control over every aspect of the application stack—from writing and optimizing code to managing servers and configuring build tools. Bubble abstracts much of this complexity away, packaging these capabilities into an integrated visual interface. While this may require an adjustment, it ultimately frees developers from the tedium of manual coding and server management. This shift allows them to focus more on creativity and user experience, and it opens up app creation to a whole new group of non-technical but creative individuals. For developers transitioning from JavaScript to Bubble, it’s interesting to know that Bubble itself is built on top of JavaScript. This foundation means that while you don't need to write JavaScript code directly, the principles and logic that drive your applications in Bubble are rooted in the same technology. In other words, transitioning to Bubble may require some mental adjustments, but having a traditional coding background can give you an advantage in no-code development as well. Bubble also supports extending your app with custom JavaScript code. First, let's examine the differences in terminology between the two platforms, before delving into their distinct approaches to app development. ## Terminology Direct comparisons between terms used in JavaScript and those in Bubble can be of limited use, as each term doesn't always have a direct counterpart. In this section, we’ll instead look at some well-known terms used in JavaScript, and then different concepts in Bubble that can serve a similar meaning or purpose when you develop. ### Event listener An event listener in JavaScript is a function that waits for a specific event to occur on a specified element. When the event occurs, the event listener executes a block of code. This mechanism allows developers to create interactive web applications by responding to user actions such as clicks, key presses, or form submissions. In Bubble, this is handled by workflow\[^1\] \[\*events\*\](#user-content-fn-2)\[^2\]. When an event occurs, such as a button click, page load, or data change, it initiates a series of actions defined in the workflow. ![](https://manual.bubble.io/files/Y84VHKPbxoBjYWoZjhLg) In Bubble, you build workflows by combining an event (1) and one or more actions (2). It’s worth noting that the two terms are not exactly the same: events in Bubble encompass a broader range of triggers, not just those related to elements. For example, a button or icon being clicked is considered an event, but you can also set up events that react to changes in the database or other non-element interactions. ### Function A function is a block of code designed to perform a specific task. Functions take inputs (arguments or parameters), process them through a series of statements, and then return an output. They are fundamental building blocks for creating reusable, modular code. Functions help manage complexity by breaking down tasks into smaller, manageable parts. ![](https://manual.bubble.io/files/9rezIdyep42wH5JxUYCH) In Bubble, a _workflow_ consists of an _event_ and one or more _actions._ In Bubble, workflows are the equivalent of functions but are designed to be more accessible through the visual interface. A workflow\[^1\] in Bubble is a sequence of steps triggered by an event\[^2\], such as a button click, page load, or data change. Each step in the workflow performs an action\[^3\], such as modifying data, \[navigating to a page\](#user-content-fn-4)\[^4\], or displaying an alert - some actions could themselves be viewed as the equivalent of smaller, simpler functions. You can read more about workflows and its components in the article series below. Article series: \[Workflows\](/help-guides/logic/workflows.md) ### Variable In this context, we mean data that is stored temporarily for some purpose. Bubble doesn’t use the term “variable” directly but offers different ways to store data during a user’s session, as opposed to storing it permanently in the database. #### Custom states Custom states in Bubble function as temporary storage fields that you can add to any element on the page through the Bubble editor. They can hold built-in field types such as text, number, and date, as well as custom data types created in the database or data from external sources like APIs or plugins. These states can store a single item or a list (array). Custom states are created visually in the Bubble editor and can be used in workflows and as data sources. They can be pre-populated with static data like text or numbers, but otherwise need to be populated using the \[\*Set state of an element\*\](#user-content-fn-5)\[^5\] action. While they are not inherently dynamic, they rely on workflows for their population and modification. Custom states are useful to hold information throughout a single page session. If the user closes the tab or navigates to another page, the information is lost. You can read more about custom states in the article below. Article: \[Custom states\](/help-guides/data/temporary-data/custom-states.md) #### Container element data sources Container elements such as groups and repeating groups can hold dynamic data in their respective data source field. This can be referenced from other dynamic expression using the element as a data source, such as \`Group Task's task\`, Group Text's text or \`Repeating Group Tasks's List of Tasks\`. Note that if you are using these elements exclusively to store variables (as opposed to displaying something on the page), you may want to look into using \[reusable element custom properties\](#reusable-element-custom-properties), as they offer more flexibility. #### Reusable element custom properties \[Reusable elements\](#user-content-fn-6)\[^6\] in Bubble, similar to components in React or Vue, allow you to set up custom properties that can hold any type of data you specify, including single records or lists. Unlike custom states, these custom properties can hold dynamic data specified with a dynamic expression and do not require workflows to update. Custom properties are particularly useful in scenarios where data storage is not necessarily based on user action. For example, by pre-populating a reusable element's custom property with a dynamic expression, the data is instantly available on page load, rather than needing to be set using an action. It also means the data is not static. Populating a custom state with a database search would retain the list as it was at the time of the search. In contrast, a custom property updates dynamically, reflecting any changes made in the database. This ensures that the data displayed in the reusable element is always current. You can read more about reusable elements and custom properties in the article below:\\ \\ Article: \[Reusable elements\](/help-guides/design/elements/reusable-elements.md) #### Result of step X A workflow\[^1\] in Bubble is a collection of an event\[^2\] and one or more actions\[^3\], akin to how a \[function\](#function) in programming is a block of code designed to perform a specific task, consisting of a sequence of statements that execute in order when the function is called. Workflows, like functions, sometimes need to temporarily store data for later use. In JavaScript, you might store data in variables to use in subsequent steps of the function. In contrast, Bubble automatically manages the creation and storage of data produced by one action, allowing it to be used in subsequent actions within the same workflow. For example, if you use the \[\*Create a new thing\*\](#user-content-fn-7)\[^7\] action to create a new thing (database record) in step 1 of a workflow, you can use the \[\*Result of step 1\*\](#user-content-fn-8)\[^8\] \[data source\](#user-content-fn-9)\[^9\] in subsequent steps to refer to the thing that was created. ### Object Objects are structures used to store collections of data and more complex entities. An object is a collection of properties, where each property is defined as a key-value pair. Objects can contain various types of data, including strings, numbers, arrays, functions, and even other objects. Data within the Bubble platform is stored in its internal structure. Technically, being built on JavaScript, Bubble uses objects, but they are not available to developers in the same way as in JavaScript. Instead, Bubble structures data in ways that are more accessible to non-technical users. This is done in a few different ways: #### Things A thing represents an individual record in the Bubble database and is used to store structured data. Each thing belongs to a \*data type\*, which is akin to a class in object-oriented programming. Data types define the structure of the thing by specifying the fields (properties) it can contain. Data types are created using Bubble's visual editor, and the database can then be populated with things using workflows\[^1\]. \* \*\*Data types:\*\* Data types in Bubble define the structure and fields for things, comparable to classes or schemas in programming. For example, a job board app could have the data types Position and Company. \* \*\*Fields:\*\* Similar to object properties, a thing can have fields that store a preset type of data. The field is set up on the data type. For example, a Company data type could have the fields Name and Address. \* \*\*Relationships:\*\* Relationships between data types can be set up visually, directly in the data type’s fields (see our dedicated article on SQL for more info on how Bubble joins tables). For example, in a job board app, the Position data type could be linked to the Company data type. The article series below covers in detail how the Bubble database is set up: Article series: \[The Database\](/help-guides/data/the-database.md) #### Option sets Option sets in Bubble are used to manage static, predefined lists of values. They are particularly useful for storing data that does not change frequently, such as categories, statuses, or colors. Option sets provide a more structured and efficient way to handle enumerations compared to creating separate data types and records for such fixed lists. Option sets are similar to enums in traditional programming languages. Each option set contains a list of options (values) that can be referenced throughout your application. For example, you might have an option set called “Task Status” with options like \*To Do\*, \*In Progress\*, and \*Completed\*. Article: \[Option sets\](/help-guides/data/static-data/option-sets.md) #### JSON Bubble supports the JSON\[^10\] format for sharing data with external applications and integrating with other web services. This capability means that Bubble can both convert its existing data into JSON format and accept incoming data from other systems in the same format. By using JSON, Bubble facilitates seamless data exchange, making it easier to connect your application with third-party APIs, perform data imports and exports, and build integrated solutions that interact smoothly with a variety of external services. Bubble also provides a few different ways to store temporary data (variables), that you can read more about in the \[Variables\](#variable) section. ### Modules/packages A module is a single file that contains functions, classes, or variables, while a package is a collection of modules organized in a directory hierarchy. They facilitate code reuse, maintainability, and namespace management, allowing developers to break down large applications into manageable pieces and share reusable components across projects. Modules/packages don't have a direct counterpart in Bubble, but can be implemented in a few different ways. #### Plugins Plugins\[^11\] are add-ons that extend the functionality of your app. They can provide new elements, actions, and data sources that integrate seamlessly into the Bubble editor. They can be created to add new features, connect to external APIs, or integrate with third-party services. The Bubble plugin marketplace offers a variety of plugins developed by the Bubble community and Bubble itself. Some plugins are free, while others are offered with a one-time price or subscription. #### Custom JavaScript code Bubble also offers several ways to implement custom JavaScript to extend its functionality. This is particularly useful for adding custom features that extend beyond Bubble's core functionality or integrating with external JavaScript libraries. You can write custom JavaScript in Bubble using the \[HTML element\](#user-content-fn-12)\[^12\] or by creating custom plugins. This capability enables the import and use of JavaScript modules or packages directly within a Bubble application. ## Other concepts in JavaScript and Bubble ### Building user interfaces In a JavaScript-based app or website, building a user interface typically involves writing HTML, CSS, and JavaScript code. Frameworks like React or Vue.js can streamline this process, but you still need to understand how to structure components, manage state, and handle events manually. For example, displaying a user’s name might involve creating a React component, managing state with useState, and using an API call to fetch the user data. Bubble simplifies UI creation through its visual editor. You can drag and drop elements\[^13\] onto the page, adjust their properties\[^14\], set conditions\[^15\] and define workflows\[^1\] that dictate how elements behave. To display a user’s name, you simply place a text element and bind it to the user’s name field from the database, using Bubble’s dynamic expression editor. ![](https://manual.bubble.io/files/tZXQnPl5VhNyFlt3xNwl) Using dynamic expression, you can easily load and display data from the database. The expression above will simply show the text saved in the _Name_ field of the currently logged in users. Bubble handles the data fetching and updating automatically, by establishing a \[WebSocket connection\](#user-content-fn-16)\[^16\] to keep dynamic database data on the page updated in real-time. When a change occurs in the database, Bubble pushes updates through this WebSocket connection to all relevant pages. This ensures that any data displayed on the page is automatically refreshed without requiring a second manual query or a page refresh. {% hint style="info" %} If you have experience working with HTML and CSS, we also have an article that explains how you approach designing, styling and assigning responsive behavior to pages and elements in Bubble: Article: \[Transitioning from HTML/CSS to Bubble\](/help-guides/getting-started/transitioning-to-bubble-from/html-and-css.md) {% endhint %} ### Data management Managing data in JavaScript often involves setting up and interacting with \[RESTful APIs\](#user-content-fn-17)\[^17\] or GraphQL. You write functions to make HTTP requests, handle responses, and update the UI based on the retrieved data. This process requires knowledge of asynchronous programming, promises, and possibly state management libraries like Redux. Bubble provides a built-in database and data management system. Data operations like creating, reading, updating, and deleting records (CRUD) are handled through Bubble's workflows\[^1\] or auto-binding\[^18\]. For instance, saving a form input involves creating a workflow that saves the input data to a specified data type. {% hint style="info" %} If you have experience working with SQL, we also have an article that explains the differences between traditional SQL development and Bubble’s approach to data management. Article: \[Transitioning from SQL to Bubble\](/help-guides/getting-started/transitioning-to-bubble-from/sql.md) {% endhint %} ### Event handling and interactivity Event handling in JavaScript involves writing functions that respond to user actions such as clicks, form submissions, or page loads. You attach these functions to DOM elements using event listeners, and keep track of a sometimes growing number of events and dependencies that can become fairly complex. In Bubble, event handling is managed through workflows\[^1\]. You visually design workflows that trigger in response to user actions. For example, when a button is clicked, you can set a workflow to display a message, navigate to a different page, or update a database record. ### Data security Ensuring data security in a JavaScript application involves setting up authentication and authorization mechanisms, often using libraries like Passport.js or Firebase. You write code to protect routes, manage user sessions, and validate user inputs. Implementing robust security measures requires a solid understanding of web security principles. Bubble simplifies data security with \[privacy rules\](#user-content-fn-19)\[^19\] and \[built-in authentication systems\](#user-content-fn-20)\[^20\]. Privacy rules allow you to define who can view, modify, or interact with specific data types based on conditions built with Bubble’s dynamic expression editor. Bubble also provides built-in user management features, including login, sign-up, and password reset functionalities. #### Performance optimization Performance optimization in JavaScript involves techniques such as lazy loading, code splitting, and minimizing DOM manipulations. Developers must identify performance bottlenecks and apply appropriate solutions, which can be complex and time-consuming. Bubble, on the other hand, handles many performance optimizations behind the scenes. While you can influence performance through efficient design and limiting the amount of data loaded at once, Bubble’s platform manages server-side optimizations, caching, and database indexing automatically. Additionally, Bubble abstracts the numerous server metrics typically managed in traditional app hosting into a single metric called workload\[^21\]. Using Bubble’s built-in tools, you can gain both a holistic and detailed view of the processes that consume the most server resources. This allows you to effectively optimize performance and scalability, without needing to delve into the complexities of server management. \[^1\]: A \*workflow\* is the combination of an \*event\* that triggers one or more \*actions\*. Article series: \[Workflows\](/help-guides/logic/workflows.md) \[^2\]: An \*event\* is the part of a workflow that triggers it. This leads to one or more actions running. Article series: \[Workflows\](/help-guides/logic/workflows.md) Article series: \[Events\](/help-guides/logic/workflows/events.md) \[^3\]: An \*action\* is the part of a workflow that performs a task. A workflow consists of an event (trigger) and one or more actions. Article series: \[Workflows\](/help-guides/logic/workflows.md) \[^4\]: You can read more about different types of page navigation in the article series below. Article series: \[Navigation\](/help-guides/logic/navigation.md) \[^5\]: \*Set state of an element\* is an action that save a piece of data in a custom state on a selected element. Reference: \[Set state of an element\](/core-resources/actions/element.md#set-state-of-an-element) \[^6\]: \*Reusable elements\* are a collection of elements, actions and customizable properties that can be re-used across your app. They are commonly used for headers and footers, for example. Article: \[Reusable elements\](/help-guides/design/elements/reusable-elements.md) \[^7\]: \*Create a new thing\* is an action that creates a new thing (database record) and optionally populates it with data. Reference: \[Create a new thing\](/core-resources/actions/data-things.md#create-a-new-thing) Article series: \[The database\](/help-guides/data/the-database.md) \[^8\]: \*Result of step X\* is a data source available only in workflows, that fetches the data returned by a previous action in the same workflow. \[^9\]: A \*data source\* is the part of a dynamic expression that fetches data from a given source, such as the database, the current user, the current date/time or an external API. Reference: \[Data sources\](/core-resources/data/data-sources.md) \[^10\]: JSON, which stands for JavaScript Object Notation, is a lightweight data-interchange format. It is easy for humans to read and write, and easy for machines to parse and generate. JSON is used primarily to transmit data between a server and web application. \[^11\]: Article: \[Plugins\](/help-guides/integrations/using-plugins.md)\\ Page: \[Bubble plugins\](https://bubble.io/plugins)\\ \\ Article series: \[Building plugins\](/account-and-marketplace/building-plugins.md) \[^12\]: The HTML element allows you to directly embed an element on the page, where you can write or paste HTML, CSS, or JavaScript code. Reference: \[HTML element\](/help-guides/design/elements/web-app/visual-elements.md#html) \[^13\]: Elements are the "building blocks" that make up your page, such as text, images, icons and buttons. Article series: \[Elements\](/help-guides/design/elements.md) \[^14\]: The properties of an element define its attributes, such as size, colors, responsive behavior, data source, and more. \[^15\]: Element \*conditions\* are rules that dynamically change an element’s properties based on the yes/no result returned by a dynamic expression. Article: \[Conditions\](/help-guides/logic/conditions.md) \[^16\]: A \*WebSocket\* is a communication protocol that provides a real-time, bidirectional connection between the user’s browser and the server, enabling instant data updates without needing to refresh the page. \[^17\]: A RESTful API is a set of web services that operate over HTTP to access and use data. It follows REST principles, using standard HTTP verbs like GET, POST, PUT, and DELETE for operations. \[^18\]: Auto-binding is a feature in Bubble that allows you to configure input forms, like text inputs, to automatically update and save their values to a specific data type and field in the database as soon as they are modified. \[^19\]: \*Privacy rules\* are settings that restrict access to data based on specific conditions, as specified in dynamic expressions. This ensures that sensitive information is only visible to authorized users. \[^20\]: Bubble features a built-in system to handle user authentication such as creating accounts, logging in, staying logged in and resetting passwords. Article series: \[User accounts\](/help-guides/data/user-accounts.md) \[^21\]: \*Workload\* is a metric that aggregates all the work the server has to do to power your app over a given time period. Article series: \[Workload\](/help-guides/workload.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/javascript.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/facebook-plugin.md). # Facebook plugin {% hint style="info" %} This is the long-form article on this topic, designed to provide a comprehensive understanding and broader context. For those seeking more technical details, including all properties and settings, be sure to check out our core reference. Reference: \[Facebook Graph API plugin\](/core-resources/bubble-made-plugins/facebook.md) {% endhint %} ## What is Facebook? Facebook is a widely-used social media platform that allows users to connect with friends and family, share photos and videos, join groups, and participate in various social activities online. It's known for its vast user base and influential role in digital communication and media sharing. The Facebook plugin allows your end-users to sign up/log in to their app using their Facebook account, as well as showing a \*Likes\* and \*Pages\* element relevant to their account in your app. You can also enable a broader access that includes the end-user's list of friends. ## Installing the Facebook Graph API plugin ![](https://manual.bubble.io/files/UyVMvMF4k1wMCfR1QFVx) 1\. First, open the \*Install new plugins\* screen in the Bubble editor. 2. To find this plugin, search for \*Facebook\*. Optionally, you can check the \*Login service\* checkbox to further filter the results. You can also scroll to the bottom of the filters list, under \*Built by\* and select \*Official\* to single out official plugins. 3. Check that the Bubble logo is visible in the bottom-right, and then click \*Install.\* ## Setting up the Facebook OAuth plugin After installing the plugin, you'll find it in your list of installed plugins and can click it to access its settings: ![](https://manual.bubble.io/files/vPqeuUAdEKRfqA1TsRym) \### Keys External documentation To generate and manage the App ID and secret key, please follow the directions provided in the official Meta for Developers documentation. External page: \[Meta for developers\](https://developers.facebook.com/docs/facebook-login/overview) The Facebook Graph API follows a common pattern of requiring two different keys to authenticate your app. \* \*\*App ID/API key (client token):\*\* The App ID (also referred to as the API Key in some contexts) is essentially the public identifier for your app. Think of it like the name tag your app wears when it talks to Facebook. In this context, it's not to be confused with your secret access token: In fact, the App ID doesn't need to be kept secret. \* \*\*App secret (access token):\*\* The Secret Key, on the other hand, is like a password. It's used to secure communication between your app and Facebook's servers. Exposure of the Secret Key can lead to security risks, unlike the App ID. ### Scope We offer two different scopes for the Facebook Graph API, that have the following properties: #### Simple The \*Simple\* option grants access to basic information such as the user's name, email, and profile picture. This option requires less permissions to be enabled when the end-user authenticates for the first time. #### With friends The \*With friends\* option extends this access to include the user's list of friends. Choosing this permission requires broader permissions from the end-user when they authenticate for the first time. ## Development keys and Live keys Facebook offers the convenient option of having separate keys for the development and live versions of your app. This feature is highly recommended as it allows you to thoroughly test your application during development without impacting the live connection. Using separate keys ensures that any changes or tests you perform in the development stage won't affect your end-users who are interacting with the live version of your app. See Meta's \[documentation\](#external-documentation) for more information on setting up development keys. ## Actions, elements and data sources To see the plugin's elements, actions and data sources, as well as their properties, please see the core reference article below: Reference: \[Facebook\](/core-resources/bubble-made-plugins/facebook.md) ## FAQ: Facebook Graph API plugin #### What should I do if I accidentally expose my App ID? The App ID is a public identifier, and does not need to be replaced if it's exposed. #### What should I do if I accidentally expose my secret key? The secret key should be kept securely private, as exposure can lead to security risks. We strongly recommend revoking the exposed key and creating a new one immediately. Remember to deploy the changes in your app to Live after replacing the secret key. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/facebook-plugin.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins.md). # Authentication plugins OAuth plugins allow you log users in using a third-party authentication\[^1\] platform such as Google, Facebook, LinkedIn, X (formerly Twitter), Instagram and others. This article series covers how to set up the official plugins developed by Bubble or the third party offering the external service. {% hint style="info" %} This article series covers the Bubble-made/provider-made OAuth plugins. There may be other plugins available in the plugin stores the offer different features on the same OAuth providers, or additional OAuth providers. For documentation and the latest updates on these plugins, please reach out to the plugin creators. {% endhint %} {% hint style="info" %} Throughout this article, we will refer to \*you\* as the Bubble developer as the \*user\*, and the users of your app as \*end-users\*. {% endhint %} ## Auth: The basics Imagine you're at a party and someone you trust (like a friend) vouches for someone new, saying they're cool. You're more likely to trust this new person because your friend says they're okay. That's kind of like what OAuth does, but in the digital world. ### \*\*What is OAuth?\*\* OAuth stands for "Open Authorization", and is a standard for delegating access to apps and systems. In simpler terms, it lets an end-user give an app permission to access their information on another app without giving away the password to that app. In this context, it means that the user can use that third-party platform to sign up and log in to your Bubble app. It sometimes means that your app can fetch information about that end-user, such as their email, name, social media posts and profile picture too, removing the need for a manual form. In some cases, the user can choose what information to reveal. ### \*\*How does OAuth work?\*\* 1. \*\*Requesting Permission\*\*: When an end-user uses your app, and needs to access information from another service (like Google, Facebook, etc.), the web app will redirect the end-user to a form hosted by that app/system, and ask for permission. This is like asking, "Hey, can I check your info on Google?" 2. \*\*Approval and Tokens\*\*: If the end-user says "Yes," Google (in this case) gives your app a special code, called an \*access\* \[\*token\*\](#user-content-fn-2)\[^2\]. Think of this token like a temporary VIP pass; it lets the web app access only what the end-user agreed to share and nothing more. 3. \*\*Access and Security\*\*: The web app uses this token to get the information it needs. Your app never knows the end-user's password for Google, giving the user a secure way to sign up/log in. ### Why is OAuth useful? 1. \*\*Security\*\*: It keeps passwords safe. The end-users password with the OAuth provider is never revealed to your Bubble app. 2. \*\*Control\*\*: End-users can control what information they share and can revoke access at any time. 3. \*\*Convenience\*\*: It's easier for end-users. They don’t need to create new accounts for every web app they use. ### How does OAuth look to the end-user? Most of your end-users are not aware of what OAuth is and how it works, and in most cases, they don't have it, as long as it provides an easy-to-use and secure way to sign up and log in. Here's how the process typically unfolds: 1. \*\*Choosing to connect\*\*: The end-user arrives at your app and sees an option to log in or sign up using services like Google or Facebook. 2. \*\*Clicking to proceed\*\*: They select this option, often presented as a button labeled "Sign in with Google" or similar. 3. \*\*Reviewing permissions\*\*: A pop-up window appears, asking the end-user to confirm if they are comfortable sharing certain information with your app, such as their email address. 4. \*\*Consenting to share\*\*: If the end-user agrees, they click "Allow" or a similar confirmation button. 5. \*\*Access granted\*\*: Your app now accesses the necessary information, and the end-user is directed to their account, ready to use your app's features. 6. \*\*Managing access\*\*: The end-user can always manage what information they've shared with various apps, including yours, through their account settings on the service they used to log in. ## Actions, elements and data sources ### Actions Signing up/logging in using a third-party OAuth app can add new actions\[^3\] to your app, relevant to the app the end-user is using to authenticate. For example, the Slack plugin allows you to post bot messages in a given Slack channel. ### Data sources Some OAuth providers provide new \[data sources\](#user-content-fn-4)\[^4\] that can provide basic or extensive data about the end-user on that platform, such as: \* The end-user's full name and/or nickname \* Profile picture \* Social media posts ### Elements Some plugins also add new elements to the Bubble editor. For example, the Facebook plugin offers an element to show a number of likes for a given Facebook page. ## Official Bubble OAuth plugins We have individual articles on each of the official OAuth plugins created by Bubble or the third-party provider: 1. \[Facebook\](/help-guides/data/user-accounts/authentication-plugins/facebook-plugin.md) 2. \[Fitbit\](/help-guides/data/user-accounts/authentication-plugins/fitbit-plugin.md) 3. \[Google\](/help-guides/data/user-accounts/authentication-plugins/google-plugin.md) 4. \[Instagram\](/help-guides/data/user-accounts/authentication-plugins/instagram-plugin.md) 5. \[LinkedIn\](/help-guides/data/user-accounts/authentication-plugins/linkedin-plugin.md) 6. \[Pinterest\](/help-guides/data/user-accounts/authentication-plugins/pinterest-plugin.md) 7. \[Slack\](/help-guides/data/user-accounts/authentication-plugins/slack-plugin.md) 8. \[Wistia\](/help-guides/data/user-accounts/authentication-plugins/wistia-plugin.md) 9. \[YouTube\](/help-guides/data/user-accounts/authentication-plugins/youtube-plugin.md) Note that this is not an extensive list of all Bubble-made plugins, but only the ones that offer authentication. ## External documentation Throughout this article series, we often point to external documentation. This approach is taken to guarantee that the information provided is both current and accurate. For instance, the method for generating and retrieving an API token or key can vary based on the specific service you're linking to. In these cases, the documentation from the respective third-party service is the definitive and up-to-date source for such procedures. Please note that Bubble is not responsible for the content found in these third-party links. ## FAQ: Third-party authentication plugins #### Is OAuth secure? Yes, OAuth is considered highly secure, equal to using a username and password. All communication with the third-party is encrypted and routed through Bubble's server. #### Can I offer more than one authentication service? Yes, you can offer as many as you like, but the end-user's selected choice is permanent. If the end-user wants to connect to a different provider after signing up, they will need to create a new account. #### Can I combine an OAuth account with a traditional email/password account? Users in Bubble can use traditional logins and social logins at the same time. There are a few cases here: \* \*\*Signing up when logged in:\*\* When a user already logged in with their email and password chooses to link their account with an OAuth provider, their existing account gets updated with the new authentication credentials. This means no new user account is created. After completing this linking process, the user has the flexibility to log in either with their email and password or through the OAuth flow. \* \*\*Email already exists:\*\* However, if a user tries to sign up by linking an account with OAuth and another user in the database already has the same email as the one provided by the external service, the process won't succeed. Instead, the user will receive a notification about the issue. \* \*\*Signing up without being logged in (existing account):\*\* On the other hand, if a user isn't logged in and goes through the OAuth flow, the system will create a new user account. But, if there's an existing user in the app's database with the same email as the one registered with the external service (like Facebook), this action will also fail, and the user will be informed. \* \*\*Adding password to existing OAuth account:\*\* For users who initially signed up using an external service and want to add a password to their account, they can do so by initiating a 'reset the user's password' action. This step adds email and password credentials to their account, which previously only used OAuth for authentication. ## Other ways to learn Articles Introduction to how user accounts work in Bubble: \* \[User accounts\](/help-guides/data/user-accounts.md) The authentication plugins are an easier way to connect to API services. To learn more about what APIs are and how to set up your own connections, see the article series below: \* Article series: \[APIs\](/help-guides/integrations/api.md) Videos \* \[User authentication (Bubble Introduction Series \\\[6/10\\\])\](https://www.youtube.com/watch?v=gn0TixSCmGU) \[^1\]: \*Authentication\* is the process of determining \*who\* an end-user is, in order to give or refuse them access to a system. It's comparable to showing your passport at the airport.\\ \\ Not to be confused with \*authorization,\* which is the process of determining \*what\* that end-user should have access to. \[^2\]: An access token is a string of letters and numbers, often structured as a long, random-looking sequence. It acts as a secure key, enabling your app to access specific end-user account information on another service without needing the user's password. This is considered more secure as the password as it is unique for each connection and can be revoked by the end-user. \[^3\]: \*Actions\* are the part of a workflow that makes something happen, such as creating a database thing, hiding/showing something on the page or navigating to a different page. In this context, actions are new types of things you can do in your app as a result of adding a new plugin. Article series: \[Workflows\](/help-guides/logic/workflows.md) \[^4\]: Data sources are any source from which Bubble can fetch data, such as \*Do a search for\* to find data in the database. In this context, a data source may give your app access to data from a third-party system. See the examples below. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics.md). # Introduction to testing and debugging First, let's spend some time to define the different terms included as you prepare your app for live users: \*\*Testing\*\* is the process of trying out the different steps of your application to check that it works as expected. It doesn't have to mean something wrong, but if there is, testing is meant to uncover it. \*\*Debugging\*\* is done when you've observed a non-expected behavior. It's the process of understanding the root cause of the issue so that you can rectify it. This introductory guide will give you some general advice on how to test and debug your app, before we move on to the tools that Bubble offers. ### The Development environment and Live environment Every Bubble app consists of two environments\[^1\]: Development and Live. Development is a fully functioning version of your app that you (and your team) can work in together to see exactly what the finished app will look live. Live is the app that your users see. The two environments have database that operate completely independently of each other. In other words, in the Development environments you can make changes to your database that have no effect on your live app, making it a completely safe environment to experiment in whichever way you need to. You should always aim to fully complete testing and debugging before deploying your app to Live. ## Testing ### Plan your testing and break it into pieces Testing is all about using your app as your users would, and working systematically through all pages and features to identify issues. While this guide will not outline what a systematic approach should look like (everyone works differently), we will still encourage you to be mindful of how you organize your testing. ### Keep notes If you are testing something and see an issue elsewhere, take a note for later and stay focused on the task at hand. Letting your focus drift from place to place is an easy way to miss things, so remember to stick to the plan, but note down anything else you see. ### Add test data An app with no data in it and an app with lots of data can behave very differently. Adding test data can help you identify issues related to design, performance and security. ### Test on different screen resolutions and devices If your app is going to be used on different screens and devices, it's a good practice to test it on different resolutions and maybe even throttling the connection speed and CPU. Chrome Developer tools offers a highly useful \[Device Mode\](#user-content-fn-2)\[^2\] that lets you do all of these things. ### Test as different users As you introduce privacy rules and conditions, your users will start to experience the app differently. Some users may have access to specific parts of your database and app, while others don't. In these cases it's useful to make a habit of testing your app as different users. For example, if you have two user types, \*user\* and \*admin\*, it's likely that one has a different access level than the other, and you may miss issues or inconsistencies if you only test as one of them. #### How to test the app as another user To use your app as a specific user, simply search for that user in the built-in database editor and click \*Run as\*. ![](https://manual.bubble.io/files/UF76GnISc4IYzq2cJwqJ) Using the _Run as_ feature lets you easily test your app as another user without having to know their credentials. \## Debugging ### Make sure you can reproduce it As you keep testing your app, you will uncover the occasional issue – don't worry, it happens even to the most experienced developers! When beginning to debug an issue, the key initial step is to establish a consistent and predictable method for reproducing it. In practice, this involves retracing your steps and running multiple tests to confirm that the issue consistently appears every time, and with the same characteristics. This lets you get a firm grasp of the problem before you spend time tackling it. ### Stay systematic and break it down Each issue you find may have more than one cause. As you identify it or them, stay focused on one at a time. It can be useful to find ways to test that the cause you're currently working on is fixed before moving on to the next. Again, keep notes to make sure you don't miss anything. ### Remember privacy rules Many issues are related to data being unavailable because of privacy rules. Keep in mind that they apply everywhere (elements, workflows and conditions), so it's often a good idea to check the rules for the relevant data type. ### Collect information If the error has been reported by one of your users, you should try to collect as much information as you can about the circumstances that produced the error. \* Which user is it? \* What kind of device and browser are they using? \* Are they using ad blockers or script blockers of any kind? \* What were the exact steps they took to produce the issue? \* Can it be reliably reproduced, or could it be because of a poor connection or other external reason? ### Reach out to the community Bubble has an incredibly welcoming and helpful community. If you ever find yourself stuck on an issue, don't hesitate to seek help! Share your problem on the \[Bubble forum\](https://forum.bubble.io/), reach out to our \[Success Team\](https://bubble.io/contact), or hire one of our \[expert coaches\](https://bubble.io/coaching) to assist you in resolving it. ### Take a break! Sometime issues are best solved on a walk outside, in the shower or lying on the couch. Other times you simply need some time to refresh your mind before returning to the screen and continuing the search. Your brain is a muscle – it too needs rest between the sessions! ## Testing and debugging tools Bubble offers two ways to debug issues, each serving a specific purpose: The debugger (checking errors on elements and in workflows as they happen) The debugger is a small panel at the bottom of the screen when you are running your app in Development. Using the debugger, you can: \* \*\*Run workflows action-by-action\*\* and check data (such as the result of a search) related to each step \* \*\*Inspect the elements on the page\*\* to check their attributes, conditions and associated data Article: \[The Debugger\](/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md) The Server Logs (diagnosing past issues) The second tool for diagnosing past issues is the Server Logs. This feature allows you to retrospectively examine what occurred in your workflows and check any unexpected behavior or errors. Article: \[The Server Logs\](/help-guides/maintaining-an-application/testing-an-application/using-server-logs.md) \## Using safe modes {% embed url="" %} Our Academy quick tip on how to preview your app in safe mode {% endembed %} Safe modes is a way to preview your app, but disabling certain parts for debugging purposes: \* HTML - this disables on-page HTML elements \* Community plugins - this disables community-made plugins If the issue resolves itself in Safe mode, you'll know it is due to something introduced by a plugin or custom code. #### How to enable Safe mode You enable Safe mode by holding the mouse button on the \*Preview\* button for one second. A dropdown will show you the list of options. ![](https://manual.bubble.io/files/XNFuWBap8AnIJnv8LEtP) What if you think it's a Bubble bug? The Bubble development team extensively tests features and uses automated testing to minimize bugs. However, if you believe you've encountered an issue that is not caused by the way your app and workflows are built but rather an unexpected behavior in a Bubble core feature, please reach out, and we will investigate. This does not apply to plugins that aren’t built by the Bubble team. For those, we recommend reaching out to the plugin author directly. #### How to Report Bugs To report a bug, please use the \*\*Bubble AI chatbot\*\*. \*Note: You must be logged into your Bubble account to report a bug.\* #### Before You Submit a Bug Report To ensure that your issue is indeed a bug, please take the following steps before submitting a report: \* Verify that your internet connection is stable and that you are using the latest version of your browser. \* Test the issue in \*Incognito mode\* (or Private Browsing) to rule out interference from browser extensions or ad blockers. \* Remove any \*custom code\* you have added in HTML elements, headers, or other custom script sections. #### While Submitting a Bug Report To help us investigate and resolve your issue as quickly as possible, please keep the following in mind: \* \*\*Be as specific as possible\*\* when describing the issue:\\ \\ ❌ \*It doesn’t work, I think it’s a bug\*\\ ✅ \*Based on this condition, this element should be red, but instead, I see it as green.\* \* If possible, \*\*reproduce the issue on a blank test page\*\* outside of your app’s core design and workflows. The more isolated the issue, the faster we can investigate. \* Provide \*\*clear instructions\*\* that someone unfamiliar with your app can follow. A step-by-step guide like \*“Click on button A,” “Type XX in the input,” “Click on button B,” “See the problem”\* is the most effective. \* \*\*Include screenshots\*\* to illustrate the issue when prompted in the chatbot. \* \*\*Videos can be helpful\*\* but should not replace written descriptions. They should serve as a complement if necessary. We understand that bugs can be frustrating and slow down development. By providing clear and detailed reports, you help us identify and resolve issues faster—benefiting not only you but the entire Bubble community. \[^1\]: Bubble apps consist of a Development and Live environment that live completely independently of each other. You can read more about this concept in our section on Version Control: Article section: \[Environments\](/help-guides/maintaining-an-application/version-control.md#environments) \[^2\]: Device Mode lets you preview how your page appears and functions on different mobile devices. It also lets you test how it behaves if you throttle CPU and connection speed. External link: \[Chrome Developer Tools Device Mode\](https://developer.chrome.com/docs/devtools/device-mode/) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app.md). # SEO: App The technical side of SEO starts on the app level. Search engines look at your site as a collection of pages under an umbrella: \*your\* \[\*domain\*\](#user-content-fn-1)\[^1\]. The settings that you set on the app level are less about the identity of your app (with the exception of social media sharing, which we'll cover further down), and more about providing \*\*instructions\*\* to the search engines, such as: \* Which pages to crawl\[^2\] and not to crawl \* URLs that have been moved and should be redirected to another URL (\[301 redirect\](#user-content-fn-3)\[^3\]) \* To read a \[sitemap file\](#user-content-fn-4)\[^4\] Some parts of your app's SEO settings can be fairly technical, but if you are not sure if you need them right now, then you most likely don't. We will still cover the basics of each part here. Your app's SEO settings are found under \*Settings - SEO/Meta tags:\* ![](https://manual.bubble.io/files/LNYCibjc0hXd1anukjaq) \## Sharing in social media (OpenGraph) The first part of your app's SEO settings are the OpenGraph details. This lets you set an identity for your app that social media sites such as LinkedIn, X and Facebook will use when a link to your app is shared. OpenGraph metadata can also affect how your page ranks and is displayed in search engines. ![](https://manual.bubble.io/files/N2cyOiYjce4aHlYIv4cY) In the example below from LinkedIn, you can see how as soon as a link is typed into a post, LinkedIn fetches the metadata. ![](https://manual.bubble.io/files/ruOphul7aRHEZNu9YfTV) This helps you convey a consistent brand identity across both social media and search. ## SEO settings ### Setting up headers (\\ , \\ ==== , \\ ---- ### ) The structure of your page plays a role in determining its ranking. A well-structured page involves organizing your text content into distinct sections, each separated by headers at various levels (such as "\` \` and "\` ========== \`"). By default, the setting to add a tag to a text element is not available, but you can enable it by checking \*Expose the type of tags for text elements\*. ### Canonical URLs Imagine you have a well-researched article in your app, and for some reason, it exists in two different places with slightly different URLs. This situation can create confusion for search engines, as they struggle to determine which version should be displayed in search results. Canonical URLs are the solution to this problem. They act as a signal to search engines, specifying which version of a webpage should be considered the "primary" or "preferred" one. By using a canonical URL, you help search engines avoid indexing multiple versions of the same content, thereby improving your website's search ranking and overall visibility. The setting \*Point URLs to primary domain for better SEO\* enables a Bubble-defined canonical url tag. ### Robots.txt Sometimes, you will want to instruct search engines to \*not\* crawl specific pages in your app. For example, if your app has a front-facing index page with other pages like \*about\* and \*privacypolicy\* you will want those indexed, but you may not want to index backend or admin pages. Robots.txt (see \[example\](https://bubble.io/robots.txt)) is a small file that Bubble automatically places in the root directory of your app. It contains instructions to search engine crawlers, specifying which parts of the app they are allowed to access and which parts they should avoid. By default the development version of your app isn't indexed. {% hint style="warning" %} Keep in mind that robots.txt is a \*request\* to search engines to avoid crawling certain pages. While most search engines will respect this, it doesn't actually \*stop\* them from crawling. So this is considered an SEO setting – not a security setting. {% endhint %} #### How do I instruct search engines to hide a page? Let's say that you want to hide the two pages \*dashboard\* and \*admin\* from crawlers. You use the \*Disallow\* command in robots.txt along with the page name to do so: \`\`\` User-agent: \* Disallow: /dashboard Disallow: /admin \`\`\` ### Sitemaps Web crawlers work by following links. If they discover your app's domain and its front page, and this page links to a page called \*about\*, then the crawler will also index that page. But what if a page \*isn't\* linked to? Or if a page contains dynamic content (such as \[www.myapp.com/products/running-shoes\](http://www.myapp.com/products/running-shoes)) – you may link to the product page, but not to every product in your inventory – which is probably the part you want to index. {% hint style="info" %} Keep in mind that for pages with dynamic content, each thing counts as its own separate page, even if they are all loaded on the same page. {% endhint %} Sitemaps are like blueprints for your app that help search engines navigate and understand your app's structure more efficiently. They are essentially XML files that list all the pages within your app even if they are not linked to. Bubble can automatically generate a sitemap for all your pages, and for dynamic pages we will include the things in your database that matches the data type specified on the page. You can select which pages you want to include in the sitemap. When you check the \*Expose a sitemap file\* box, a list of your pages is displayed. Check each page that you want to include. ### Custom header and body content All the script and meta tags placed in the header will be inserted between the \`\` tags on every page of your app, while the scripts added to the body field will be positioned between the \`\` tags across all pages. ![](https://manual.bubble.io/files/qDBVrNuREVKiGthUv8oY) {% hint style="info" %} Adding data to this field will add it to all pages – you can also add it to pages one-by-one in the \[settings for each page\](/help-guides/maintaining-an-application/seo/seo-page.md). {% endhint %} ## 301 redirects A 301 redirect is a permanent redirection method that helps maintain SEO performance when a page moves to a new location. It simply says: \* The page used to be \*here\* \* ... and now it's \*here\* \* ... and it's \*permanent\* (301) Bubble offers an easy way to add a \*before\* and \*after\* URL. The URLs should be the \*full\* URL (including the protocol such as https): \`\`\` ❌ www.bubble.io/page \`\`\` \`\`\` ✅ https://www.bubble.io/page \`\`\` #### SEO ramifications of 301 redirects From an SEO perspective, this is important for a few reasons: \* It helps the search engine find the new page when the old one is missing \* It tells the search engine that the content on the new page is not duplicated – it has simply moved \* It ensures that any referral traffic still reaches the right content #### When are 301 redirects useful? 301 redirects is useful in any case where you need to instruct search engines that a page has moved. \* Whenever you rename a page \* Whenever you change the slug of a thing you are using as dynamic page content \* If you are moving from a non-Bubble framework and your URL structure or domain changes ### Using wildcards in 301 redirects Wildcards in 301 redirects allow you to dynamically match parts of a URL and redirect them to a new URL structure. This functionality is especially useful when dealing with groups of URLs that follow a consistent pattern, reducing the need to create individual redirects for each URL. Wildcards are represented by an asterisk (\\\*), which acts as a placeholder for dynamic content in the URL. These placeholders can then be referenced in the destination URL to preserve or reorder the dynamic parts of the original URL. For example: \*\*From:\*\* \`https://www.example.com/page1/\*\` \*\*To:\*\* \`https://www.example.com/page2\` A request to \\\_ will redirect to . Wildcards can also represent multiple dynamic parts in the URL, which can be carried over to the destination using placeholders like %1, %2, etc., corresponding to the order of the wildcard matches. #### How to use wildcards in 301 redirects To enable and use wildcards in 301 redirects, follow these steps: \*\*Enable Wildcards\*\* \* Check the box labeled \*Allow wildcards in redirects for more dynamic urls\* in your redirect settings. \* Note: Exact matches for 301 redirects will work regardless of whether this checkbox is enabled. \*\*Set up the redirect rule\*\* \* Replace dynamic parts of the source URL with \\\* to indicate wildcards. For example: \* \`https://www.test.com/page1/\*\` -> \`https://www.test.com/page2\` \*\*Use placeholders to preserve data\*\* Wildcard matches can be preserved in the destination URL by referencing them using %1, %2, etc.: \* %1 corresponds to the first \\\* in the source URL. \* %2 corresponds to the second \\\*, and so on. For example: \`https://www.test.com/page1/\*/\*\` -> \`https://www.test.com/page2/%1/%2\` \*\*Ensure accuracy in the structure\*\* While wildcards allow dynamic matching, the slashes (/) in the source and destination URLs must remain accurate and consistent. For example: \`https://www.test.com/page1/\*/\*\` -> \`https://www.test.com/page2/%2/%1\` \*\*Query string behavior\*\* URL parameters (the query string) are automatically copied over to the destination URL, regardless of the wildcard setup. For example: A request to \`https://www.test.com/page1/abc?user=123\` will redirect to \`https://www.test.com/page2/abc?user=123\`. ### Hosting files in root directory Bubble lets you upload files to the root directory. There are many use cases for this, but from an SEO perspective the most common use is to upload a custom sitemap .xml file. ## SEO audit criteria Chrome features an integrated SEO audit tool (found in Inspector > Audits). This tool highlights criteria that may impact your search results. Below is an overview of each criterion and how Bubble apps fare: | Audit criteria | | | ------------------------------------- | ------------------------------------------------------------------------------------------------------------ | | Mobile-friendly | Use the responsive engine and set up pages that follow mobile best practices | | \\ tag | Bubble handles this automatically | | Title | Set up titles on all pages and remember dynamic content | | Meta description | Set up descriptions on all pages and remember dynamic content | | HTTP status code | Bubble handles this automatically | | Links have descriptive text | Set up all your links with descriptive texts | | Page isn’t blocked from indexing | Bubble handles this automatically | | "robots.txt is valid | Bubble handles this automatically, but you can also \[customize it\](#robots.txt) | | Image elements have \\\[alt\] attributes | Add alt tags to all images in the property editor of each image | | Document has a valid hreflang | Bubble handles this automatically | | Document has a valid rel=canonical | Bubble handles this automatically, but you can also set up \[301 redirects\](#301-redirects) | | Document uses legible font sizes | Font sizes less than 12px are too small to be legible. Use it sparingly (60% of text above bigger than 12px) | | Document avoids plugins | This does not apply to Bubble (\*plugins\* here does not refer to Bubble plugins) | \[^1\]: Your domain is the root part of your URL, such as \[www.bubble.io.\\\\\](http://www.bubble.io.\\\\) \\ All other content in your app is considered a part of that domain. \[^2\]: \*Crawling\* is the process when a search engine scans your site to add it to its index. \[^3\]: A 301 redirect is a method used to permanently redirect one URL to another. In non-technical terms, it's like forwarding your mail to a new address when you move to a new house. \[^4\]: A sitemap file is a document that provides a roadmap of your app's content. It helps search engines understand its structure, making it easier for them to find and index its pages. In simple terms, a sitemap file is like a table of contents for a website. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist.md). # Optimization checklist {% tabs %} {% tab title="Experience level" %} Workload optimization sometimes touches on advanced Bubble practices. We recommend this guide for developers who are fairly experienced with Bubble, and it's useful to read up relevant chapters in the User manual to prepare for the process. {% endtab %} {% tab title="Related articles (10)" %} \*\*Client-side versus server-side\*\* Understanding the difference between server-side and client-side is key to evaluating processes for workload. Article: \[Server-side vs client-side processing\](/help-guides/workload/understanding-workload/client-side-and-server-side-processing.md) \*\*\* \*\*Data\*\*\\ In this article series, we cover how to work with different types of data in Bubble: Article series: \[Data\](/help-guides/data.md) \*\*\* \*\*Workflows\*\* \* Article series: \[Workflows\](/help-guides/logic/workflows.md) \* Article: \[Events\](/help-guides/logic/workflows/events.md) \* Article: \[Actions\](/help-guides/logic/workflows/actions.md) \*\*\* #### \*\*Logic\*\* Workflows is a part of the \*Logic\* series user manual series. \* Article series: \[Logic\](/help-guides/logic.md) \* Article: \[The frontend and backend\](/help-guides/logic/the-frontend-and-backend.md) \* Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md)\\ Dynamic expressions are used both to set up conditions, and are highly useful in different actions that you may want to add to your workflows. \* Article: \[Conditions\](/help-guides/logic/conditions.md)\\ Conditions are used to determine whether a workflow or action should run or not, by checking whether something is true. \* Article series: \[Navigation\](/help-guides/logic/navigation.md)\\ Using workflows to let the user navigate between pages and page sections. {% endtab %} {% endtabs %} Optimization framework The content of this article follows our workload optimization framework, which consists of the following points: 1. \*\*Complexity:\*\* How complex is a given process? 2. \*\*Repetition:\*\* How frequently is a given process repeated? 3. \*\*Volume:\*\* How much data is returned by the database in a given process? To learn more about the optimization framework, check out the article below. Article: \[Workload optimization framework\](/help-guides/workload/optimizing-workload/optimization-framework.md) \*\*\* In this article, we provide a quick guide to optimize areas of your app where optimization opportunities are common. Each expandable box below includes a link to a more detailed article for deeper insights. Before diving into each point, please remember that while these tips can serve as a checklist for optimizing your app, they won’t cover every unique scenario. Think of them as examples of how to apply the optimization framework by assessing whether a process is complex, repeated, or returns a high volume of data. Page load Full article: \[Optimizing page load\](/help-guides/workload/optimizing-workload/optimization-checklist/page-load.md) ### Go to page action Page is loaded events will trigger every time the \*Go to page\* action is used, even if the user remains on the same page, and it doesn't technically refresh. #### Solutions: \* \*\*Repetition:\*\* remove \*Page is loaded\* events, or replace them by another event that doesn't repeat as often. \* \*\*Repetition:\*\* use conditions to ensure \*Go to page\* only runs once. ### Loading data on page load Loading data and/or performing searches on page load means that they are likely to be performed frequently. \* \*\*Repetition:\*\* instead of on page load, load data later (such as requiring a \[user interaction\](#user-content-fn-1)\[^1\]). \* \*\*Repetition:\*\* \[use conditions\](#user-content-fn-2)\[^2\] to stop invisible elements from loading data. \* \*\*Repetition/volume/complexity\*\*: avoid \[nested searches\](#user-content-fn-3)\[^3\]. \* \*\*Volume:\*\* set up your database in a way that returns less data ### Page load workflows It can be useful to run workflows as soon as the page loads, but keep in mind that anything that happens on page load is \*repetitive.\* \* Look for ways to make page load workflows lightweight \* \*\*Complexity:\*\* reduce the number of actions. \* \*\*Complexity:\*\* simplify dynamic expressions. \* \*\*Complexity:\*\* Avoid \[nested searches\](#user-content-fn-3)\[^3\]. \* \*\*Volume:\*\* avoid searches that return a \[large amount of data\](#user-content-fn-4)\[^4\]. \* \*\*Repetition:\*\* consider whether a workflow needs to run on every page load. \* \*\*Repetition:\*\* check whether the \*Go to page action\* forces a workflow to run more often than you anticipated. ### Redirects Redirecting users to a different page is common in cases such as when the user is not logged in. Redirection can happen server-side (before the first page is loaded), or client-side (after the first page is loaded). Performing redirects server-side means that no workload is spent sending the page HTML before the user is redirected. \* \*\*Complexity:\*\* keep redirection events as straightforward as possible, such as using \*User is logged out\* with no conditions. When Bubble doesn't need to check anything on the page, it can redirect the user immediately instead of \[loading the page first\](#user-content-fn-5)\[^5\]. ### Data aggregation Many apps aggregate data in different ways (such as counting or calculating a sum or average). This is often done through a data source like \*Do a search for\* in combination with an operator like \*:count, :sum,\* or \*:average.\* \* \*\*Repetition:\*\* considering calculating the numbers and storing them somewhere, instead of redoing the calculation every time they are displayed. \* \*\*Repetition:\*\* consider not showing data until the user asks for it through interaction such as a button click. \* \*\*Repetition:\*\* use conditions to avoid querying the data until an element is visible. \* \*\*Complexity:\*\* set up the dynamic expression with as few sub-expressions as possible, and avoiding nested searches. Searches Searching for data is on its own not an especially heavy database operation, but we can use the optimization framework to determine whether a search spends a more significant amount than is necessary. \* \*\*Complexity:\*\* avoid nested searches. \* In repeating groups where each row contains a second search. \* In search expressions, where a constraint or field contains a second search. \* \*\*Complexity:\*\* avoid advanced filters. \* Advanced filters (using the :filtered and :advanced operators) can substantially increase the WU needed to complete the query. \* \*\*Volume:\*\* be mindful of structured and unstructured data. \* Structured data is short, to-the-point data like names, phone numbers and emails. \* Unstructured data can be long and "heavy", like blog posts, articles and product descriptions. \* More text means more data to download, which translates into spending more WU. \* \*\*Repetition:\*\* Be mindful of how often a search query is repeated \* Searches on page load are naturally loading every time the page loads \* Search results auto-update\[^6\]; you don't need to perform another query for updated results. \* Identical searches on the same page are only queried once, but queries in workflows are performed each time the workflow is executed. Consider using search results that have already been loaded when possible. Full article: \[Searches\](/help-guides/workload/optimizing-workload/optimization-checklist/searches.md) Workflows and actions Full article: \[Workflows and actions\](/help-guides/workload/optimizing-workload/optimization-checklist/workflows-and-actions.md) ### Number of actions Each action that interacts with the server may add some WU to the calculation. Additionally, more actions can increase the total size of your app’s code. While this doesn’t affect WU consumption, it can lead to slower page load performance. \* \*\*Complexity:\*\* look for ways to reduce the number of actions. ### Workflow complexity \*\*Complexity:\*\* look for dynamic expressions that are more complex than they need to. \* Containing nested searches or advanced filters. ### Workflow frequency Even a low-impact workflow can spend considerable amounts of workload if it is repeated frequently. \* \*\*Repetition:\*\* be mindful of using events like \*Page is loaded,\* \*Do every X seconds\* and potentially \*Do when condition is true,\* especially when they contain database operations such as searching or changing data. \* \*\*Repetition:\*\* for particularly resource-heavy operations, find ways to encourage users to run them less frequently. ### Working with lists Working with lists, such as \*Make changes to a list of things\* and \*Delete a list of things\* are of course sometimes necessary. Still, keep in mind that it manipulating a list of things consumes more workload than a single thing. \* \*\*Volume/repetition:\*\* avoid making frequent changes to a list of things. \* \*\*Repetition:\*\* consider using \[\*Make changes to a list of things\*\](#user-content-fn-7)\[^7\] instead of \[\*Schedule API workflow on a list\*\](#user-content-fn-8)\[^8\] and \[recursive workflows\](#user-content-fn-9)\[^9\] when possible. Backend workflows and API Full article: \[Backend workflows\](/help-guides/workload/optimizing-workload/optimization-checklist/backend-workflows.md) ### Schedule API workflow on a list vs recursive workflows These two methods of performing bulk operations can often produce the same outcome, while one consumes a lot of more WU than the other. \* \*\*Repetition:\*\* using recursive workflows forces Bubble to re-schedule the workflow a lot of times, whereas Schedule API workflow on a list will schedule all the workflows in one operation. In other words, Schedule API workflow on a list spends less WU and is the recommended method from a WU perspective. ### Bulk operations Bulk operations are sometimes necessary, but are among the most WU-intensive tasks you can give the server. \* \*\*Repetition:\*\* be mindful of how often you run a bulk operation. Optimally, they should be rare. \* \*\*Repetition:\*\* Smaller bulk operations can sometimes be more efficiently handled by \*Make changes to a list of things\*, rather than Schedule API workflow on a list/recursive workflows. \* \*\*Complexity/repetition:\*\* optimize bulk processes to not do more work than they absolutely need to. \* Look for actions that could be repeated just once (such as on the last cycle, as opposed to on every cycle) \* Pass lists as parameters, instead of performing the search query in every workflow \* Set up conditions to be as lightweight as possible. For example, a condition that includes \*Do a search for\* may consume an unnecessary amount of WU \### Database trigger events The database trigger event is a powerful feature for ensuring database integrity, but since they can trigger frequently, they can also potentially consume a significant amount of WU. \* \*\*Repetition:\*\* set up database triggers with conditions that ensures it doesn't trigger too frequently. \* \*\*Complexity:\*\* ensure that a database trigger event and its actions and conditions don't perform complex queries such as searches with \*:filtered\* and \*:advanced\* operators, and nested searches. \* \*\*Repetition:\*\* sometimes, database trigger events can be combined into one. This lets you perform the condition on the event only once, and may also make the actions inside more lightweight. ### API authentication API workflows and Data API endpoints that don't require authentication can be repeatedly accessed. \* \*\*Repetition:\*\* As a general rule, inbound API requests to your app should require authentication, to avoid anyone simply calling them repeatedly. \* \*\*Volume:\*\* avoid sending more data than you need via the Data API by setting up privacy rules and protect fields that should not be returned by the database. \[^1\]: User interaction in this context could mean requiring the user to click an element to initiate the search, instead of doing it automatically on page load. \[^2\]: Client-side conditions, such as \*Element is visible\* can be a lightweight way to stop data from loading immediately, and instead load when it's needed. \[^3\]: \*Nested search\* means a search that initiates one or more additional searches to finish. For example, by using a constraint with a dynamic expression that contains \*Do a search for\*. This can substantially increase both \*complexity\* and \*volume.\* \[^4\]: The workload calculation of data returned by the database takes both the \*number of things\* and \*number of bytes\* returned. As such, keep the number of things as low as possible, and avoid heavy fields, such as unstructured data. \[^5\]: Client-side redirects happen when the page is loaded, and then the user is redirected. Since the page needs to load first, Bubble will spend some WU on that process. Article series: \[Navigation\](/help-guides/logic/navigation.md) \[^6\]: Bubble sets up a web socket connection that pushes new data to the device whenever something changes in the database. This is taken care of automatically. \[^7\]: \*Make changes to a list of things\* is an action that makes changes to multiple things in one operation. Reference: \[Make changes to a list of things\](/core-resources/actions/data-things.md#make-changes-to-a-list-of-things) \[^8\]: \*Schedule API workflow on a list\* schedules a list of workflows that will execute once for each item in a list. Article: \[Bulk operations\](/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared.md) \[^9\]: \*Recursive workflows\* are workflows that schedule themselves at the end, in essence making it a loop. Article: \[Bulk operations\](/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database.md). # The database The database is the cornerstone of most applications. It handles all the \*dynamic\* data, meaning data that you and your users can create, change, view and delete as frequently as needed. The database works in tandem with your app's design to give your users the combination of being able to work with complex data efficiently, without being burdened by the mechanics of how it actually happens under the hood. Most of your users don't know how it works and indeed don't even know that it's there – they just know that the information they stored in your app yesterday is still there today for them to interact with. ![](https://manual.bubble.io/files/1L4sT6UBjqStUBgYo6Iw) Your app's user interface is all your users will ever see while the database rests underneath the stage silently doing its job. \## What is a database? When you hear the term \*database\*, you might imagine vast servers, intricate codes, and complex structures. But with Bubble, the idea of a database is made refreshingly simple and user-friendly. At its core, a database is a structured collection of data. Think of it as a digital library, where instead of books, you have data entries, and instead of shelves, you have tables or, in Bubble’s terminology, \*data types\*. Each data type can have several fields that store specific kinds of information. For instance, a data type \*User\* might have fields such as \*Name\*, \*Email\*, and \*Date of birth\*. Within Bubble, this database is visual and intuitive. Rather than writing SQL queries or scripts to manage the data, you interact with a clean, graphical interface. You can create new data types, add fields, or adjust relations between different data types with a few clicks. And while Bubble takes care of the heavy lifting in the background, ensuring that the data remains secure and retrievable, you can focus on designing the logic and flow of your application. For those familiar with traditional databases, Bubble's approach simplifies many of the complexities involved. There's no need to stress about database schemas, SQL syntax, or indexing. Instead, Bubble handles these technical aspects, allowing creators to focus on the logic and design of their app, making the process of integrating and utilizing a database far less daunting. The database comes with its own set of commands to create, manipulate and delete data. ![](https://manual.bubble.io/files/qwn1MdMOjjVVy7iJ1bk9) \## ## Communicating with the database When you and your users interact with your Bubble app, two computers are involved: \* The device that the user is accessing the app from (such as a laptop or cell phone) \* Bubble's server (located in a server park) Whenever an action is needed that involves the database, such as reading, writing or deleting data, that command is sent from the user's device to the server, where the job is completed and a confirmation and any requested information is sent back to the device. ![](https://manual.bubble.io/files/HTo5aRuFrUjcsTUhjohY) As such, working with data in your app is an ongoing stream of communication between the user's device and the Bubble server. This doesn't just happen on page load, but continually as the user provides your app with actions and input. Even for a single user, small packets of data can be sent back and forth several times per second. As the developer of the app, you can set it up to send all sorts of different commands to the server: \* Create things \* Make changes to and delete things \* Search for things and return the result as a list \* Find one specific Thing and return its content Any data sent between the user's device and the server is encrypted at all times, ensuring that it stays private. Let's say a user provides input about himself such as name and date of birth: when that data is being sent to the Bubble server, it's encrypted and can't be read by anyone else. It's also encrypted during storage on the server itself. What is database encryption? Encryption is a method used to protect information by converting it into an unreadable format. This ensures that even if unauthorized individuals or systems would manage to access the database, they won't be able to comprehend the actual data unless they possess the appropriate decryption key or method. Imagine your database as a diary. Instead of writing your secrets in plain English, you decide to use a special code only you understand. If someone were to find and read your diary, they wouldn't understand its contents without knowing how to decode your special code. Database encryption works on a similar principle, but with algorithms and cryptographic keys. Bubble automatically ensures the database is encrypted at all times. Encryption during rest and transit The data in and sent from the database can be in two states: \*\*Rest\*\* means when the data is stored on the server's hard drive. In this state the data is encrypted using the industry standard \[AES-256 encryption\](#user-content-fn-1)\[^1\]. \*\*Transit\*\* means when the data is moving from the server to the user's device through the interoptic cables that make up the internet. During this state the data is encrypted with the \[TLS protocol\](#user-content-fn-2)\[^2\], which ensures three important points: \* The data has been encrypted, rendering it unreadable in case of interception by unauthorized parties. \* The source of the data, i.e. the Bubble server, has been authenticated, which guarantees that the data originated from a verified source and not an imposter. \* The data's integrity has been maintained throughout its transmission, ensuring that it has not been tampered with or altered in any way during transit \### Privacy rules Privacy rules are rules that govern what users can access what data. It's the most important part of your database's security, and we strongly recommend that all apps that host any kind of private or sensitive data set up privacy rules to protect it. Article: \[Protecting data with privacy rules\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md) ## Data types and fields In the next article in the series, we'll look into how you create custom data types, and populate them with fields to store relevant information. Article: \[Data types and fields\](/help-guides/data/the-database/data-types-and-fields.md) ## Bubble database terminology | Term | Description | | --- | --- | | Constraint | A filter applied to a search to narrow down the results. For example, retrieving all products with a price less than $50. | | Data source | Defines where the data in an expression or element comes from. This is often a specific search (_Do a search for_) or direct reference to a type of data in the database (such as _Parent group's thing_). | | Data type | Represents a category of data (e.g., User, Product, Order). Similar to a table in traditional databases. | | Do a search for | The data source that retrieves specific data from the database based on certain constraints. | | Field | Attributes or properties within a Data Type (e.g., Email, Name, Price). Similar to columns in a table. | | List | A collection of things. For instance, a user might have a list of favorite products. A field can be set up to store one thing or a list of things. | | Privacy rule | Criteria that determine how data can be searched for, modified, or viewed based on user roles or other conditions. | | Repeating Group | A UI element in Bubble that displays a list of things from the database, allowing for dynamic rendering of data. | | Thing | An individual record or entry in the database. | \## Additional resources Technical information about the Bubble database \*\*Server\*\* The Bubble database is hosted on Amazon’s Relational Database Service (RDS) which is a part of Amazon Web Services. The database is encrypted using the industry standard \[AES-256 encryption\](#user-content-fn-1)\[^1\]. \*\*Database technology\*\* Bubble uses PostgreSQL – an open source database management system. In other words, we have not invented a new kind of database system, but use one that has been in development for decades and is thoroughly tested and audited for stability and security. This is one of the most widely used systems on the internet, and since it's based on the SQL standard (a very common database format), Bubble can communicate with other databases without worrying about compatibility. How the Bubble database is different from traditional databases Technically, Bubble uses the same technology as the majority of other web servers: SQL, and specifically PostgreSQL. Still, the way the database is visualized in the Bubble editor can be a bit confusing if you come from a traditional database background. The major difference is that Bubble \*\*automates the use of primary and foreign keys.\*\* When creating a relationship between two data types (tables), Bubble uses a custom data type field to represent a reference to another record in a different table. For example, let's say we have a "User" data type and a "Post" data type, and we want to create a relationship between them such that each post is associated with a user. In Bubble, we would create a field in the "Post" table with the data type "User", which would represent a reference to a user record in the "User" table. While Bubble doesn't expose the use of foreign keys to developers, database relationships still technically rely on them. The Unique ID field serves as the primary key for a record and is used to retrieve data, but this part of the process is hidden to make database setup and management easier for users without a database background. While you may have use for the foreign key in some select scenarios, you generally don't need to reference it in Bubble in the way that you may be used to in other environments. The quick tip YouTube video below shows how this works visually: Video lesson: \[How to add a data type as a custom field\](https://www.youtube.com/watch?v=4txlG9nwr1E) \## Other ways to learn Video lessons \* \[The data tab\](https://www.youtube.com/watch?v=z0L8vFsCwkk) \* \[Creating the data structure\](https://www.youtube.com/watch?v=2NO1ET1bMLM) Articles \* \*\*Planning your database structure\*\*\\ This article takes an introductory look at how to plan the database structure for your app.\\ \\ Article: \[Planning your database structure\](/help-guides/getting-started/building-your-first-app/database-structure.md) \* \*\*Maintaining your database\*\*\\ Keeping your database clean and up-to-date helps your app run efficiently and makes it easier for you as a developer to stay on top of the data. Check out our article series below for different ways of maintaining your database.\\ \\ Article series: \[Maintaining your database\](/help-guides/maintaining-an-application/database-maintenance.md) \[^1\]: \*AES-256 encryption\* is an encryption algorithm that uses a 256-bit key to encrypt and decrypt data.\\ \\ It's a widely used and highly secure encryption standard that is approved by the US government for protecting classified information. \[^2\]: TLS (Transport Layer Security) is a protocol used to secure data sent over the internet. It's the most widely used protocol used with HTTP.\\ \\ It ensures that the data is private and can't be seen by someone who is not supposed to see it. \\ External link: \[TLS on Wikipedia\](https://en.wikipedia.org/wiki/Transport\_Layer\_Security) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/reusable-elements.md). # Reusable Elements Reusable elements are a way to create groups of elements that can be used in more than one place. For example, if you have created a navigation toolbar, you may want that same toolbar to be visible on multiple pages, and only have to make changes to it once to update all of them. ![](https://manual.bubble.io/files/DV4ToNrpFt6WxWZhIoR7) The navigation toolbar on www.bubble.io (marked in red) is a typical use case for reusable elements. This toolbar and all its buttons and workflows can be re-used in as many places as you need. Reusable elements contain elements, workflows\[^1\] and \[custom states\](#user-content-fn-2)\[^2\] and each instance of the reusable element behaves in isolation: in other words, what happens in one reusable element has no effect on other copies of the same reusable element, even if they're on the same page. ### Examples of reusable elements Reusable elements can be used for any collection of elements/workflows that you want to re-use across your app. To further illustrate what reusable elements are often used for, let's look at a few examples: 1. \*\*Navigation Bar\*\*: This is usually placed at the top of every page and provides links to the main sections of your app. 2. \*\*Footer\*\*: Like the navigation bar, a footer is a consistent element placed at the bottom of each page, containing information such as copyright notices, contact details, and additional links. 3. \*\*Login/Signup Form\*\*: forms reused across different pages for user authentication. 4. \*\*Search Bar\*\*: If your app includes a search function, you may want that feature to be present on multiple pages. 5. \*\*Buttons\*\*: Call to action (CTA) buttons like "Sign Up", "Buy Now", or "Learn More" can be standardized and used throughout your application. 6. \*\*Sidebar Menu\*\*: a sidebar menu may be present on multiple pages for navigation. 7. \*\*Pop-up Modals\*\*: Reusable pop-up windows for things like confirmation messages or user prompts. 8. \*\*Contact Forms\*\*: Standardized forms for user inquiries. 9. \*\*Data Cards\*\*: Card lists showing stuff like user profiles, eCommerce products and tourist destinations 10. \*\*Error Messages\*\*: Standardized error messages can be used across different scenarios and pages. ### Why use reusable elements? There are many reasons as to why you would want to use them: #### Speeding up development and maintenance Any change that you make to a reusable element is instantly visible across all instances of it. Instead of making changes in a lot of different places across your app, you can centralize the management of key features into one element. #### Maintaining consistency By using reusable elements for designs that are used frequently, like forms, pop-ups, and footers, you give your app a consistent look and cut down on the work you have to do to maintain it. #### Isolating work in the Bubble editor If a page has lots of elements and workflows, putting some parts in reusable elements can make it easier to focus. This way, there are fewer things to keep track of on the screen at the same time. #### Performance Reusable elements keep your app lightweight and performant, since its content only needs to be loaded once. #### Reusing workflows Reusable elements can also be used to store workflows that you use in multiple places across your app. In fact, a reusable element doesn't have to contain any visible elements – you can use it to simply \[trigger workflows\](#user-content-fn-3)\[^3\]. ## Reusable element types Reusable elements can be created as one of the following container types: \* \*\*Group:\*\* used to contain other elements \* \*\*Popup:\*\* used to contain other elements and hover centered above all other content on the page \* \*\*Floating group\*\*: used to contain other elements and hover near an edge of the screen (such as a navigation toolbar) {% hint style="info" %} Each of these types behave in the same way that their container element counterparts do. You can read more about the different types in our article series on containers. Article series: \[Containers\](/help-guides/design/elements/web-app/containers.md) {% endhint %} ## Creating reusable elements [](https://manual.bubble.io/help-guides/design/elements/reusable-elements.md#creating-and-using-reusable-elements) There are multiple ways to create new reusable elements: ### The page menu To create a new blank reusable element: 1. Open the page navigation menu in the upper left corner of the Bubble editor 2. Scroll to the \*Reusable elements\* section 3. Click \*Add a new reusable element\* ![](https://manual.bubble.io/files/Is5YBMCCfWZhQ69g3Mk6) \### The element tree You can also create a blank reusable element using the \[element tree\](#user-content-fn-4)\[^4\]: 1. Navigate to the \*Design\* tab of the Bubble editor 2. In the element tree, scroll down to the \*Reusable elements\* section 3. Click \*New reusable\* ![](https://manual.bubble.io/files/KNODr4rnjjnkMWAjVSvM) \### Converting existing element(s) You can also convert one or more elements on a page into a reusable element: \* If you select a container element, a new reusable element will be created, containing the child elements inside of the original container \* If you select one or more elements, a new reusable element will be created containing those elements \* The original elements on the page will not be deleted or replaced with the newly created reusable element \* Any workflows associated with the selected elements will be copied into the new reusable element, but may break if they lose access to original references To convert existing containers or elements into a reusable, do the following: 1. Select one or more elements on the page 2. Right-click the mouse on one of the selected elements or click the \*Edit\* menu at the top of the screen 3. Select \*Convert to a reusable element\* A new reusable element will be created and you will be taken to that element in the editor. {% embed url="" %} Our Academy course includes how to convert groups into reusable elements {% endembed %} ## Passing data to and from a reusable element In many cases you'll need to pass data to and from a reusable element. There are a few different ways to do this: ### Using the data source When a reusable element has a \*Type of content\* set and it's been placed on the page, you can set a data source for it. For example, if the reusable element has a data type called \*Product\* as its type of content, you can set any product in your database as the data source on the page where the reusable element is placed. This method works \*\*one\*\* direction: passing data from the parent to the reusable element. ### The Display data action The \*Display data\* action can be used to send any kind of data to the reusable element, as long as it matches the \*Type of content\* set on that element. For example, if you have a form to edit someone's user profile, you can send the relevant user data to the reusable element using the display data action. This method works \*\*both\*\* directions: passing data from the parent to the reusable element or vice versa. ### Custom states You can also pass data from the parent page to a reusable element using the \*Set state of an element\* action: 1. Set up the relevant custom state with the correct data type on the reusable element. The custom state needs to be create on the parent reusable element, not any of its children 2. Use the \*Set state of an element\* action to populate the custom state with data This method works in \*\*both\*\* directions: passing data from the parent to the reusable element or vice versa. ### URL parameters \[URL parameters\](#user-content-fn-5)\[^5\] do not pass data directly into a reusable element per sé, but since they can be read and manipulated by both the page and any reusable element within that page, they can be a useful way to share information between the two. This method works in \*\*both\*\* directions: passing data from the parent to the reusable element or vice versa. ### Reusable element properties Reusable elements also come with customizable properties that can be set up to share dynamic data between it and other elements such as the parent page. ![](https://manual.bubble.io/files/xJi80pfpgXACqC9qZ19l) Properties can be populated by a default value assigned on the reusable element itself or from the parent. Any new property that you add will be assigned a field on each instance of that reusable element placed on a page, and they can be individually assigned data. The data populated in the fields are prioritized in order of 1) data assigned from the parent, and 2) default data, meaning that the data from the parent element takes priority. Unlike custom states (that require an action to be assigned a value), reusable element properties let you use dynamic data. Unlike the \*Type of content\* field that all resuable elements have, you can set up as many different properties as you need, each with individual data types. #### Reusable element property types You set select one of three types for any new property. \* \*\*Dynamic value\*\* lets you assign any \[basic data type\](#user-content-fn-6)\[^6\] or \[custom data type\](#user-content-fn-7)\[^7\] that you can then populate using a dynamic expression, such as a database search, an option set or something else. This is useful for passing different types of data dynamically to and from the reusable element. \* \*\*Color picker\*\* lets you assign a \[hex color code\](#user-content-fn-8)\[^8\] or a saved \[color variable\](#user-content-fn-9)\[^9\]. This is useful for dynamically passing a color value to the reusable element. You can then use that color to communicate something to your users, such as a different background, button or text color. \* \*\*Checkbox\*\* is a simple way to pass a \[yes/no value\](#user-content-fn-10)\[^10\] to or from the reusable. This method works in \*\*both\*\* directions: passing data from the parent to the reusable element or vice versa. #### Reusable element property descriptions {% hint style="info" %} This feature is only available in the new property editor. {% endhint %} You can add a description to each property you set up on a reusable element, to make it easier to differentiate multiple properties, or remember what a specific property is for. ![](https://manual.bubble.io/files/6SmrKztXzaC9AiaFCwMr) \#### Passing data both ways Let's revisit the point that reusable element properties can pass data not only \*to\* a reusable element, but \*from\* the element to the parent. This value can then be read by any element on the parent, allowing you to pass dynamic data to other elements on that page without having to use actions. The fact that you can keep dynamic values updated automatically between a reusable element and its parent opens up for scenarios where you can use the reusable element to store different variables that you use elsewhere on the page and manage from one place. ## Adding an existing reusable element to a page To add an existing reusable element to a page, navigate to the \*Reusable elements\* section of the \[element tree\](#user-content-fn-4)\[^4\], click the element that you want to add, and then click on the area where you want to add it to a page. ![](https://manual.bubble.io/files/ze6mVxbkBoEZIl1nCn13) Every reusable element you create will be added to the _Reusable element_ section of the element tree. \## Modifying dimensions Reusable elements' dimensions are defined when you edit the element itself. However, these elements are responsive (except if you make them fixed width), and if you need to resize them in the destination page you can do so, and the content will adjust as defined with the responsive settings of the inner elements. ## Other ways to learn Video lessons \* \[Converting elements to reusable elements\](https://www.youtube.com/watch?v=3GEH\_hCaAWk) \* \[How to build a responsive navigation bar\](https://www.youtube.com/watch?v=3lUlmTZ\_IQo) \[^1\]: The collection of an \*event\* and a set of \*actions\* in Bubble is called a \*workflow.\*\\ \\ The event represents a trigger (such as a button click), and the actions represent what should happen upon triggering (such as saving a thing in the database).\\ \\ Article: \[Workflows\](/help-guides/logic/workflows.md) \[^2\]: \*Custom states\* are variables that you can save on any element on the page, including the page itself. They let you store data temporarily that is reset when the page is reloaded.\\ \\ Article: \[Custom states\](/help-guides/data/temporary-data/custom-states.md) \[^3\]: To trigger a workflow from a reusable element you use the \*Trigger a custom event from a reusable element\* action.\\ \\ Reference: \[Trigger a custom event from a reusable element\](/core-resources/actions/custom.md#trigger-a-custom-event-from-a-reusable-element) \[^4\]: The \*element tree\* displays all the elements on the current page organized into parent-child relationships. Article: \[The element tree\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-element-tree.md) Article series: \[The element hierarchy\](/help-guides/design/elements/the-element-hierarchy.md) \[^5\]: A \*URL parameter\* is a piece of information that you place in the browser's URL. They follow a key-value-pair\\\[^11\] structure and can hold many different types of data.\\ \\ Article: \[URL parameters\](/help-guides/data/temporary-data/url-parameters.md) \[^6\]: These are Bubble's built-in types such as text, numbers, dates, yes/no, etc. \[^7\]: These are the data types that you have created for your app specifically, be it products, articles or something else. They can be given any name and assigned any number of fields. Article: \[The database\](/help-guides/data/the-database.md) \[^8\]: A \*hex color code\* is a six-digit alphanumeric code that represent colors. Each hex color code begins with a hash sign (#) followed by six characters divided into three pairs, each representing the intensity of red, green, and blue in the color.\\ \\ For example, #000000 represents no color intensity in any of the red, green, or blue channels, resulting in the color black. \[^9\]: Color variables let you save a palette of colors that you can apply throughout your Bubble app and maintain from one place. Article: \[Color variables\](/help-guides/design/variables-and-styles/color-variables.md) \[^10\]: Yes/no is one of Bubble's basic data types, and simply represents a true or false statement.\\ \\ If you have a traditional coding background, this is similar to a boolean. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/reusable-elements.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms.md). # Input forms Input forms are the elements that you use to collect information from your users. They can be used for a simple checkbox or combined into complex forms. {% hint style="info" %} The articles in this section cover Bubble's built-in input elements. There are also a wide range of plugins in the \[plugin store\](https://bubble.io/plugins) that offer new ways of accepting user input. {% endhint %} ## Different kinds of input User input can mean many things, and most applications accept a wide range of different categories of input from their users. Even single forms are usually made up of different types of inputs that makes it easy for your users to understand what kind of data they're asked to provide. ![](https://manual.bubble.io/files/X0JLOEx4Tmcu2k0QsY5w) A simple signup form like the one above combines several different categories of input forms to make the UX easy for your users to understand and to prepare the data for processing – such as saving it in the database. \### Text and numbers Text and number inputs allow users to provide text ranging from short, \[structured data\](#user-content-fn-1)\[^1\] like an email address, an order number or a name to long, \[unstructured data\](#user-content-fn-2)\[^2\] like a blog post or product description. Text can be formatted (rich text) or unformatted (plain text). Article: \[Text and number elements\](/help-guides/design/elements/web-app/input-forms/text-and-numbers.md) ### Dates and time Date and time inputs allow users to provide date and time values. Some inputs let users type the information in, others are set up to let users pick a date from a calendar and a time from a timepicker. Article: \[Dates and time elements\](/help-guides/design/elements/web-app/input-forms/dates-and-time.md) ### File uploads File uploads are a third category of input that allows users to upload any kind of file to your application. Article: \[File uploads\](/help-guides/design/elements/web-app/input-forms/file-uploads.md) ### Selection controls Selection controls are input elements that let you set up pre-defined options for your users to select from. This allows you to restrict the available choices, ranging from simple yes/no answers to selecting preset text/numerical values and dynamic content from your app's database. This includes: \* Checkboxes \* Radio buttons \* Dropdown lists Article: \[Selection control\](/help-guides/design/elements/web-app/input-forms/selection-controls.md) ## Triggering a workflow when an input is changed You can trigger a workflow whenever the value of a specific input form is changed. ## Input forms and security With the \`This input is disabled\` property, you can disable an input form. Disabling an input makes it read-only in the UI, but it's not a secure way to prevent edits. Because it's handled client-side, users can still tamper with it. Use server-side protections like privacy rules, workflow conditions, or backend workflows to enforce security. Article series: \[Security\](/help-guides/security.md)\\ Article: \[Client-side and server-side\](/help-guides/security/client-side-and-server-side.md) Video lessons \* \[How to trigger workflows from input changes\](https://www.youtube.com/watch?v=mDEVJLujlkQ) \[^1\]: \*Structured data\* is information that is organized in a consistent format. For example, a phone book would typically contain structured data like First name, last name and email.\\ \\ \\&#xNAN;\*Unstructured data\* is data that is more inconsistent and often longer. Examples include news articles, blog posts and the contents of en email. \[^2\]: \*Unstructured data\* is data that doesn't have a predictable format. Examples include news articles, blog posts and the contents of en email. \\ \\&#xNAN;\*Structured data\* is information that is organized in a consistent format. For example, a phone book would typically contain structured data like First name, last name and email. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/web-app/input-forms.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md). # The debugger When encountering unexpected behavior, the debugger comes in handy for closely examining each step of a workflow or the details of an element as the app is being used. The debugger primarily serves two key purposes: \* \*\*Run workflows action-by-action\*\* and check data (such as the result of a search) related to each step \* \*\*Inspect the elements on the page\*\* to check their attributes, conditions and associated data The debugger does not have any visible parts in the Bubble editor, but is visible when you run your app in Development. ## Enabling and disabling the debugger [](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md#activating-the-debugger) When you click \*Preview\* to see your app in run-mode, the debugger is automatically activated. If you want to enable or disable it, you simply have to change the \[URL parameter\](#user-content-fn-1)\[^1\] \*debug\\\_mode\*. When the debugger is enabled, you will see the parameter in the URL: \`\`\` debug\_mode=true \`\`\` A full URL will look like the following: \`\`\` https://my-bubble-application.bubbleapps.io/version-test?debug\_mode=true \`\`\` ...or if you have multiple URL parameters: {% code overflow="wrap" %} \`\`\` https://my-bubble-application.bubbleapps.io/version-test?parameter=key&debug\_mode=true \`\`\` {% endcode %} The debugger is meant for desktop use and is not designed to work on mobile. To disable the debugger, simply remove the parameter, or set its value to \*false\*. ## Using the debugger When the debugger is active, you will see a bar at the bottom of the screen when you preview your app: ![](https://manual.bubble.io/files/sjQKv13NqUtESw1hqric) When the debugger is active you will see it as a bar at the bottom of the screen. {% hint style="info" %} When the debugger is enabled, Bubble automatically adds space at the bottom of the page. This is only visible in debugging mode and not to your Live users. {% endhint %} ![](https://manual.bubble.io/files/nqRCaYz9P5SoZ3MKrThc) \* The \*\*left-hand side\*\* shows the different controllers for inspecting \*\*workflows\*\* \* The \*\*right-hand side\*\* shows the controls for inspecting \*\*elements\*\* ### Workflows The left side of the Debugger is the Workflow Debugger. You can see three buttons that control how the debugger behaves when a workflow is being triggered. Three modes are possible: 1. \*\*Normal\*\* mode runs workflows without interruption. 2. \*\*Slow\*\* mode runs workflows with a a one-second pause between each action 3. \*\*Step-by-step\*\*' mode lets you control the execution of the workflow by pausing between each action until you click \*Run next\* (only visible when step-by-step mode is enabled) Step-by-step is the most widely used debugger mode, as it gives you complete control over each action step, allowing you to progress at your own pace. When the mode is active, Bubble will work for a workflow to be triggered by an event. As soon as that happens, it will pause on the event itself so that you can check what triggered it and any associated data. ![](https://manual.bubble.io/files/SEUfw2M45ThXP3uJLF4j) The first step the debugger will show is the event that triggered the workflow. In this case it was a button-click. The step we are currently inspecting is marked in grey, and the next step is in white. Clicking \*Run next\* will move on to the the next step: the \*Create a new Product\* action: ![](https://manual.bubble.io/files/OMqa6GlB8lCZy4EwpC4O) Note the numbers in the screenshot above: 1. In this example, we inspect the \*Name\* field of the Product we are creating, where the value "T-shirt" is displayed. By clicking the value, we can trace the data source from which it is derived. 2. After clicking the value, we can see its data source on the right-hand side: in this example the value came from an input form called \*Input Product name\*. By pausing at each step and examining the details of each action, you can verify if the data yields the anticipated values and is saved as intended. {% hint style="info" %} The debugger status is saved when the page is refreshed. If a workflow navigates to a different page or triggers a page refresh, the resuming workflow will execute subsequent actions in the same mode. {% endhint %} ### Adding breakpoints [](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md#adding-breakpoints) When working on complex pages with numerous workflows, the step-by-step mode might not be ideal since it stops too frequently. If you want to investigate a specific workflow, event, or action, you can add a breakpoint that activates the debugger in step-by-step mode when that event or action is executed. ![](https://manual.bubble.io/files/wIVK30WEYWmgfqNACILY) Breakpoints are added in the workflow editor, either on an event or an action. As soon as Bubble encounters that event or action, it will pause and enable step-by-step mode from that point forward. {% hint style="info" %} Note that this setting only has an effect when the debugger is active (meaning debug\\\_mode=true appears in the URL) and will not influence how your application runs in Live. {% endhint %} ## Inspecting elements Sometimes, you may need to determine why an element is displayed in a specific manner, particularly when using conditions or displaying data. The debugger lets you select an element on the page and view the list of conditions and fields, along with their values. ![](https://manual.bubble.io/files/qJKoWIWgiYi6tsTKunlK) First, to enable Inspect mode, click the \*Inspect\* button in the bottom right corner. There are two ways to select an element to inspect: \* You can click the element on the page (workflows will not trigger when you are in inspect mode) \* You can use the dropdown list next to the \*Inspect\* button and search for/select the element from there (this is useful for elements that are invisible). ### Understanding expression evaluations [](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md#understanding-expressions-evaluations) When an element is selected, you can start to evaluate its properties, conditions and expressions. In the example below, we have selected the \*Create Product\* button. ![](https://manual.bubble.io/files/uhfwPfakSpbS0jG1ufEZ) Conditions are displayed in a separate list under the header \*Conditions\*. If they are in red color, it means the condition does \*not\* return true. If the condition is true, it will be displayed in a green color. ### Digging into expressions By clicking the relevant expression\[^2\], you can take a closer look at each step and how it evaluates. ![](https://manual.bubble.io/files/vw6X2RsUuf0GjNdXHdQ1) In the example above, we can check the last part of the expression: \*is logged in\*. We can see that this part of the expression returns a \*no\*. If we click the first part of the expression, we can see the parameters associated with the data source \*Current user:\* ![](https://manual.bubble.io/files/VD5rfAZDvkFLLWQsbR30) Any expression can be inspected in this way. Most fields on this user are empty since they are logged out, but you can see the unique ID and Created/Modified date that Bubble generates for all users who visit your app. Each expression allows you to inspect every data source, operator and comparison. Any sub-expressions are also accessible by clicking them. ## Run-mode execution errors The debugger also lets you identify run-mode execution errors, such as when an API call to a service returns an error due to a missing parameter. When a workflow or element encounters an error, the debugger icon turns red and becomes clickable. Clicking on it reveals the list of errors. When you encounter an issue, particularly when using external services through plugins, checking for execution errors in the debugger should be one of your initial troubleshooting steps. ![](https://manual.bubble.io/files/5zcZRHnVcg1WHLlZdEfd) \## Other ways to learn Video lessons \* \[How to use the debugger\](https://youtu.be/UNtXp\_VDssk) \[^1\]: A \*URL parameter\* is a piece of information added to the page's URL after a question mark (?).\\ \\ It can be used to store data and for navigation. Article: \[Navigation\](/help-guides/logic/navigation.md) \[^2\]: \*Expressions\* are dynamic pieces of data or calculations that are used within elements, workflows, or conditions to define values, set up booleans, or manipulate data. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/searches.md). # Searches One aspect that often contributes to workload\[^1\] consumption is the use of database searches via the \[\*\`Do a search for\`\*\](#user-content-fn-2)\[^2\] \[data source\](#user-content-fn-3)\[^3\]. A search operation is not in itself a particularly heavy operation, but can typically consume higher workload if the search: \* Returns a high volume of data \* Is particularly complex \* Is repeated frequently These three points can sometimes lead to slowing down the query itself. In some cases, this can be noticeable to your users, and can be detrimental to your app's user experience. Sometimes, complex queries are needed – it's simply a part of the work your app is doing and cannot be avoided – other times they can be tweaked to be more efficient or even removed altogether. In this article series we'll dive into some of the different aspects of searches and how the affect WU\[^4\]. ## What is a database search? {% hint style="info" %} If you are new to databases, we have an entire section dedicated to the database is and what it does. We recommend reading this first to know the essentials if you are unfamiliar with this part of Bubble. Article series: \[The database\](/help-guides/data/the-database.md) {% endhint %} Let's first look at what a database search is from a WU perspective. Database searches are a data source, meaning that they are a place from which Bubble can pull data to use in your app, such as populating a repeating group or table element. ### Dynamic expressions and WU Database searches are built using \[dynamic expressions\](#user-content-fn-5)\[^5\]. They are highly flexible, giving you as the developer the freedom to set them up to serve almost any purpose – but that flexibility also means that you are free to set up searches that are not optimized for performance and WU consumption. Two main points affect search WU consumption: 1. The \*\*volume of data returned by the database\*\*: For example: 1. \*\*Records in a repeating group\*\*: if you load an unusually high number of things into a repeating group, the amount of data returned by the database will increase. 2. \*\*Data saved in each field\*\*: if each thing contains a high volume of text data, such as long articles or blog post, and especially if this is combined with a high number of records, the amount of data returned by the database will increase. 2. \*\*The complexity of the dynamic expressions\*\* can also increase the server load. A search can be made more complex by adding advanced filters. Keep in mind also that different steps in an expression can make up separate calculations. For example, if you set up a constraint in a search that itself contains another search, you may be multiplying the number of searches ### How it is calculated Earlier in this series, we described the \[\*theme park entry ticket metaphor\*\](/help-guides/workload/understanding-workload/the-workload-calculation.md). The \[WU activity table\](#user-content-fn-6)\[^6\] gives you an overview of the entry ticket cost of performing a search, and from there, additional work that you give the server is added to that base cost. | Operation | WU | Calculated | | --- | --- | --- | | Database search | 0.3 | Per search operation | | Data returned from database | 0.000003 | Per byte returned | | Results | 0.015 | Per record returned | | Joined results | 0.015 | Per joined record returned
(e.g. Current Cell’s User’s **Team**) | \## The volume returned by the database The total volume of your database does not increase WU consumption in a search. For example, a search spanning 100 records will spend the same amount as a search spanning 10,000 records. However, the final volume of data returned from the database has a preset WU cost. For example, product descriptions, blog posts and articles can contain more data than names, phone numbers and emails. As such, the “weight” of a single thing, combined with the number of things can increase volume of data returned (which is a part of the WU equation), but neither variable affects the cost of the search process itself. It's worth remembering that the cost per character is very low, but you can stop Bubble from sending more data than you intended by saving less data on each record, stopping fields from being sent by use of privacy rules and avoiding downloading a high number of things on page load. ## What is search complexity? The second part of the equation is the complexity of the dynamic expression that makes up the search. To understand what makes a search complex, we need to look briefly into how a search is actually performed. In simple terms, a database search works by eliminating records that don’t match your constraints. For example, if your database contains 100,000 records and 80,000 of them don’t match a specific constraint, Bubble can exclude those 80,000 from the potential “candidates.” This means that Bubble can quickly rule out large portions of the database based on the constraints, using techniques like indexing to speed up the process on the backend. For instance, if your app frequently searches for products by a number field (such as a price), indexing allows us to arrange a table where products are sorted by their price. This makes it easier and quicker to eliminate non-matching records during the search, since the sorting allows us to "cut" the list at a point where the price is lower than 50 (see the screenshot below). ![](https://manual.bubble.io/files/Yj7D4s2cV8TBlAphh3ct) Most searches are completed through a process of elimination; whatever _doesn't_ match constraints is removed in chunks. This is a part of the database’s inherent functionality. It’s handled automatically and does not consume additional WU. #### Advanced filters The method described above is how most searches in Bubble are performed. However, it’s possible to create a more complex search by adding filters that require Bubble to process each row of data individually, rather than eliminating candidates in bulk. In those cases, it’s technically not the original query that spends more WU, but potentially additional queries that each incur their own WU costs.This happens when you add advanced filters that forces Bubble to do processing on each row of the data. Take a look at the expression below: ![](https://manual.bubble.io/files/ATxpe3Ygv9jxIyi4vXvP) The _:filtered_ operator can sometimes drastically decrease the efficiency of a search, both slowing it down and increasing WU consumption. Click screenshot to enlarge. The \`:filtered\` operator can sometimes drastically decrease the efficiency of a search, both slowing it down and increasing WU consumption. Click the screenshot to enlarge. In the example above, it might seem like you’re performing a single search, but in reality, you could be performing one search per row of the initial search results. The expression in the screenshot is searching for products that match the average price of all products within the same category. First, the \`Do a search for\` operation matches 1,000 products, and then Bubble applies the filtering. This means Bubble is not performing one search, but potentially 1,001 searches: a drastic increase that consumes a significant amount of workload and slows down the search process. What could we do instead? \* Here’s a clean, proofread version with the typo fixed and everything else left intact: If you can, try to avoid using the \`:filtered\` operator (and especially with advanced constraints), and instead rely on constraints that don’t in themselves initiate a second query. If they contain simple, non-dynamic constraints, Bubble will attempt to combine them into a single query, but when adding the \`:advanced\` operator in particular, you may unknowingly make the query more complex. \* Instead of performing a search every time we want to know a \*Category's\* average price, we could save the average price on each \*Category\* in a number field. This way, we could set up a dynamic expression that checks a \*This\* \*Product's Categories' Average price\* (see screenshot below). \* Consider whether there are even simpler ways to set up a search with similar results, and if the search is "nice to have" or necessary. \* You can also save the results of the search as a list, to avoid having to perform the query every time a user requests it. For this method, you'll need to develop your app to keep the list up to date, as lists don't automatically update. Also, lists can hold a maximum of 10,000 things. ![](https://manual.bubble.io/files/0ldzGdoliYQAYdA804Dc) By storing the average price in a separate _number_ field on the _Category_ data type, we can avoid performing as many searches as in the first example. The example above still requires Bubble to check the price of each Product in the search against its category, but we avoid performing multiple searches to calculate the average. This would require you to keep the average price on a Category up to date. You can ensure this by using \[database trigger events\](#user-content-fn-7)\[^7\] whenever a Product's price changes for example. ## Nested searches Nested searches are a common source of high WU consumption. Let's say that you are loading a list of client companies in a CRM and displaying the result in a repeating group. Two data types are used here: \* Company \* Employee (connected to a Company) In each row, you also search for and count the number of employees in each company, looking something like the table below: | Company | Employees | | --- | --- | | Company 1 | 1500 | | Company 2 | 2000 | | Company 3 | 800 | How many searches are performed in this example? You may think one, since the list is showing one list of companies. But the actual number is four: one search for companies, and then three searches/counting of the employees in each row. In this example, we're showing only three rows, but if this were to grow to hundreds of rows, you could potentially be performing hundreds of searches every single time the page loads: this can quickly lead to an overconsumption of workload. A possible solution to this is to instead save the number of employees in a number field on each company, and update it each time an employee is added or removed. It's a bit more work for you as the developer, but can drastically reduce the work for the server. ## Sending the data When a search is complete, the database returns the results. The amount of data being sent can vary dramatically, depending on how much data the data type contains (the "blog post" vs "first name" example), how many things to send and any operators that you add to the search. For example, downloading a list of 1,000 blog posts to a repeating group (even if you are only \*displaying\* the title of the post) can mean that Bubble has to send a significant amount of data, whereas if you instead use an aggregation operator such as \`:count\` or \`:average\`, Bubble only returns a number, which is an insignificant amount of data almost regardless of the number. It's important to be aware that Bubble sends \*all\* data saved on a thing when a thing is queried, and not just those that are displayed on-screen. The exception is fields that are protected with \[privacy rules\](#user-content-fn-8)\[^8\] that the current user does not match – that data never leaves the server. Knowing this, we can tailor our database to download less data: \* Consider what data is needed on your data type. Sometimes fields are added that do not add to the overall user experience or general quality of the app \* Also consider the number of things you need to download. You can avoid downloading too much data by setting up repeating groups that load as the user scrolls, use pagination or simply reduce the number of things overall. \* In some cases, it makes sense to split data types into separate types where one is specialized for search results, and the other contains the data. This is often referred to as a \*satellite data type\* in the Bubble community. As you plan your database, we again encourage you to not put emphasis only on WU. The cost of sending data is very low, and you should balance the optimization process with deadlines, app complexity and user experience. ## Search updates Whenever \[\`Do a search for\`\](#user-content-fn-9)\[^9\] is used as a data source for an element, Bubble maintains a web socket connection with the database as long as the page is open and the device is connected to the internet. This ensures that any changes in the database (even if made by another user) are automatically updated in the search results on the page. In other words, there is no need to manually refresh a search query; it updates automatically. The exception to this is when the initial fetch happens through a workflow\[^10\]: in that case, the results will not update automatically and will require another workflow to refresh the data. ## FAQ: Database searches and WU #### If I perform an identical search multiple times on the same page, do they all add to WU? Bubble is set up to not process a search query more than one time. In other words, if you perform the same identical search in two different places on the same page, the search will only be performed once. If the queries are \*not\* identical (such as one having an extra constraint), they will be processed separately. Note that if you perform that search in a \*workflow\*, the query will be repeated. #### If a search is performed, and then a change is made in the database that updates the results, is the query performed all over again? The results from a database search is dynamic in the sense that any change made to the database by any user is immediately visible in the app of all other users. However, this doesn't mean that the entire query has to be re-processed. Bubble only sends the necessary updated data, making the process very lightweight. You can see the specific cost of updating data on the page in the \[WU activity table\](#user-content-fn-6)\[^6\]. If you'd still like to avoid this, you can use the \[\`:make static\`\](#user-content-fn-11)\[^11\] operator to save the list without the dynamic connection to the database. While there are scenarios where this approach makes sense, we'd generally discourage using this to save WU, as it can lead to data inconsistencies in your app. #### If I use the "Current user" data source, will it consume WU? Any information on the Current user is downloaded when the page loads, regardless of whether you reference this anywhere on the page. This includes all fields saved on that user, except for those that the current user is not allowed to see as a result of privacy rules. Note that linked data types, such as \`Current User's Company's name\` may still consume a tiny bit of WU to load when you reference it, as it's only loaded when needed. #### If a \*Make changes to a thing\* has a condition, which uses a search that is used in the make changes action itself too, will we be charged for search twice? Generally, Bubble doesn't perform a search more than once, as longs as they are identical. Note that this applies to elements, while \`Do a search for\` performed in a workflow will be repeated each time that condition or action is executed. #### If I search for data and load it into a repeating group on one page, will Bubble cache the result so that the query doesn't need to be performed a second time when I navigate to a second page? Bubble searches are dynamic, and always kept up to date with new information in the database. As such, every time \`Do a search for\` \*is\* used on a new page, the query will be processed as a new search. This also applies if the current page is refreshed. #### If I use the \*Go to Page\* action and remain on the same page (such as updating URL parameters), will searches be queried again? No, as long as you stay on the same page, searches on the page will not be repeated. Keep in mind that searches in \*workflows\* are repeated each time they are executed, and the \*Go to page\* action may lead to workflows running more times than you intended. #### Does Bubble perform indexing on the database to make searches as efficient as possible? Yes, with some caveats. Database indexing can greatly improve the efficiency of a search, but only when the database volume is large enough. Bubble processes different data types and queries intelligently to index the database as needed. This can sometimes lead to varying search speed, depending on whether the database has been indexed for a specific query, but it does not affect WU. \[^1\]: \*Workload\* is the metric that Bubble uses to calculate and display how much work the Bubble server has to do to keep your app running. It's often abbreviated to WU (Workload Unit).\\ \\ Article series: \[Pricing and workload\](/account-and-marketplace/account-and-billing/pricing-plans.md) \[^2\]: \*Do a search for\* is the data source in Bubble that searches your app's database for specific information using dynamic constraints, and then downloads the data to the user's device. Reference: \[Do a search for\](/core-resources/data/data-sources.md#do-a-search-for)\\ Article series: \[The database\](/help-guides/data/the-database.md) \[^3\]: A \*data source\* is any place from which Bubble can fetch data, such as the database, the current user, the current time or an external API. They are used in dynamic expressions. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md)\\ Reference: \[Data sources\](/core-resources/data/data-sources.md) \[^4\]: \*WU\* is an abbreviation for Workload Unit. This is the metric that Bubble uses to calculate and display how much work the Bubble server has to do to keep your app running.\\ \\ Article series: \[Pricing and workload\](/account-and-marketplace/account-and-billing/pricing-plans.md) \[^5\]: \*Dynamic expressions\* are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. \\ Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) \[^6\]: WU is calculated by assigning specific activities different "entry ticket" costs. You can see the exact values in the article below.\\ \\ Article section: \[WU activity types and cost\](/help-guides/workload/understanding-workload/what-contributes-to-workload.md#what-does-an-activity-cost-in-wu) \[^7\]: \*Database trigger events\* are a type of backend event that triggers whenever some specific data in the database changes. What this means is that whenever something is created, changed or deleted, the event will trigger and execute a workflow. Article: \[Database trigger events\](/help-guides/logic/workflows/events/backend-events/database-trigger-events.md) \[^8\]: \*Privacy rules\* are conditions that you set up on each data type in order to protect the data from being viewed and edited by unauthorized users.\\ \\ Article: \[Protecting data with privacy rules\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md) \[^9\]: \*Do a search for\* is a data source that's used to search for and return a list of results from the database, such as searching for a list of users.\\ \\ Article series: \[The database\](/help-guides/data/the-database.md)\\ Reference: \[Do a search for\](/core-resources/data/data-sources.md#do-a-search-for) \[^10\]: Such as using the \[^11\]: \*Make static\* takes a list that relies on dynamic data and converts it into a list with the current items. Once converted to static, the list will not change if underlying values change.\\ \\ Reference: \[The :make static operator\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/pages/-MTpydODwo34mk5NucJy#...-make-static) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/searches.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/finding-data.md). # Finding data {% hint style="info" %} This section takes a long-form look at how searches in Bubble work.\\ \\ To see the the more concise and technical complete list of settings, constraints and operators, you can check out our \[core reference entry on searches\](/core-resources/data/search.md). {% endhint %} Having added and updated data in our database, we'll also need a way search for that data and display it around our app. ## Finding data Whenever you need to find some data in the database, you can perform a search using the \*Do a search for\* \[data source\](#user-content-fn-1)\[^1\]. This lets you set up a dynamic query to the database with specific constraints, and Bubble returns all things of that data type that match the constraints. You can only search for one data type at a time, such as \*Users.\* Let's say you want to search for all users who have the name John. We can set up the \*Do a search for\* function like the example below. {% hint style="info" %} Data sources like \*Do a search for\* are one of the building blocks in \*\*dynamic expressions.\*\* To read more about how to work with expressions, check out our dedicated article on the subject:\\ \\ Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) {% endhint %} First, we set the Type of content to \*User\* and in the \*Data source\* dropdown we pick \*Do a search for:\* ![](https://manual.bubble.io/files/TvGj1ib8FfLYpEVmZPkv) Then we set up a \*constraint\* which instructs Bubble to only return users that have the name John. The result will always be a list, even if it contains just one thing. ![](https://manual.bubble.io/files/27ENsjLinrp7R1qjNRrH) In this example we are searching for users named John. This is the basic way that database queries work: we tell Bubble what kind of data to search for, and then provide one or more constraints that each thing in the returned list needs to match. We can use this logic to find data in all sorts of scenarios: \* To display the results on a screen \* As part of a workflow (for example if we want to make changes to one or more things) \* As part of a \[conditional expression\](#user-content-fn-2)\[^2\] In the example above, we used a static value as a constraint: the name John. We can also set this up as a \*dynamic\* value. For example, we could change the condition to ask for the value of an input field instead. This would let your users type in a name and search the database for users that match: ![](https://manual.bubble.io/files/tyFQ7aFW2cyFkM6bOr7p) In this example we are searching for a dynamic value from an input field called _Input search by name_. By referring to that value as a search, we can let our users specify what to search for. {% hint style="info" %} Element data sources using \*Do a search for\* are synchronised with the database in real-time. This means that any changes happening in the database, even if made by another user, will be immediately visible in your app. There's no need to manually update searches. The exception is if the initial search was fetched in a workflow. {% endhint %} ## Sorting the results Sometimes you'll want to sort the result in a specific way, such as showing users in alphabetical order or tasks by their priority or deadline. This can be used to display the records in a list, or it can be used to find a specific record. For example, if you want to load the \*last\* user that was created in your database, you can sort the list by creation date and isolate the newest user with the \*first item\* or \*last item\* operator (depending on the sorting order). You can set the sort order when you perform a search. ![](https://manual.bubble.io/files/bCnGvya0dOo8AB8WOKpA) In this screenshot we are sorting users by their name. In some cases you will be referring to a list that's \*not\* loaded from a search, or where for some reason you need to apply the sorting \*after\* another operator in the expression. In that case you can use the \*sorted\* operator. ![](https://manual.bubble.io/files/8FLKHxEnlYBrRZQdiUGk) In this example we are using another repeating group as the data source and then applying sorting on that list. \## The difference between a \*list\* and a single thing Bubble has two ways of handling database records: as single items or as a list. It's important to understand this distinction, because the two are treated differently. For example, when you \[load data into container elements\](#user-content-fn-3)\[^3\], a \[\*group\*\](/help-guides/design/elements/web-app/containers/groups.md) element will expect a single thing, while a \[\*repeating group\*\](/help-guides/design/elements/web-app/containers/repeating-groups.md) will expect a list of things. Whenever you perform a search, the result will be a list – even if it only returns one thing (meaning it's a list with a count of one, but still a list). ### Loading a single record from a list Whenever you set up a data source that returns a list, such as \*Do a search for\*, Bubble elements\[^4\] and expression operators\[^5\] that expect a \*single\* item will return an error in the \[issue tracker\](#user-content-fn-6)\[^6\]. In cases like this, you will need to instruct Bubble to load \*one\* of the records in the list. You do this by adding another operator in the data source expression: \* \*\*First item\*\* will return the first item in the list. What item that will be depends on how the list is sorted. The default sorting is by creation date. \* \*\*Last item\*\* will return the last item in the list. What item that will be depends on how the list is sorted. The default sorting is by creation date. \* \*\*Random item\*\* will return a pseudorandom\[^7\] item from the list. \* \*\*Item #:\*\* will return a single item as specified by its index number in the list. This operator requires you to also define a number, such as \*Item 5\*. By combining search constraints with the \*first item\* operator you can often reach the exact thing you were looking for. For example, you could search for \*users\* and use the Email field as a constraint. Since emails are unique, you can be sure to find the right record by providing the email address of an existing user. If you then apply the \*first item\* to the list of results, you will have turned the list into a single thing. ### Turning a single record into a list Sometimes you'll need to go the other way and turn a single item into a list, even if that list still only contains the one record. To do this, use the \[\*Converted to list\*\](#user-content-fn-8)\[^8\] operator. ![](https://manual.bubble.io/files/8fBX9rReV3wdtfkSuREm) In this example we are taking the _User_ loaded into a group called _Group User_ and turning it into a list. The list will still contain just one record, but Bubble will treat it as a last. In the example this makes it a valid data source for a repeating group. \## Other data sources Searching for data in the database with \*Do a search for\* is one way of finding data. | Data source | Description | Returns | | ---------------------- | ----------------------------------------------------------------------------------- | ----------------------------------------------- | | Do a search for | Searches the database using constraints. | A list of things | | Current user | The user currently using the app | One thing | | Current page thing | The database record currently loaded onto the page using the \*Go to page\* action. | One thing | | Get data from page URL | Getting a thing from a URL parameter that contains a unique ID. | One thing | | Things's X | Getting a thing from a field saved on another thing, such as Current User's Company | A list or a single item, depending on the field | ## Other ways to learn Core reference \* \[Searching\](/core-resources/data/search.md) Video lessons \* \[How to use search constraints\](https://youtu.be/gOjGDCJrXYI) \* \[How to use the \*Do a search for\* data source\](https://www.youtube.com/watch?v=-2\_3kuyOxkw) \[^1\]: A \*data source\* the part of an expression that makes up the source from which Bubble will pull the data.\\ \\ In this context, the data source is a databse search. It could also load the data saved on the current user by using the \*current user\* data source. In an expression, the data source can (but doesn't have to) be followed by an \*operator\*. For example, if you search for users and want to return the first item in the list of results, you can use the \*first item\* operator:\\ \\ Do a search for users:first item. In this case, the \*Do a search for\* is the data source and the \*first item\* is the operator. \[^2\]: A conditional expression is a way to ask Bubble a question that returns either a true or false value. We can then use the response to in some kind of logic, such as to change the formatting of an element or determine whether a workflow should run or not.\\ \\ In the context of database searches, we could for example set up an expression that checks whether there is already a user named John by searching for it and counting the results. If the result is bigger than 0, Bubble returns a yes. \[^3\]: Container elements such as group can have a database thing loaded into them. This way, each child element can reference that data to display data, auto-bind input elements and in workflows.\\ \\ Article: \[The element hierarchy\](/help-guides/design/elements/the-element-hierarchy.md)\\ Article section: \[Loading data into containers\](/help-guides/design/elements/web-app/containers.md#loading-data-into-containers) \[^4\]: \*Elements\* are all the things that you place on the page, such as containers, input forms and visual elements like icons and images.\\ \\ Article series: \[Elements\](/help-guides/design/elements.md) \[^5\]: An \*operator\* is any step that you add to an expression after the data source. \\ For example, if you have a list of things, and you want to return the \*first\* item in that list, the expression might look like this:\\ \\ \\&#xNAN;\*Do a search for:first item\*. In this example the \*Do a search for\* is the data source and the \*first item\* an operator. \[^6\]: The issue tracker is the counter in the upper right part of the screen in the Bubble editor. Whenever there is one or more issue with your app it will show a red text and the number of issues. \[^7\]: \*Pseudorandomness\* means that the generated number appears to be random, but is actually produced by a deterministic system.\\ \\ To your users it makes no noticeable difference, but it means that the number is not cryptographically secure. \[^8\]: The \*Converted to list\* is an operator that you can add to a data source in an expression. It will turn a single database record into a list containing that record.\\ \\ Reference: \[The converted to list operator\](https://manual.bubble.io/help-guides/data/the-database/pages/-MTpydODwo34mk5NucJy#...-converted-to-list) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/finding-data.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md). # API Connector security {% hint style="info" %} This article covers the \*\*security\*\* aspects of using the API Connector plugin specifically. If you want to learn more about the API Connector in general, you can check out the articles below: Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md)\\ Article series: \[API\](/help-guides/integrations/api.md) {% endhint %} The API Connector is Bubble-made plugin used to make \[outbound API calls\](#user-content-fn-1)\[^1\] to external apps and systems. The API Connector is designed to automatically manage many security aspects and defaults to strict security settings to prevent unintentional vulnerabilities. Still, as with any other area of app development, it's essential for you, the app developer, to ensure the API connector is configured securely and to familiarize yourself with best practices in this domain. ## Handling API keys {% hint style="info" %} In this section, when we say "API keys," we're talking about all generated tokens used for authentication. This includes not just traditional API keys, but also OAuth tokens, JWTs (JSON Web Tokens), secret access codes, and other authentication credentials. {% endhint %} Many services that you connect to using the API connector will generate one or more API keys that you use to authenticate\[^2\] your requests. ![](https://manual.bubble.io/files/oCZlIIkyP1nvgenu3XOl) Authentication identifies **who** the client is and authorization determines **what** they should have access to. API keys are unique strings of letters and numbers that act like a password or a digital handshake between applications. They grant access to specific functionalities and data within an API service, allowing your app to talk to that system seamlessly. > Just as you wouldn't want to leave your home key under a doormat for anyone to find, it's crucial to keep your API keys hidden and secure. If they are exposed, malicious actors can misuse them, potentially leading to unauthorized access, data breaches, or unexpected charges if the API has associated costs. By ensuring API keys remain private, you're safeguarding the relevant API connection. Some ground rules for handling API keys in Bubble: #### \*\*API keys should never be stored in places that can be revealed in your app's source code, such as:\*\* ❌ Option sets\\ ❌ In on-page workflows, elements and dynamic expressions\\ ❌ In app texts (translation strings)\\ ❌ In custom states\\ ❌ In URL parameters\\ ❌ In the names and/or labels of your workflows, elements, pages, data types/fields and option sets\\ ❌ In the default values of your data type fields #### \*\*API keys should not be shared with anyone outside of your team - do not share it in places such as:\*\* ❌ Chat channels\\ ❌ Forum posts\\ ❌ Social media posts\\ ❌ Screenshots API keys should be handled like you would handle the passwords of your most important logins. ## Parameters #### \*\*What are parameters?\*\* Parameters in an API call are essentially pieces of information you send along with the call to either request specific data or provide some context. If the recipient recognizes the parameters, they can then tailor the response to fit your requirements. For example, if you're calling an API to get weather information, a parameter might be the city or postal code. If you are calling an API to create a new user in an external app, parameters might be the email address and name of that user. \*\*Where are parameters included?\*\* Parameters can be placed in various parts of an API call: 1. \*\*URL Parameters\*\*: Often seen in the URL itself after a "?" symbol. For example, \`api.website.com/data\`\*\*\`?city=NewYork\`\*\*. 2. \*\*Header Parameters\*\*: Included in the request header, often used for authentication or specifying content type. 3. \*\*Body Parameters\*\*: Used in POST requests, where data is sent in the request body. Useful for sending more complex data like JSON objects. \*\*Why set them to private in the API Connector?\*\* In the API Connector, setting parameters to "private" removes it from your app's code files and makes it inaccessible to end-users. This is possible because API calls by default are routed through Bubble's server. This allows us to store the parameter only on the server and include it as needed when the call is made. ![](https://manual.bubble.io/files/R8UBrsniOakzXuulTu4c) Checking _Private_ keeps the parameter on the server, hiding it from end users. When the call is made, the parameter is sent from Bubble's server directly to the API. This is particularly important for sensitive info. For example, you wouldn't want to accidentally expose an API key or confidential data. Keeping parameters private ensures they remain a secret between your app and the API. #### Making URL parameters private In the example above, we've ensured that a parameter in the \*Header\* is private. But what about parameters that you include in the URL? Just like header and body parameters, they too can be set to private. But before that, they need to be parameterized. Let's first look at an \*\*insecure\*\* parameter included in the URL: ![](https://manual.bubble.io/files/OCbSTCn4sLinw1B8aL1a) The information above would be visible in your app's code file on the user's device. In many cases there is nothing wrong with this, but in the example above, we have included some sensitive information: an API key.So how do we hide it? Note the text on the right-hand side of the URL input form that says \*(use \\\[\] for params)\*. This tells us that we can use brackets to turn a string of text in the URL into a parameter, that can then be set to \*private.\* Let's see what a more \*\*secure\*\* way to send the parameter would look like: ![](https://manual.bubble.io/files/sDKP8Nvtn9z8PCgkcpwO) In the example above, we wrapped the URL parameter inside of brackets, and Bubble automatically creates a parameter below with an input field for both the key and the value. This allows us to set the parameter to \*private\* keeping it hidden from the app's users. You can set up more than one bracket in each URL, and even turn the whole URL into a private parameter if you prefer to even keep that hidden. ## API call structure and security {% hint style="info" %} This section gives a brief introduction to how API calls work. If you want to learn more about how API requests and responses are structured, as well as the HTTP protocol, you may be interested in reading our extended section on how APIs work. Article series: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) Article: \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) Article section: \[What is the HTTP protocol?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol) {% endhint %} An API call happens in two stages: there's the \*\*request\*\* and the \*\*response.\*\* In the case of the API Connector (making \*outbound\* calls), your Bubble app (the \*\*client\*\*) is always the one making the request, and the server you are communicating with (the \*\*server\*\*) is sending the response. The entire process is transferred via the \[HTTP protocol\](#user-content-fn-3)\[^3\] (and in most cases encrypted with SSL/TLS), just like when you load a web page. To learn more about the different \*parts\* of a request, we recommend the article listed above. In the table below, we've listed the short-form explanation for each, along with common security recommendations: | Part | Purpose | Security Considerations | Recommendations | | --- | --- | --- | --- | | [Header](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-4) | Contains [_metadata_](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-5)
for the API call | Can reveal information about the request, e.g., [content type](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-6) | Avoid sensitive info in custom headers | | [Body](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-7) | Contains the main _content_ of the request/response | Transmits the actual data, which can be sensitive | Avoid including information that the API server doesn't need. | | [Method](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-8) | Indicates the _type_ of request (e.g., GET, POST) | Certain methods (e.g., POST, PUT) may change data on the server | Use the appropriate method for the task; Avoid using methods that change data unless necessary | | [URL](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-9) | Specifies the endpoint and sometimes parameters | Parameters can expose sensitive information if not set to private | Use the [_private_ setting](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-10)
to mark parameters as private
Avoid placing sensitive info directly in the URL | | [Parameters](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md#user-content-fn-11) | Details for specific queries or actions | Can be crucial for data operations | Make sure parameters don't leak sensitive data
Use _private_ when necessary | \#### Don't send the server more data than is needed Keep in mind that while the information in a call may be encrypted with TLS\[^12\] while in transit, the receiver of the request (the server) will decrypt all the data included in it. While most API services can be trusted to handle that information securely, it's still best practice to not include more information than is needed. That's why our recommendations above encourage you to follow that practice. This is in line with \[the principle of least privilege\](#user-content-fn-13)\[^13\]. ## Default parameter values To enable a specific API call, you need to initialize\[^14\] it. If the call includes parameters, you need to assign a \[default value\](#user-content-fn-15)\[^15\] to these parameters that Bubble can use when the initialization is done. The default parameters become part of your app's code base, and can be viewed on the device of the user. \* Do not store sensitive information in this field \* If you prefer the value to not show up anywhere, you can delete its content after the initialization is done ![](https://manual.bubble.io/files/CRUsoUoLxjmAukw3DERw) Sometimes you'll need to include one or more parameters when you initialize a call. You can remove these values after it has been initalized to avoid them being visible anywhere in your app's code. \## External API dashboard settings and features When using the API Connector, many of the settings you will use with that API are not set on Bubble's side, but in the dashboard of the API provider. To maintain secure connections, it's important to go over these settings and ensure they are properly set up. Settings are sometimes connected to one specific API key, meaning that you can use different keys with different settings to maintain flexible security. Note that the different settings and features available in each API service can vary. ### Limit Permissions Many API services offer settings for limiting the permissions of a call, such as which applications can use the key or which API services the key can call. We recommend setting permissions to the strictest possible setting that lets you successfully run the call you need. ### \*\*Rate Limits\*\* Many providers have \[rate limits\](#user-content-fn-16)\[^16\], or allow you to set your own rate limits in order to maintain an expected volume of calls or stay within a budget. Learn how to set and view rate limits set by the API you're connecting to. This prevents overwhelming the server, overspending your budget and potential IP blacklisting. ### Get to know audit logs and analytics Many API services keep detailed logs of every request and response that goes through their platform using your authentication. Learning to use the audit logs helps you stay on top of all the data that is exchanged, as well as debugging errors. Logs and analytics can also help you identify unusual patterns that might indicate malicious activity or potential vulnerabilities. ## FAQ: API Connector #### What should I do if I misplace an API token? If an API token somehow ends up in the wrong place, we strongly recommend immediately logging into the relevant API service and disabling it. With most services you can then generate a new one, making the old API key useless. \[^1\]: \*Outbound API calls\* means that the request is coming \*\*\*from\*\*\* your Bubble app \*\*\*to\*\*\* an external API service, as opposed to an inbound API call. \[^2\]: \*Authentication\* is the process of verifying the identity of the client that is trying to access the server. You can compare this to a passenger wanting to board an airplane. At some point the passenger will reach a security checkpoint where they have to present valid credentials to confirm their identity, usually in the form of a passport.\\ \\ In other words, authentication is about asking \*who the client is\*\*\*.\*\*\\ \\ Article section: \[Authentication and authorization\](/help-guides/integrations/api/introduction-to-apis.md#authentication-and-authorization)\\ Article series: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) \[^3\]: HTTP, or Hypertext Transfer Protocol, is a protocol: a set of rules that governs how data is shared between two systems to make sure both parties understand it.\\ \\ Article section: \[What is the HTTP protocol?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol) \[^4\]: Metadata for the API call. It often includes info like authentication tokens and the content type. Think of it as the envelope details when sending a letter. \[^5\]: Data that provides information about other data.\\ \\ In API calls, metadata provides context and additional details about the content in the body, helping systems process it correctly. For example, it's used to tell the server who the sender is and what kind of data to expect (text, a file, etc). \[^6\]: In API calls, consider the content type as the language or format in which you choose to communicate. Just as you might select a language (English, Spanish, etc.) for a verbal conversation, the content type specifies the format (like JSON or XML) for the data you're sending or expecting to receive.\\ \\ It ensures both parties (the sender and the receiver) are on the same page, understanding the data being exchanged. \[^7\]: The main content of the request or response. If you're sending data to a server or receiving it, this is where that data lives. In our letter analogy, it's the written content inside the envelope. \[^8\]: The \*HTTP Method\* tells the server what action to take on the specified resource. For example, a GET method retrieves data, while a POST method sends data.\\ \\ Article section: \[The HTTP method\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#http-method)\\ Article: \[What is the HTTP protocol\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol) \[^9\]: The web address or endpoint you're sending the request to. It's the destination of our hypothetical letter.\\ \\ The URL can (but doesn't have to) include parameters. \[^10\]: To set URL parameters as private, they first need to be parameterized. The above section covers this:\\ \\ Article section: \[Making URL parameters private\](#making-url-parameters-private) \[^11\]: Specific criteria or filters in your request. If you're asking a database for user data but only want users from New York, "city=New York" could be a parameter. Imagine it as special instructions you give when sending a package. \[^12\]: TLS (Transport Layer Security) converts data into a secret code while it travels between your web browser and a server. This keeps the info safe from eavesdroppers, ensuring the communication remain private and secure.\\ \\ TLS is essentially a more up-to-date version of the older SSL encryption. \[^13\]: \*The principle of least privilege\* means giving just enough access needed for a task and nothing more.\\ \\ Article section: \[The principle of least privilege\](/help-guides/security/api-security.md#the-principle-of-least-privilege) \[^14\]: \*Initializing\* an API call means to send a request to the external app or service to verify that it is working.\\ \\ This serves two purposes: 1) to ensure that you are getting a successful response, and 2) for Bubble to learn what the response looks like. \[^15\]: The \*default value\* is simply the value you provide during initialization to test that it is recognizable by the external app or system. \[^16\]: \*API rate limits\* specify how many requests your app can send to a given API within a given time frame, such as per minute/day/month. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis.md). # Plugins that connect to APIs To connect to an \[external API\](#user-content-fn-1)\[^1\], you will in many cases use the \[API Connector\](#user-content-fn-2)\[^2\] to set up the authentication and the different calls. There are many plugins however, that already have the authentication method and calls set up, that can save you some time. Before deciding to use the API Connector you may want to explore the plugin store to see if there's already a plugin that handles the calls you need. ## Finding API plugins There are two simple ways to search for plugins that connect to an API: ### Searching for the API provider: To \*\*search\*\* for relevant plugins: 1. Navigate to the \*Plugins\* section of the Bubble editor and click \*Add plugin\*. 2. Search for the API you want to connect to (i.e. Stripe) 3. Click the \*Install\* button ### Filter by plugin type Plugins in the plugin store are categorized into \*\*types\*\*, and you can use these to filter out the plugins by whether they are related to an API or not: ![](https://manual.bubble.io/files/cpY8xleYGGMlFepXPKRN) By selecting the **API** plugin type you can filter the search results for plugins that are related to different API services. \* Navigate to the \*Plugins\* section of the Bubble editor and click \*Add plugin\*. \* Under \*Types\* on the left-hand side menu, click \*deselect all\* \* Select the \*API\* type \* You can further filter results by checking relevant boxes under \*Category\* or use the search function \[^1\]: External APIs are applications and services you can connect to to share data and actions.\\ \\ Article: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md)\\ Article:\[ What is RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) \[^2\]: The API Connector is Bubble's tool for setting up and making outgoing API requests.\\ \\ Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md)\\ Reference: \[The API Connector\](/core-resources/api/the-api-connector.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/backend-workflows.md). # Backend workflows {% hint style="info" %} This article focuses on backend workflows from the perspective of optimizing for workload unit (WU) consumption. For a more general introduction to backend workflows, you can read the article series below: Article series: \[Backend workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md) {% endhint %} {% hint style="info" %} This article series on workload will sometimes reference documentation shared in other parts of the series, as well as the core reference entry for workload. We recommend you get to know the core reference entry, and proceed to read the series as a whole (in that order). Reference: \[Pricing and workload\](/account-and-marketplace/account-and-billing/pricing-plans.md)\\ Article series: \[Optimizing for workload\](/help-guides/workload.md) {% endhint %} One of the places that apps can run into an increase in workload consumption is in backend workflows. Let's first agree on what backend workflows are. \[Backend workflows\](#user-content-fn-1)\[^1\] is the umbrella term for all workflows that are created in the \*Backend workflows\* editor: \* API workflows \* Database trigger events \* Recurring events \* Custom events (that are not on a page) ![](https://manual.bubble.io/files/hgGJnLjP37RLVPwMvbat) You can read more about backend events in general in \[this article\](/help-guides/logic/workflows/events/backend-events.md). In the illustration above, we'll focusing mainly on the two first types of workflows: \* API workflows \* Database trigger events While the two latter types can certainly also spend workload, it's typically the two first that are the primary contributors to system load and warrant optimization. ## API workflows API workflows can be triggered from outside of your app or inside, depending on how you set them up. An important introductory point is that the work being performed by the workflow will spend workload, regardless of whether it's triggered internally or from an external source. API workflows consume workload in the following operations: \* Workflow: \* The scheduling of the workflow (Schedule API workflow/Schedule API workflow on a list) \* Any condition(s) on the workload \* Actions \* Any processing done by the actions in the workflow \* Any condition(s) on any of the actions What this tells us is that simply looking at the actions does not give you the full picture; the scheduling and conditions also give the server work to do. When you plan workload on the page, you can sometimes perform certain conditions client-side, but it's worth remembering that \*everything\* that happens in an API workflow is performed server-side. ### The scheduling Scheduling an API workflow consumes a tiny bit of workload. For one-off operations, this is negligible, but if you are repeatedly scheduling new workflows (by setting up \[recursive workflows\](#user-content-fn-2)\[^2\] for example), this part of the workflow can accumulate. Recursive workflow and the \*Schedule API workflow on a list\* behave a bit differently and as such consume a different amount of workload: \* A \*\*recursive workflow\*\* schedules itself once per time it iterates, until a condition is met. In other words, if you run a recursive workflow on a list of 100 things, the \*Schedule API workflow\* action will run a 100 times, consuming a tiny portion of workload each time. This also means that recursive workflows are executed sequentially (as opposed to in parallell). \* \*\*Schedule API workflow on a list\*\* schedules all of its workflows in one operation. While that operation may require more workload than scheduling a single API workflow, the on-going re-scheduling of a recursive workflow will in most cases consume more. Schedule API workflow on a list attempts to execute all the operations in parallell (as opposed to sequentially). As we have emphasized earlier, this doesn't mean that you should always choose one method over the other; it means that you can make an informed decision. Recursive workflows run in a sequential manner and offer a bit more flexibility. \*Schedule API workflow on a list\* is faster to configure and typically completes more swiftly, while consuming less WU. It can also be directly executed from the database editor using the Bulk feature. ### Conditions Conditions can be placed on the workflow/event itself, or on any of the action steps inside. Conditions are a double-edged sword since they can both \*save\* workload and \*consume\* workload, depending on how they are used. Let's look at each case: #### Saving workload with conditions Conditions tell a workflow or action whether it should run or not. As a result, a condition can stop a workflow or action from ever triggering, saving the workload that would have been spent. > A condition can stop a workflow or action from ever triggering, saving the workload that would have been spent Unless a specific workflow or action should \*always\* run when requested, it makes sense to place a condition on it to stop it from running unnecessarily. If you are setting up recursive workflows, a condition is also needed to stop the workflow from re-scheduling itself indefinitely. #### Consuming workload with conditions With that covered, we can look at the flip side: conditions themselves spend workload. Since everything in an API workflow happens server-side, the condition will spend an amount of server resources no matter how it's set up. As such, there are two questions you can ask yourself: \* Do I need this condition? \* Is there any way I can make this condition spend less workload? A condition is built with a \[dynamic expression\](#user-content-fn-3)\[^3\], just like workflows and element data sources; in other words, they consume the same amount of workload performing the same operation. Let's say for example that you set up a condition that performs a database search, like the example below: ![](https://manual.bubble.io/files/89rSG2IPFyYDXhT5RZS9) In this example, the Bubble server has to perform that search query every single time the API workflow is triggered, which can potentially consume a lot of server resources. Maybe there are ways to make the condition more lightweight, or maybe it's even more performant to run the workflow regardless of the search result (if the workflow is more lightweight than the condition). As the example illustrates, conditions do spend workload too: the location of a dynamic expression—whether in a condition, workflow, or as a data source in a \[repeating group\](#user-content-fn-4)\[^4\]—doesn't exempt it from consuming server resources. Be mindful of how you structure your conditions to keep them from spending too much. Placing a condition on an action, rather than on the event, incurs the same resource cost. However, halting the workflow at the event step can conserve workload by preventing it from progressing to subsequent action steps. ### Actions Each action in an API workflow will also spend resources. Again, we need to keep in mind that on the front-end (the page), we can sometimes leverage client-side actions to move some of the processing away from the server, but in an API workflow everything happens server-side. Once more, our aim isn't to reduce the use of actions to the extent that it compromises the user experience of our app. Rather, it's about recognizing and understanding that every action step in a workflow uses resources. If you are looking to optimize an API workflow, it's worth reflecting on each action step whether: \* It's needed at all \* It could run only when needed, using a lightweight condition \* It could be set up in a more efficient way (see below) Furthermore, the expressions within each action will also make server queries for processing. ![](https://manual.bubble.io/files/GXj2p4cb4Ztnjy3ze2Ff) In the example above, workload is spent: \* On the action itself (writing data to two fields on the Product data type) \* On \*three\* searches: \* First, we search for the product to make changes to \* Then, we search for and count the number of products (Field 1) \* Lastly, we search for a user and return their address This is an action step that likely would benefit from optimization. Perhaps one or more of the searches could be replaced with a parameter\[^5\] (that is itself not the product of a search) or there are other ways you locate the data without having to search for it. If you need to use searches, make sure that you set them up efficiently: \* Avoid nested searches (searches that use another search as a constraint) \* Avoid advanced filters \* Use as many constraints as you can, so that Bubble can \[rule out database things quickly\](#user-content-fn-6)\[^6\] ### Authenticating API clients It's common for API workflows to require authentication. This mandates that the client present evidence of their identity to execute the workflow, often in the form of a token that Bubble has generated for you. Authentication is vital not just for security but also to safeguard your server resources. An unprotected API workflow, accessible to anyone aware of its endpoint, leaves your app vulnerable to a flood of requests. This could be from well-intentioned users or malicious actors deploying botnets. #### Authentication and conditions Additionally, requiring authentication can give you access to a broader set of conditions for workflows and actions. You can halt an API workflow at the event level using this approach. Examining fields on the user that the client represents offers a lightweight method to determine whether the condition should proceed or be bypassed. Similarly, while a client may authenticate and gain permission to initiate the workflow, certain action steps might be bypassed based on their identity, saving workload in the process. ### API workflows and privacy rules Privacy rules are of course necessary to protect your database data from unathorized access, but it too can help you save workload. Privacy rules are essentially search constraints, which means that any query you perform can finish faster and deliver a shorter list of results if you use more constraints. Privacy rules centralize many of your search conditions based on the client's identity, streamlining the retrieval process for search results. ## Database trigger events Database trigger events execute whenever a specific change happens in the database. What this means is that whenever something is created, changed or deleted, the event will trigger. By combining this event with a dynamic expression, you can specify exactly what \*kind\* of change you want the event to be watching. ### How database trigger events work Let's first look at the cycle that a database trigger event works through: \* Any database trigger event is connected to one specific data type \* Conditions are normally used to specify exactly what \*kind\* of change we're looking for \* Whenever \*any\* change is made on that data type, Bubble will check the condition on the trigger event to see whether it matches. \* Changes include writing to any field on that data type, as well as things being created and deleted As that cycle suggests, conditions that you place on a database trigger event will consume a tiny bit of workload even if the condition returns a \*no\* and the workflow is not triggered. This understanding is the first step to planning efficient database triggers. That being said, database trigger events have access to a limited list of data sources: \* Thing before change \* Thing after change What this means is that because you're not able to perform database searches and other resource-heavy operations, the condition on a database trigger event will usually be fairly lightweight. ### Reducing the workload on the trigger There are a few questions you can ask yourself about each database trigger event that can help you reduce workload: #### How often is the data type associated with this trigger changed? In other words; how many times over a given period will Bubble write to the database on \*any\* record of that specific data type. Keep in mind that for \*every\* change, Bubble will need to check the condition: if this specific data type changes many times per hour, minute or even second, a considerable amount of resources may be spent simply checking whether the event should trigger or not. We can illustrate with an example: let's imagine you are building an app with a chat feature similar to WhatsApp or Facebook Messenger. It's in the nature of apps like this to create a lot of new records, as each message is typically saved in the database as a thing. Each individual user could be creating new messages several times per minute, and as your user base grows, this could extend into many times per second. In this scenario, a database trigger event, regardless of the actions it performs, can consume considerable workload, and you may want to find other ways to perform the tasks that the event executes, to avoid spending too much on the condition being repeatedly checked. #### Can you combine triggers? It's not uncommon to set up multiple database trigger events for the same data type. While this is not a practice we discourage in any way, there is still a potential to reduce the workload consumption in some scenarios by combining two database trigger events into one. Take a look at the whole picture: if you can reduce the number of events and actions by combining them, there's a change it consumes less server resources in total. #### Does it need to be handled by a database trigger event? Database trigger events are sometimes used to watch for one data type/field to change, and then update another one in response. Let's look at this from two scenarios: \*\*Scenario 1: use database trigger event to update field\*\* In scenario 1, a data type is updated by the user in a form in the app using the \[\*Make changes to a thing\*\](#user-content-fn-7)\[^7\] action. The database trigger event reacts, and writes something to the database in response. In this case, workload is spent on the following: \* The original database change \* Starting the evaluation of the database trigger event \* Checking the condition on the database trigger event \* Running the actions in the database trigger event workflow \*\*Scenario 2: make the change in the original workflow\*\* In scenario 2, instead of using a database trigger event to react to the changes, we make the change using an action in the original workflow on the page. In this case, workload is spent on the following: \* The original database change \* The secondary database change As you can see, we have reduced one step in this process: Bubble no longer has to spend resources on the database trigger event condition, but instead simply runs the action in the original workflow. Using method 2 over method 1 can reduce the total workload; as always, it's up to you as the developer to weigh the advantages and drawbacks of each method. Database trigger events provide a reliable way to maintain your database integrity (and will respond even to manual changes in the Bubble database editor), but at the expense of a slightly higher workload cost. ### Actions Just like with API workflows, each action (and the condition and dynamic expressions in that action) spends server resources. From this point on, database trigger events follow the same logic as \[actions in an API workflow\](#actions), and the same advice applies. ## Finding the right balance It's important to yet again emphasize a point: workload is spent doing \*work\*. In other words, it's not a competition to reduce the metric to its absolute possible minimum. Server-side processes can be an incredibly important resource in your app to maintain security, database integrity, and speed up development. There's no doubt that these concerns can weigh more heavily than workload consumption in many cases, and before you spend your time over-engineering your app to reduce workload, it's worth reflecting on \*each\* task whether that's the right priority. Your workload metrics dashboard will give you an overview of where your workload is being spent; use it wisely to prioritize. Sometimes, even the most workload-hungry process \*needs\* to be there in order for your app to be useful to your users or to allow you to spend time on other optimizations such as new features. Remember, while this article provides strategies to reduce workload, the exact reduction can be challenging to estimate due to the unique nature of every Bubble project. Sometimes, significant optimization efforts might not bring the results you were hoping for. If you're uncertain about the benefits of a particular optimization, don't hesitate to consult with fellow \[forum members\](https://forum.bubble.io/) or our \[Success team\](https://bubble.io/contact). ## Summary Summary: Backend workflows and workload \* Backend workflows, including API and database trigger events, can increase workload consumption. \* API workflows, triggered internally or externally, consume workload in their scheduling, actions, and any attached conditions. \* The scheduling of API workflows, especially in recursive workflows, accumulates workload over time. \* Conditions in workflows, while potentially saving workload by halting unnecessary operations, also consume resources. All backend conditions are performed server-side. \* Every action in an API workflow incurs server resources. Client-side conditions are not applicable, since all backend workflows are executed on the server. \* Database trigger events are activated by changes in the database and consume workload every time they check conditions. \* Combining multiple database triggers into one and questioning the necessity of each trigger can reduce workload. \* Directly making changes in the original workflow instead of using database trigger events can sometimes be more efficient. \* The balance between necessary server-side processes for security and integrity and workload reduction is crucial. \* Monitoring the workload dashboard helps identify key areas for optimization but remember that not all optimizations yield significant workload reductions. \* Lastly, always keep your users in mind: creating a secure, well-performing app with a good user experience should usually be a higher priority than saving WU. \[^1\]: \*Backend workflows\* is an umbrella term for all workflows that are scheduled/triggered to run on the server, as opposed to on a page. This includes API workflows, database trigger events and more.\\ \\ Article series: \[Backend workflows\](/help-guides/logic/workflows/events/backend-events.md) \[^2\]: \*Recursive workflows\* are API workflows that schedule themselves one or more times, so that they are looped. This is usually done for bulk editing a list of things for example. Article: \[Recursive API workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/recursive-api-workflows.md) \[^3\]: \*Dynamic expressions\* are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) \[^4\]: A \*repeating group\* is a container type element used to display a list of things. For example, you can use a repeating group to show a list of users, products or tasks. Article: \[Repeating groups\](/help-guides/design/elements/web-app/containers/repeating-groups.md) \[^5\]: A \*parameter\* in this context, refers to a specific piece of data or value that is passed into the API workflow from an external system or using the \*Schedule API Workflow\* action. Article section: \[API workflows: defining parameters\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/creating-api-workflows.md#defining-parameters) \[^6\]: Database searches are a process of elimination. By adding more constraints, Bubble can rule out things (records) faster and reach the final result using less server resources. Article series: \[The database\](/help-guides/data/the-database.md) \[^7\]: The \*Make changes to a thing\* action is used to write in the database on an existing thing (record). Article: \[Creating, saving and deleting data\](/help-guides/data/the-database/creating-saving-and-deleting-data.md) Reference: \[Make changes to a thing\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/pages/-MTujs88N9W-2FUmQGag#make-changes-to-thing...) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/backend-workflows.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/web-app/visual-elements.md). # Visual elements \*\*Visual elements\*\* are the elements you can place on that page that cannot contain other elements (groups) and cannot accept input (input elements). They usually serve two purposes: \* To display information or contribute to the aesthetics of the page \* To accept button clicks ![](https://manual.bubble.io/files/6cIvv6znSo3L5KBlevIl) In the illustration above, all elements are visual elements: text, an image and a button. The visual elements category contains the following elements: ## Text A non-editable text element. Both the header and the body copy in the image above are text elements. Video lessons \* \[How to use the text element\](https://www.youtube.com/watch?v=mtS7bLsV-tg) \* \[Formatting text with BBCode\](https://www.youtube.com/watch?v=mtS7bLsV-tg) \* \[How to Use Text Transform Operators\](https://www.youtube.com/watch?v=kmvmYAlrjUk) \## Button A button is a shape with a text/icon that's optimized for click workflows. It can contain a text, an icon or both. Video lessons \* \[How to use the button element\](https://www.youtube.com/watch?v=tk1Rjo8SziI) \* \[How to use the \*An element is clicked\* event\](https://www.youtube.com/watch?v=CObRfZiAitY) \## Icon Icon elements let you pick an icon to display from several different \[icon collections\](#user-content-fn-1)\[^1\]. {% hint style="warning" %} On Android devices, \*\*phosphor “filled” icons may display as black boxes\*\* instead of the intended icon. This issue is due to a bug in a third-party library required for rendering these icons. At this time, there is no workaround. The issue will remain in place until it is resolved by the library author. If your app relies on filled phosphor icons, consider using an alternative icon style for Android builds. {% endhint %} Video lessons \* \[How to use the icon element\](https://www.youtube.com/watch?v=DR-UZ27J8GM) \* \[How to use the \*An element is clicked\* event\](https://www.youtube.com/watch?v=CObRfZiAitY) \## Link The link element lets you set up a link with a custom text and destination. It can dynamically point to one of your internal pages (including sending data to that page) or point towards an static and/or external link. Video lessons \* \[How to use the link element\](https://www.youtube.com/watch?v=-wJZPaXQZpw) \## Image Image elements allow you to place images in your app. The element supports all widely used image types such as png, jpg, svg, webp and gif. Video lessons and articles \* Video: \[How to use the image element\](https://www.youtube.com/watch?v=eazYG0lRzrg) Bubble also has a separate element for uploading images: \* Video: \[How to use the image uploader element\](https://www.youtube.com/watch?v=ZXjhQkM5qV0) \* Article: \[File uploads\](/help-guides/design/elements/web-app/input-forms/file-uploads.md) \#### Generating an image with AI You can generate images with AI. Type in a prompt and select a size, quality, and style. The \*Auto\* setting lets the AI choose style setting based on your prompt. The number of tokens used depends on your selections. Check \*Generate Alt tags\* to automatically generate an \[Alt text\](#user-content-fn-2)\[^2\]. ## Shape The shape element adds a rectangle to the page which can be resized, rounded and styled in different ways. Video lessons \* \[How to use the shape element\](https://www.youtube.com/watch?v=z\_H7jQUFsTA) \## Alert The alert element adds a bar that can show a text message for a set amount of seconds before it disappears. It's used to display temporary messages such as success and error messages. Video lessons \* \[How to use the alert element\](https://www.youtube.com/watch?v=Die7FRWEsbY\\&t=18s) \* \[How to use the e\*lement has error\* event\](https://www.youtube.com/watch?v=\_HNvvPxcWAU\\&t=3s) \## Video The video element lets you implement streaming video in your app. The element supports YoutTube and Vimeo. Video lessons \* \[How to use the video element\](https://www.youtube.com/watch?v=wOc2FIja-uE) \## HTML The HTML element lets you place a snippet of HTML code on the page. It can be useful when you need to include custom HTML code in your app that cannot be achieved through Bubble's visual editor. This can be HTML code, CSS styles, and JavaScript code. Typical use cases for the HTML element include: \* Embedding third-party widgets \* Using custom CSS to style or animate elements \* Adding custom functionality with Javascript Video lessons \* \[How to Use The HTML Element\](https://www.youtube.com/watch?v=T8Y6JFg8Ph8) \## Map The Map element lets you implement a Google Map on the page, fully navigatable by your users. Video lessons \* \[How to use the map element\](https://www.youtube.com/watch?v=bZL1nCBhoWk) \* \[How to use the map marker is clicked event\](https://www.youtube.com/watch?v=474NiBb14iw) \## Built on Bubble This element lets you add a small "Built without code: Bubble" logo to your app. \[^1\]: Icons are contained within libraries, similar to all the letters in a specific font. For a list of the natively supported icon libraries in Bubble, see the icon element. Reference: \[Icon element\](https://manual.bubble.io/core-resources/elements/visual-elements#icon) \[^2\]: "Alt text" is short for \*\*alternative text\*\*. It's a written description of an image used by screen readers for visually impaired users, displayed when an image fails to load, and read by search engines to understand what an image depicts. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/web-app/visual-elements.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication.md). # Authentication {% hint style="info" %} \*\*Authentication\*\* is the process of identifying \*\*who\*\* a client\[^1\] is in order to determine what resources\[^2\] they have access to your your application. {% endhint %} ## Introduction Both the \[Data API\](#user-content-fn-3)\[^3\] and the \[Workflow API\](#user-content-fn-4)\[^4\] can be set up to require the client to authenticate themselves in order for your app to determine what resources they are allowed to access. In simpler words, you can require all external systems that want to access your database and workflows to log in using a secret password. ![](https://manual.bubble.io/files/oCZlIIkyP1nvgenu3XOl) The article in the link below explains how the \[\*bearer token\*\](#user-content-fn-5)\[^5\] is used to authenticate a client, regardless of the method you choose (except if you use no authentication). {% content-ref url="/pages/qVQrCNasyAQigdo9Xbbb" %} \[How to authenticate\](/help-guides/integrations/api/the-bubble-api/authentication/how-to-authenticate.md) {% endcontent-ref %} ## Authentication methods {% hint style="info" %} You can set the access level for an \*\*API workflow\*\* using the \*\*Authentication\*\* setting. This determines whether the workflow can be accessible to everyone, to authenticated users and admins, or to admins only. Article section: \[API workflow access level\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md#access-level) {% endhint %} There are three different levels of authentication that you can set up in Bubble, each with their own pros/cons and security ramifications. You can use the settings described \[above\](#access-level) to maintain precise control over which users or systems are allowed to access each workflow. The articles below outline the three different authentication methods you can use: {% content-ref url="/pages/rsXV8xr4MaHaHzTtpDZz" %} \[No authentication\](/help-guides/integrations/api/the-bubble-api/authentication/no-authentication.md) {% endcontent-ref %} {% content-ref url="/pages/GDxZ1naAd3kTJnMtSG7K" %} \[As a user\](/help-guides/integrations/api/the-bubble-api/authentication/as-a-user.md) {% endcontent-ref %} {% content-ref url="/pages/qeuXuXXBXWf8aK3ZAFf1" %} \[As an admin\](/help-guides/integrations/api/the-bubble-api/authentication/as-an-admin.md) {% endcontent-ref %} \[^1\]: The \*client\* is the system that initiates an API Connection by sending a request, as opposed to the \*server\* who is the one to receive it and respond. \[^2\]: An API resource is a specific item or service that is made available by the API and can be accessed via a unique endpoint.\\ \\ This can be a data type such as \*Users\* or a specific API Workflow.\\ \\ Article section: \[What are resources?\](/help-guides/integrations/api/introduction-to-apis.md#resource) \[^3\]: The Data API can give external applications access to your app's database to read, create, edit and delete records.\\ \\ Article: \[The Data API\](/help-guides/integrations/api/the-bubble-api/the-data-api.md)\\ Reference: \[The Data API\](/core-resources/api/the-bubble-api/the-data-api.md) \[^4\]: The Workflow API lets you set up API workflows that can be triggered from outside of your own application without visiting any page.\\ \\ Article: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md)\\ Reference: \[The Workflow API\](/core-resources/api/the-bubble-api/the-workflow-api.md) \[^5\]: The bearer token is a string that identifies \*\*who\*\* the client is. It serves as both username and password and is included in the \*header\* of the API request.\\ \\ Article: \[How to authenticate\](/help-guides/integrations/api/the-bubble-api/authentication/how-to-authenticate.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/api-glossary.md). # API Glossary Authentication and authorization \*\*Authentication\*\* is the process of verifying the identity of a client sending an API request (\*\*who\*\* the client is). For example, the Bubble API can be set up to require a bearer token to prove the identity of the client trying to connect. This process of providing the credentials and the server verifies them is the authentication process.\\ \\ \*\*Authorization\*\* is the process of determining \*\*what\*\* a client has access to after they have authenticated themselves. It is the mechanism by which an API can determine what a user or system is allowed to do once they have been authenticated. For example, after a client has authenticated themselves with the Bubble API, the API will check your app's Privacy API settings, privacy rules and other details to determine whether they have access to specific \[resources\](#resource). \*\*In short:\*\* Authentication is the process of verifying \*\*who\*\* you are, while authorization is the process of verifying \*\*what\*\* you have access to. \*\*Other ways to learn:\*\* Article: \[Authenticating with the Bubble API\](/help-guides/integrations/api/the-bubble-api/authentication.md)\\ Article: \[Setting up Authentication in the API Connector\](/help-guides/integrations/api/the-api-connector/authentication.md)\\ Article: \[The Data API and Privacy Rules\](/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules.md)\\ Article: \[The Workflow API and Privacy Rules\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules.md) API API stands for \*Application Programming Interface\* and it is a set of protocols, routines, and tools for allowing different software systems to communicate with each other. Imagine you're at a restaurant. You, the customer, want to order food, but you don't go into the kitchen yourself. Instead, you give your order to a waiter. The waiter then goes to the kitchen, gets your food, and brings it back to you. In this scenario, the kitchen is like an external app or system (the server). You, wanting to get some data or service from this system, are the client. The waiter is like the API. Just as the waiter takes your order to the kitchen and brings back your food, the API takes requests from one app (the client) to another (the server) and returns the needed response. \*\*Examples:\*\* 1. \*\*Data Retrieval:\*\* Fetching data from a remote database, like getting weather updates from a weather service. 2. \*\*Integration:\*\* Connecting to different services, like integrating a payment gateway (e.g., PayPal or Stripe) into your app. 3. \*\*Automation:\*\* Performing tasks in other systems, like posting a social media post to LinkedIn or creating an appointment in Google Calendar. 4. \*\*Enrichment:\*\* Enhancing functionalities, like using a map API to display locations in your app. 5. \*\*Authentication:\*\* Verifying user identity and granting access using an authentication system like OAuth to log into your app through Google or Facebook credentials. \*\*Other ways to learn:\*\*\\ Article: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md)\\ Article: \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) Client/Server In the context of an API call, the \*\*Client\*\* is the one that initiates the call and the \*\*server\*\* is the one to respond.\\ \\ In the case of an \*\*incoming\*\* API request (The Data API or Workflow API) the system sending the request is the \*\*client\*\* and the Bubble server that hosts your app is the \*\*server.\*\*\\ \\ In the case of \*\*outgoing\*\* API request (The API Connector) your Bubble app is the \*\*client\*\* and the system you are connecting with is the \*\*server\*\*.\\ \\ \*\*Other ways to learn:\*\*\\ Article: \[The Client/Server relationship\](/help-guides/integrations/api/introduction-to-apis.md#client-server-and-resource) Endpoint An endpoint is a specific URL that an application can send requests to, to retrieve or manipulate data.\\ \\ In the Bubble API, the endpoint is the URL that identifies a \*\*data type\*\* or a specific \*\*API Workflow.\*\* In outgoing requests made via the API Connector, the endpoint is the HTTP action and URL that you are pointing the call towards.\\ \\ \*\*Other ways to learn:\*\* Article: \[Data API endpoints\](/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-endpoints.md)\\ Article: \[Workflow API endpoints\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-endpoints.md) HTTP Method / HTTP Verb The HTTP method is the instruction for the server to indicate the desired action to be performed on the specified \[resource\](#resource) (e.g. GET, POST, PUT, DELETE). \* \*\*GET:\*\* Retrieves data from a server\\ (like viewing a webpage or getting a weather update). \* \*\*POST:\*\* Sends data to a server to create a new resource\\ (like adding a new calendar appointment to Google Calendar). \* \*\*PUT:\*\* Updates an existing resource with new data\\ (like changing the date of a calendar appointment in Google Calendar). \* \*\*DELETE:\*\* Removes a resource from the server.\\ (like deleting an appointment in Google Calendar) \*\*Other ways to learn:\*\* Article section: \[What is the HTTP protocol?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol)\\ Article section: \[What is the HTTP method?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#http-method)\\ Article: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) HTTP protocol The HTTP protocol is the blueprint for how most data is exchanged between a client and a server. It defines how a request and response is formatted, so both systems understand each other. \*\*Other ways to learn:\*\* Article section: \[What is the HTTP protocol?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol)\\ Article section: \[What is the HTTP method?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#http-method)\\ Article: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) JSON JSON is a lightweight data interchange format typically used in Javascript. It uses human-readable text to transmit data objects that consist of attribute–value pairs and array data types.\\ \\ It is commonly used both in incoming API Connections (the Data API and Workflow API) and outgoing API Connections (The API Connector). #### \*\*Example\*\* Below is an example of what JSON code may look like. In this example we're storing data about a user, and as you can see, it's easily readable both by humans and computers: \`{\` \`"user": {\` \`"id": "123456",\`\\ \`"username": "johnDoe123",\`\\ \`"email": "johndoe@email.com",\`\\ \`"firstName": "John",\`\\ \`"lastName": "Doe",\`\\ \`"birthdate": "1990-01-01",\`\\ \`"profilePictureUrl": "https://example.com/profiles/johnDoe123.jpg",\`\\ \`"phone": "555-1234",\`\\ \`"joinedDate": "2022-04-20"\` \`}\` \`}\`\\ \\ \*\*Further reading:\*\*\\ API glossary: \[Object / JSON object\](#object-json-object)\\ Article section: \[What is the JSON format?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-json-format) Key-value pair A key-value pair is a basic data structure where a 'key' (a unique identifier) is linked to a 'value' (the data). It's used in many programming languages, and in Bubble you can often come across it when you work with the \[API Connector\](#user-content-fn-1)\[^1\]. For example, in the \[JSON\](#json) code below, the text marked in bold are two key-value pairs: \* Key: "id" - value: "123456" \* Key: "username" - value: "johnDoe123" \`{\` \`"user": {\` \*\*\`"id": "123456",\`\*\*\\ \\&#xNAN;\*\*\`"username": "johnDoe123",\`\*\* \`}\` \`}\` Oauth2 OAuth2 is a protocol used by a server to determine a client's authorization. It lets a User grant an app (like your Bubble app) access to the resources stored in an external app without having to share their login credentials with the first app.\\ \\ Instead, the server that hosts the external app will issue a token that your app can use to access the User's resources. That way, subsequent requests can be made without the User having to authorize each one or share their credentials.\\ \\ \*\*Examples:\*\* \* A User wants to connect their social media account (such as Facebook or Twitter) to your Bubble-built social media management app in order to share posts automatically. The User grants your app access to their social media account using OAuth2, and your app is issued a token that it can use to post photos on behalf of the User. \* A User wants to be able to automatically add appoints to Google Calendar when a meeting is booked in your Bubble-built CRM. The User grants your app access to their Google account your app is issued a token that lets your app make changes to the User's calendar as needed. \* An enterprise clients wants to allow your app to access resources from their server without giving them actual login credentials. They use OAuth2 to issue a token to your app that you can use for subsequent calls. Object / JSON Object A JSON object is a way to structure data in a way that both computers and humans can easily understand. An object can consist of multiple \*\*keys\*\*, and each key has a \*\*value\*\*. This is often called a key-value pair. In Bubble, consider the \*User\* data type as an example. When you examine a User in Bubble, you'll notice it consists of various built-in and custom fields like email, name, and phone number. These fields act as keys in a key-value pair, and the specific information for each user (their actual email address, name, and phone number) represents the values. In JSON, a user object may look something like this: \`{\`\\ \`"user": {\`\\ \`"first\_name": "Ana",\`\\ \`"last\_name": "Silva",\`\\ \`"email": "ana.silva@example.com"\`\\ \`}\`\\ \`}\` As you can see, this is perfectly readable for a human, but the consistent structure also means computers can easily read it. The similarity to Bubble is not a coincidence – in fact, Bubble downloads data to the page in a JSON structure. This is why Bubble communicates with other apps and systems so easily – because JSON is a widely used format. Payload The payload refers to the data sent with the request. Depending on the \[HTTP method\](#http-method) used, the payload can be part of the request body (as in a POST, PUT, or PATCH request) or within the URL itself (as in a GET request with query parameters). For most API interactions that involve the transmission of data (like creating a new user or updating a record), the payload carries the necessary information. #### \*\*Example:\*\* Imagine you're creating a new user in a system using an API. The API documentation specifies that the endpoint expects data like a username, email, and password. The payload for this API call might look something like this: \`{\` \`"username": "johnDoe123",\`\\ \`"email": "johndoe@email.com",\`\\ \`"password": "securePassword123"\` \`}\` In this example, the \[JSON\](#json) structure containing the username, email, and password is the payload. When making a POST request to the API endpoint, this payload would be included in the body of the request. The API server processes this payload and performs the necessary actions, such as creating the user in the database. Resource A resource is a specific data object or service that is made available by an API and can be accessed via a unique endpoint using methods such as GET, POST, PUT, and DELETE.\\ \\ For example, if you are trying to access data about a specific User in your Bubble app from an external application, the \*User\* endpoint can be considered a resource. The same can be said about a specific API Workflow.\\ \\ In other words, a resource represents a specific piece of information or functionality that an API can provide.\\ \\ \*\*Other ways to learn:\*\*\\ Article: \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) Request/Response In an API call, the \*\*request\*\* is the data sent from the client to initiate the connection. It contains all the data needed to authenticate and instruct the server what the request is about.\\ \\ The \*\*response\*\* is the data sent back from the server to the client in response to the request.\\ \\ \*\*Further reading:\*\* Article: \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) RESTful APIs that are RESTful mean that they are built on a set of architectural principles for building web services known as \*Representational State Transfer (REST)\*. Most commercial and public API services adhere to these principles.\\ \\ In short, this is a way to ensure that APIs that communicate with each other are compatible, or "speak the same language" if you will. Bubble's API and the API Connector is built around RESTful principles, which means it can connect to almost any web API.\\ \\ \*\*Other ways to learn:\*\* Article: \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) Token A token is a string that identifies the client sending an API request.\\ \\ In the case of \*\*incoming\*\* requests (The Data API or Workflow API) the token is issued by Bubble.\\ \\ In the case of \*\*outgoing\*\* requests (The API Connector) the token is issued by the server you are connecting to. #### How are tokens different from username/password? A token is a unique, randomly generated string that confirms a user's session or authorization, usually given \*after\* the first login. It lets users access services without constantly inputting their username/password, enhancing security. Think of it like this: If a user logs into your app using Facebook, they don't hand over their Facebook login details to your app. Instead, Facebook verifies their login and hands your app a token as proof. A key advantage is that tokens can be swiftly revoked, making them more secure and flexible compared to the traditional username/password method, which can be tedious to alter.\\ \\ \*\*Other ways to learn:\*\*\\ Article section\*\*:\*\* \[What is a bearer token?\](/help-guides/integrations/api/the-api-connector/api-guides/openai/authentication.md#the-bearer-token) \[^1\]: The \*API Connector\* is a plugin that allows you to set up outbound API calls to external apps and services from your app. Article series: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/api-glossary.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/static-data/app-texts-translations.md). # App texts (translations) App texts, short for \*Application texts and messages\* is a sort of database for text strings that you can use around your app. It can be used for a single language, but Bubble also lets you translate all the strings into different languages to offer your users a multilingual app. Application texts are a part of Bubble's \*static data\* features. This means that they are not dynamic, like the database, and that the app needs to be redeployed every time something changes. As such, they are not meant to store long strings of text like articles and product descriptions, but shorter content like headers, menu options and button labels. {% hint style="warning" %} Application texts become part of your application's codebase and is downloaded to every user on page load. You should never use these strings to store sensitive information. {% endhint %} ## Assigning application texts Application texts can be used in any expression, meaning that it can be assigned to any element property that accepts dynamic texts: this includes text elements, labels on buttons and checkboxes, text input fields, tooltips an many other places. ![](https://manual.bubble.io/files/wrd0gDKfoUDlHFj8LMGo) The editor will show the text \*App text (\\\[name\])\* and the app will show the string you have saved in the app text editor in the currently active language. ![](https://manual.bubble.io/files/u2tcWZ0VRbpSHZh20Zjr) Application texts can be used in any dynamic expression. In the screenshot above we're using an app text called _My input_ as the placeholder for a text input element. This also means you can use them in workflows, element conditions and any other place where you can insert a dynamic expression. In the example above, we have selected \*App text\* as the data source, and \*My input\* as the operator: this is the ID of the particular string we want to show, which means it needs to be created first. ## Editing application texts To access the application text editor, go to \*Settings - Languages.\* Under \*General settings\* you will find your app's default language and the field on the user that determines the user's language preference (more on that below). Under \*Application texts and messages\* you will find all the custom text strings that you have added (if any) as well as Bubble's core texts. The left column is the ID of the text. In the example from earlier, the ID of the text was \*My input\*. We'll find this ID and ![](https://manual.bubble.io/files/kVZxEEOFdoVeOm2CiWKP) The strings ID is on the left side, and the string that will be displayed to your users is on the right. Click the image to enlarge. \### Core texts The core texts are the text strings that Bubble includes by default. You can change their string, but they can't be deleted and their ID remains static. These strings cover different error/informational messages connected to Bubble's core functionality. These built-in texts are already translated into all the available languages. ### Element strings Some elements and plugins also add text strings that become available at the bottom of the list. For example, the multi-file uploader plugin adds standard texts such as \*Cancel upload\* and \*Remove file\*. ## Exporting and importing translations Bubble also lets you export all the language strings to a CSV file and then re-import the file after having made the needed adjustments to it. This way you can efficiently invite other users to translate the strings without giving them access to the Bubble editor. 1. Click the \*Export\* button and download the CSV file that Bubble generates 2. Make the needed adjustments to the file, but make sure that no text ID's are changed and that the columns remain exactly as they were when you downloaded the file 3. Click the \*Import\* button and select the finished file. {% hint style="warning" %} Importing a CSV file will overwrite all strings, even if the cell in the CSV file is left empty. If you want to keep a string as it was upon export, make sure it remains in the file. {% endhint %} ## How Bubble determines the language Bubble determines the app's current language based on the following hierarchy: 1. The "lang" parameter in the URL if it is set 2. The current user's language if the field exists and is it's value is valid 3. The application primary language 4. English ## Adding multiple languages Application texts are set up for multiple languages, and uses the \[IETF language tag\](#user-content-fn-1)\[^1\] language codes to identify each language and dialect. ### Setting the main language The main language is the language that is used by Bubble to run your app when no language setting is set. This language will be used to define the messages that your application can send and show to users and change how location-sensitive elements behave. For instance, it will impact how dates are formatted in the Date Input element and the Calendar element or the map element's captions. ### Setting the language field on the User Users in Bubble don't have a language setting field built in, but lets you set one up if you need it. The name of the field is not important, but the field must return a valid IETF language tag to work – in other words, the field must contain a text that matches one of the abbreviations in the dropdown. ![](https://manual.bubble.io/files/Nzlteh9U2tk84YaCT6lz) The language field on the user must return one of language codes in the language dropdown, such as fr\_fr. When you have set up the field, you assign that field to control the user's language setting with the dropdown \*Language field on the user type\*. Select the field you set up, and Bubble will automatically respond to the value in the field to display strings in the user's language. ![](https://manual.bubble.io/files/YuWcfsWR7SoulzYWLNlS) In this example we have created a field called _Language_ of type _text._ This particular user has the code ar\_ar, which means they have selected Arabic as their language. If the field is empty, Bubble will default to the language set in the \*Application primary language\* dropdown. ### Setting the language with a URL parameter The application language can also be set in the URL, by using the lang query string parameter. This means adding \`lang=code\` to the URL, where \`code\` is the standardized language code, i.e. the one found in Settings > Language (most, but not all, of these codes have the format of two characters, underscore, two characters). For instance, using Russian in your app would be done by hitting this URL \`https://myapp.com?lang=ru\_ru\`. ## FAQ: Application text #### If a text string is not translated into the active language, what will Bubble display? If the user has selected a language and a string on the page has not been translated into that language, the text \*(no translation)\* will be displayed instead. Bubble's error console in the bottom right corner of the debugger will also flag a warning when you preview the page. #### What happens if the language field on the user is empty? If you have set a field on the user to be a language field and that field is empty or returns an invalid language code, Bubble will default to the language set in the \*Application primary language\* dropdown. #### How do application strings affect performance? The application strings you add become part of your applications JavaScript source code files. This means that they are downloaded to every user that opens up any of your pages. For performance reasons, Bubble only downloads the text in the language that the user has selected – this is why changing the language on the user requires a page load so that the updated JavaScript file can be generated and downloaded. Application strings are no more performance-taxing than placing the string directly on the element; if they are used in multiple places they are more lightweight, since they only need to be stored once. Even if you don't plan to translate your app it can be useful to maintain all your strings in one place. #### Do Application texts support right-to-left writing (RTL)? Yes, Application texts support RTL languages such as Arabic, Hebrew and Urdu. Note that you may need to tweak your app design if you plan to switch between LTR and RTL languages, so we recommend testing your application in both languages. {% hint style="danger" %} \*\*Known Issue: right-to-left (RTL)\*\* When displaying text in a right-to-left (RTL) format and applying certain operations or changes, the text might switch back to a left-to-right display. If you're prioritizing RTL support, we recommend previewing your pages in run-mode to ensure they display correctly. {% endhint %} #### I have made changes to app texts, why are the changes not visible in the live app? If you can't see the changes you've made, please check the following: \* Changes in app texts are visible as follows: \* Development: after the page is refreshed \* Live: after the app has been deployed and page has been refreshed \* Check that you are viewing the app in the same language as the string you have changed \* Check that the \*Saving\* indicator next to the edit menu is showing \*Saved\* to confirm that the change has been synced to the Bubble server. If not, please check your internet connection. ## App texts in native mobile apps ## App texts (translated text strings) The \[app text feature\](#user-content-fn-2)\[^2\] is supported in native mobile apps, allowing you to localize content based on the device’s language settings. {% hint style="info" %} On web apps, Bubble normally determines which language to display using a \`language\` field on the User data type. In mobile apps, this behavior differs: the app references the \[\*\*primary language set on the user’s device.\*\*\](#user-content-fn-3)\[^3\] {% endhint %} #### How it works When a mobile app launches, Bubble compares the device’s primary language to the list of \*\*supported languages\*\* defined in your app’s mobile settings. If a match is found, the corresponding App Text translations are used. If not, the app will display content in the \*\*primary app language\*\*. You can manage supported languages under the Mobile settings section of your app: ![](https://manual.bubble.io/files/czimGqs1XNnbyb9TlPBh) You can add languages and dialects in the _Settings –_ _Supported languages_ section of your app. \#### Supported languages and dialects Some languages have regional variations, known as dialects. For example: \* \`fr-FR\` (French – France) \* \`fr-CA\` (French – Canada) \* \`fr-BE\` (French – Belgium) Bubble supports setting specific dialects for each supported language. However, a user’s device might only report a \[base language\](#user-content-fn-4)\[^4\] code such as \`fr\` without a region-specific code. To handle this, Bubble includes a \[\*\*fallback language\*\*\](#user-content-fn-5)\[^5\] setting that determines which dialect to use if the device only provides a base language. \*\*Example\*\* If you support \`fr-CA\` and \`fr-BE\`, and a user’s device reports only \`fr\`, Bubble will use the fallback dialect you’ve specified—such as \`fr-CA\`—to display translated App Text. #### Behavior summary \* Mobile apps use the \[device’s \*\*primary language\*\*\](#user-content-fn-3)\[^3\] rather than a user-defined setting. \* If the device language \*\*matches a supported dialect\*\*, that translation is shown. \* If it matches a \*\*base language only\*\*, Bubble uses the \*\*fallback dialect\*\* you’ve defined. \* If no match is found, the app defaults to its \*\*primary language\*\*. #### Updating your app \* If you add supported languages, these can be included in an \[over-the-air (OTA) update\](#user-content-fn-6)\[^6\]. \* For the translations defined in the system-level prompts (like permissions messages), a new build is required, as these values are \[compiled into the native binary\](#user-content-fn-7)\[^7\]. \[^1\]: IETF language tag is a list of language codes widely used on the internet.\\ \\ It combines different standards such as ISO 639 to to distinguish language variants such as British English (en\\\_gb) and American English (en\\\_us). IETF (the Internet Engineering Task Force) is an organization that works to create voluntary standards for the internet. \[^2\]: The \*app text\* feature lets you set up static strings for your app in different languages. Article: \[App texts\](/help-guides/data/static-data/app-texts-translations.md) \[^3\]: The top language set in the user’s device settings. This is the language the operating system uses for menus, apps, and system messages. \[^4\]: The general form of a language without any regional variation—such as "fr" for French, without specifying a dialect like "fr-FR" (French – France) or "fr-CA" (French – Canada). \[^5\]: A backup language used when the device’s language matches a base language (like "fr") but not any of the specific dialects you've added (like "fr-CA" or "fr-FR"). \[^6\]: An update that can be pushed to users without requiring a new build or app store approval. Changes take effect automatically the next time the app is opened. Article: \[Publishing your app in iOS App Store\](/help-guides/publishing-your-app/native-mobile-app/ios-app-store.md#ota-over-the-air-updates-quick-changes) \[^7\]: This text is included directly in the app’s packaged code, meaning it can’t be changed without creating a new build and resubmitting it to the app stores. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/static-data/app-texts-translations.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md). # Using Algolia Bubble has an integration with \[Algolia\](https://www.algolia.com/), a third-party search-as-a-service provider. Bubble apps using this integration have their data sent to Algolia for indexing, and use Algolia as a data source to power elements like repeating groups and searchboxes. ## Benefits of Algolia What are the benefits of using Algolia? A noticeable one for your users is speed - Algolia searches are fast, and noticeably faster than Bubble native searches at scale. A second one is customizability - Algolia allows you to tweak the search algorithm, among other parameters as well. Note that unlike a plugin which must be installed, this integration is built natively into the editor, much like Bubble’s integrations with Google Maps and Google Geocode. ## \*\*Who should consider this\*\* [](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md#who-should-consider-this) Bubble does have native search capabilities, but Algolia provides a more performant and customizable search experience at scale. Users of this integration will also need their own Algolia plan (though Algolia also offers a free tier). In other words, Algolia is more suitable for Bubble apps at a large scale that rely on search as an important part of their user experience; thus, this feature is only available for Bubble apps on the Professional plan and above. ## Setup [](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md#setup) To start off, you must have your own Algolia account and copy your Algolia keys into your app’s Settings. When creating an Algolia account, you \*\*do not\*\* have to create indices yourself. Instead, right after signing up, you should visit the "API Keys" section of the dashboard. You will see a screen like this: !\[\](https://s3.amazonaws.com/appforest\_uf/f1585840673248x789535177939069300/algolia\_keys.png) In your Bubble app, in Settings > General in the "General services API Keys" section, there is a checkbox for "Enable searching with Algolia" (if you do not see this checkbox, your app does not have this feature, chances are because it is not in the right tier). Once you check the box, you will see input fields for the application ID and two keys from the Algolia dashboard. Once you've copied and pasted those values in, the Bubble app will confirm that it thinks the keys are of the correct format (note the green text below): !\[\](https://s3.amazonaws.com/appforest\_uf/f1585840814678x830973864721420500/algolia\_settings.png) The other parts of the Algolia feature mentioned below will not appear until valid keys and an application ID have been supplied in Settings. ## I\*\*ndexing\*\* [](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md#indexing) After keys have been added, in the Privacy tab for every data type, you’ll see the option to index that type with Algolia. !\[\](https://s3.amazonaws.com/appforest\_uf/f1585840930894x345364301566459140/algolia\_privacy\_tab.png) If a data type is indexed to Algolia, Bubble will send \*\*all public fields\*\* to Algolia, i.e. the fields that are visible via search in the “Everyone else (default permissions)” Privacy rule. Bubble will automatically create the necessary indexes in Algolia for you - \*\*you should not rename those indexes\*\*. In addition, make sure that the data type being indexed has \*\*"Find this in searches"\*\* under the "Everyone else" permission checked. After you toggle a data type to be indexed by Algolia (checkbox on the right), you will probably want to trigger an indexing of all the things of that type. You can do so in the modal accessed at the top of the Privacy page for any indexed type. !\[\](https://s3.amazonaws.com/appforest\_uf/f1585840975838x691412509932716700/algolia\_indexing\_modal.png) You can choose to trigger a full indexing of all indexed types or just one type, and you can choose to do this for your Development database ("test"), Live database, or both. Note that doing a full indexing could take noticeable capacity over a period of time (depending on how many things there are), so the recommendation is to trigger a full indexing once after adjusting all your data types’ settings, and to do it at non-peak hours. Behind-the-scenes, the full indexing runs the same process as a large CSV data export, so you can actually see the status of these tasks in App Data > Export. When things of an indexed data type are changed, added, or deleted, Bubble will automatically try to update the corresponding Algolia index for you. This should be generally reliable, but in the event that you find Algolia “out of sync” with your Bubble database, you can always trigger a full re-indexing in the same way as above. During set-up, after you run the first indexing, we recommend you check the Algolia portal to make sure that you're seeing the records you expect in the newly created indices. ## S\*\*earching\*\* [](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md#searching) Once you’ve activated Algolia for your app, you will see a new data source, “Search with Algolia”. For example, this can be the data source for a repeating group, or the “Choices style” for a searchbox. The Algolia data source also lets you choose to query over a specific field, or all fields of a data type. You cannot change the sort order of an Algolia result in Bubble because that is controlled in Algolia. After all, we are relying on their search expertise, manifested in their algorithm! You are able to customize the Algolia search algorithm for a particular index via the Algolia dashboard. For example, you can change the weights of different fields in the search algorithm. Note: one limitation of the current integration is that you should not set two fields as “equal weight” in the Algolia interface. {% hint style="info" %} Note that the default setting in Algolia is to return 20 entries in the first 'page' of the search. At this time there's no way for your Bubble app to access other pages of results, but you can change the number of results in the first page by going to the Algolia portal > the appropriate index > Configuration > Pagination. {% endhint %} ## Known limitations [](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md#known-limitations) This is the v1 of the Algolia feature. It has these known limitations: \* This only supports \*\*text\*\* and \*\*number\*\* fields. For all other field types (including fields which are other custom data types), Bubble will make a "best effort" attempt to send those fields to Algolia, but it will likely not be sensible. To restate explicitly, the Algolia integration is not meant for other fields like dates, geographic addresses, ranges, Users, or fields that are other custom data types. \* This only supports \*\*public data fields\*\*, so it is not good in situations where data privacy is very important, e.g. when you want to prevent one user from seeing another user's data. For example, it is good if you have a short-term rental marketplace app where all users can see any rental on the app. It is not good for an e-commerce experience where you have many vendors and you want to build a search for only one vendor's products. \* Algolia has limits on the size of certain fields. If Bubble detects that a given Thing has a field that is too long (text fields are the most likely culprit), it will automatically clip them for you so that it can be sent to Algolia. This can be disabled in Settings, but should only be done so by advanced users who are accounting for this in Algolia's settings. \* In Algolia's settings, you may see an option to rank two fields as "equal weight" - please \*\*do not\*\* do this, as it will break the Bubble integration. \* Bubble will automatically create the indices in Algolia - please \*\*do not\*\* change the names of these indices, though you are free to adjust other settings as desired. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/the-database/using-algolia.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/slack-plugin.md). # Slack plugin ## What is Slack? Slack is a business communication platform offering many features like chat rooms, direct messaging, and integration with various third-party services. It's widely used in professional environments for team collaboration and communication. The plugin lets your end-users sign up and log in with Slack, access Slack data, and perform actions as a Slack user or bot, such as sending messages and posts. ![](https://manual.bubble.io/files/aVAV8brF8AXaTxBym2YA) 1\. First, open the \*Install new plugins\* screen in the Bubble editor. 2. To find this plugin, search for \*Slack\*. Optionally, you can check the \*Login service\* checkbox to further filter the results. You can also scroll to the bottom of the filters list, under \*Built by\* and select \*Official\* to single out official plugins. 3. Check that the Bubble logo is visible in the bottom-right, and then click \*Install.\* ### Setting up and configuring the Slack API External documentation To set up an account and generate and manage the credentials, please follow the up-to-date directions provided in the official Slack Developer documentation. External page: \[Slack for Developers\](https://api.slack.com/docs) The Slack API follows a common pattern of requiring two different keys to authenticate your app. \* \*\*API key:\*\* The App ID (also referred to as the API Key in some contexts) is essentially the public identifier for your app. Think of it like the name tag your app wears when it talks to Slack. In this context, it's not to be confused with your secret access token: In fact, the Client ID doesn't need to be kept secret. \* \*\*Secret key:\*\* The Secret Key, on the other hand, is like a password. It's used to secure communication between your app and Slack's servers. Exposure of the Secret Key can lead to security risks, unlike the App ID. ## Setting up the Slack plugin After installing the plugin, you'll find it in your list of installed plugins and can click it to access its settings: ![](https://manual.bubble.io/files/DDwBYRmIqNjT8XCryonq) \## Actions, elements and data sources To see the plugin's actions and data sources, as well as their properties, please see the core reference article below: Reference: \[Pinterest\](broken://pages/jHperPW6Cal3msovwvnI) ## FAQ: Slack plugin #### What should I do if I accidentally expose my Client ID? The Client ID is a public identifier, and does not need to be replaced if it's exposed. #### What should I do if I accidentally expose my secret key? The secret key should be kept securely private, as exposure can lead to security risks. We strongly recommend revoking the exposed key and creating a new one immediately. Remember to deploy the changes in your app to Live after replacing the secret key. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/slack-plugin.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/temporary-data/url-parameters.md). # URL parameters A URL parameter is a piece of information that you place in the browser's URL. They follow a key-value-pair\[^1\] structure and can hold many different types of data. {% hint style="warning" %} Due to Bubble's internal logic, \*\*avoid\*\* using the following strings as \*\*keys\*\*: \* id \* debug\\\_mode \* resume {% endhint %} ## How URL parameters are structured Every page in your application (except for the index page) has its own URL that follows a regular pattern: \`\`\` https://my-bubble-application.bubbleapps.io/mypage \`\`\` or if you have connected to a domain: \`\`\` https://www.mydomain.com/mypage \`\`\` This points the browser to the right domain and to the right page. The information in that URL is actually an instruction to the \*server\* to send the correct page back to the browser. In other words, your browser \*sends\* that URL to the server, which responds by sending back the files needed to display the page. URL parameters also serve a function, but instead of talking to the \*server\* they can send messages to the current \*page.\* In other words, your Bubble app can write and read URL parameters in the browser's URL bar and use that information for different purposes. URL parameters are listed after the complete page URL, and are separated from that URL with a question mark (?). If there are multiple parameters, they are separated from each other with an ampersand. ![](https://manual.bubble.io/files/yhu39r3dh15RDrMxqlR3) Each URL parameter consists of a \*\*key\*\* and a \*\*value\*\*: \* The \*\*key\*\* identifies the parameter with a unique string of text such as \*name\* \* The \*\*value\*\* is the data that the parameter holds, such as \*John\* The structure would then look like this: \`\`\` name=John \`\`\` If we place that in the full page URL (and separate it from the URL with a \*?\* as we explored earlier) we get: \`\`\` https://www.mydomain.com/mypage?name=John \`\`\` Now to add slightly more complexity, let's change the \*name\* parameter to \*firstname\* and add a second parameter called \*lastname\*. \`\`\` https://www.mydomain.com/mypage?firstname=John&lastname=Doe \`\`\` In this last example, Bubble would be able to identify the full name \*John Doe\* from the URL bar. Let's have a look at how that happens. ## Reading URL parameters {% hint style="warning" %} \*\*Note\*\*: There are some \*\*plugins\*\* that can manipulate the browser's URL bar, including its parameters. It's worth noting that Bubble does not always catch updates to parameters if they are not made with the \*Go to page\* action.\\ \\ Recognizing the change may require a page reload or the plugin may be able to return an updated value. {% endhint %} As we've covered, the URL parameter consists of a key and a value, and we need to instruct Bubble what \*key\* to look for in order to get the value in return. To do that, we set up an expression where we use the \*Get data from page URL\* \[data source\](#user-content-fn-2)\[^2\]. ![](https://manual.bubble.io/files/otPD9d3StQbZZBykQNIC) After picking the data source, Bubble will ask for some additional parameters: ![](https://manual.bubble.io/files/n2egwI3Ud1bkKieR5bCO) 1\. The first one is the \*\*key\*\* to identify our parameter. We want to fetch the first name (John), so we'll set that to \*firstname\*. 2. Secondly, we need to tell Bubble what kind of data to expect. We can set this to \*text.\* As soon as you set the key, you can see on the right side that Bubble updates the expression to say \*Get firstname from page URL.\* If the parameter \`name=John\` exists in the URL, the text element will show the name John to our users. If the URL parameter can't be found or has an empty value, it will display nothing. ## Reading different data types In the example above we used the text data type to read a simple piece of information: a name. But URL parameters can also be used to read other types of data. {% hint style="info" %} Bubble's general data types (text, numbers, dates, etc) need particular formatting in order to ensure compatibility with all browser. Bubble automatically applies the correct formatting in most cases, but if you have hardcoded links or want to learn more about how the different data types are formatted, check out the info-box below. {% endhint %} Formatting Bubble's general data types in a URL parameter #### Text/numbers/Geographic address/file/image Text and numbers can for the most part be added just like you want them to appear when you read the value, but special characters may give you problems with some browsers. To ensure compatibility, you can include characters that are not normally valid in a URL by encoding them using percent-encoding. In percent-encoding, characters are converted into a sequence of characters. For example, the character / is converted to %2F, and the character ' is converted to %27. Let's say we wanted to encode the product header \*O'Donnel t-shirt in white/blue.\* We have three special characters: space, ' and /. {% code overflow="wrap" %} \`\`\` https://www.mydomain.com/mypage?productname=O%27Donnel%20T-shirt%20in%20white%2Fblue \`\`\` {% endcode %} When you use the \*Go to page\* action to add a URL parameter, Bubble \*\*automatically encodes\*\* the string as needed. If you set up hardcoded links, you may need to add percent-encoding manually. You can use Bubble's format as URL operator to convert a text to the right format. Files and images contain the URL string, and also needs to be formatted with percent-encoding. #### \*\*Numeric range\*\* Numeric ranges can't be passed as a single data type. Instead, you should break the range into its minimum and maximum number into to separate number parameters. For example, you can add a parameter called \*min\* with the value 1 and another called \*max\* with the value 5. Then when you need to reference the range you can use the \[\*range\* operator\](#user-content-fn-3)\[^3\] to combine the two values into a valid numeric range. #### Date Dates have the following format: \* \*\*\*Format:\*\* Month Day, Year Hour:Minute am/pm \*\*or\*\* M/D/YYYY h:mm am/pm\* \* \*\*Example:\*\* Jan 1, 1970 8:50 am Dates also need percent-encoding, which Bubble will automatically apply: \`\`\` Jan%201%2C%201970%208%3A50%20am \`\`\` %2C represents a comma (,), %3A represents a colon (:), and %20 represents a space. #### Date range Date ranges, like number ranges, need to be passed in two separate values, such as \*startdate\* and \*enddate\* and then combined with the \[\*range\* operator\](#user-content-fn-4)\[^4\]. Dates need to be passed with percent-encoding as described in the \*Date\* section. #### Date interval Date interval is passed as the number of milliseconds between to datetimes. #### Yes/ no Yes/no values are passed as written out: \*yes\* or \*no.\* \### Custom data type things You can also link to a custom data type in a URL parameter. To read and retrieve the correct thing, that thing's Unique ID needs to be present in the parameter. The name (key) of the parameter does not affect the result, but when you use the \*Get data from page URL\* data source you need to set it to the correct data type, as exemplified below: ![](https://manual.bubble.io/files/EJ8CbFQXXecT10a1wbpM) 1\. First we set the name (key) that identifies the right parameter 2. Then we set the \*type\* to the data type of the thing we want to retrieve 3. Bubble then lets you add operators to the \*Get data from page URL\* data source relevant to that thing. In the example we are getting the name of the Task. The URL in this case would look like this: \`\`\`url https://www.mydomain.com/mypage?task=1676895495518x833172344879202800 \`\`\` ### Option sets You can also retrieve an option from an Option set. Option sets do not have Unique ID's but are identified by the value stored in the \*Display\* field. Just like with data types, you can give the parameter an arbitrary name, but you need to set the \*type\* to the Option set you want to retreive. ![](https://manual.bubble.io/files/LFFIFZQAMLOOR4dN5PBJ) 1\. First we set the name (key) that identifies the right parameter 2. Then we set the \*type\* to the Option set we want to retrieve 3. Bubble then lets you add operators to the \*Get data from page URL\* data source relevant to that Option set. In the example we are getting the abbreviation of the State. The URL in this case would look like this if we included the state name in the Display field: \`\`\` https://www.mydomain.com/mypage?state=Texas \`\`\` ## Setting URL parameters There are two ways to pass URL parameters to a page: 1. The first is to \*\*include it with the URL when the page loads\*\*, for example by linking to the page with a URL that includes the parameters. Simply copy/pasting the URL into a link will have Bubble recognize the parameters on page load. 2. The second is to use the \*\*\*Go to page\*\*\* \*\*action\*\* and checking \*Send more parameters to the page.\* This will apply the necessary encoding to whichever information you provide and send the parameter. ![](https://manual.bubble.io/files/KD2Q9yHEhVrYgmFl9xAb) The Go to page action lets you send the parameters by adding them in a list as illustrated above. The left-hand input field is the _key_ and the right-hand field is the _value._ If you remain on the same page, the page will not be reloaded, but the parameters will be instantly updated. {% hint style="info" %} The \*\*Go to page\*\* action does not reload the page if you are going to the same page that you are already viewing. This means you can set and change URL parameters as much as needed without the page having to be reloaded. {% endhint %} ## FAQ: URL Parameters #### Can you pass a list of Things in a URL parameter? You can only pass one value at a time in each URL parameter (but you can create as many parameters as you need, within the maximum URL length supported by the browser). There may be workarounds to pass lists, but it's not officially supported by Bubble at this point. #### Are URL parameters secure? URL parameters are not insecure by and of themselves, but they can require that you understand the potential vulnerabilities associated with using them. For example: \* They are fully editable by your users, meaning that they can add, remove and change URL parameters as they want. \* They are of course also fully visible in the browser's URL bar, meaning that they should never contain any sensitive data \* When used for navigation, keep in mind that a tech-savvy user can pay attention to the URL parameters and understand their structure: if you don't secure your navigation in other ways the user may be able to access sections they are not supposed to \* When including custom data types in the URL, you are revealing the Unique ID of that thing. Again this is not a vulnerability on its own, but can \*lead\* to vulnerabilities. Someone could for example replace the Unique ID in the URL to see a record that's not their own: the things needs to be protected with Privacy Rules \[^1\]: A key value pair is a way of storing data. It consists of a \*key\* and a \*value\*.\\ \\ In the context of URL parameters, the \*key\* is the name of the parameter, and the \*value\* is the value. For example:\\ \\ ?name=john\\&age=56 In this example, the \*keys\* are \*name\* and \*age\*, and the values are \*john\* and \*56\* \[^2\]: A \*data source\* is any source from which Bubble can pull in data, such as a database search, the current user or an API call. We can then narrow down the data from that source if needed using \*operators.\*\\ \\ In the context of URL parameters, we are asking Bubble to use the URL as a data source. \[^3\]: The \*range\* operator Generates a number range from two numbers and returns a range whose lower bound is the smaller of the two numbers and the higher bound is the larger one.\\ \\ Reference: \[The range operator\](/core-resources/data/operations-and-comparisons.md#less-than-range-greater-than) (numerical) \[^4\]: Generates a date range from two dates. This represents a span of time from the moment of the first date to the moment of the second date. Date ranges are a useful tool for representing availabilities or time slots. Reference: \[The range operator\](/core-resources/data/operations-and-comparisons.md#less-than-range-greater-than-1) (date) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/temporary-data/url-parameters.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab.md). # Settings tab The Settings tab lets you control key configuration options for your app. You’ll find options for general app info, privacy, API services, SEO, language, Bubble version, workload and features specific to mobile apps—all in one place. Use this section to manage how your app behaves, appears, and connects with users and external services. Settings in this tab apply to the current app only—they do not affect your overall Bubble account. ## Sections ### App plan Manage the plan your app is on, paid plugin subscriptions and file storage. Article: \[Pricing and Workload\](/account-and-marketplace/account-and-billing/pricing-plans.md)\\ Page: \[Bubble pricing\](https://bubble.io/pricing) (comparison of the different pricing plans) #### General General app settings such as: \* Privacy and security \* General appearance \* \[General services API keys\](#user-content-fn-1)\[^1\] (such as Sendgrid and Google Maps) \* \[Custom fonts\](#user-content-fn-2)\[^2\] \* \[Importing Figma designs\](#user-content-fn-3)\[^3\] \* \[Optimize app\](#user-content-fn-4)\[^4\] ### Domain/email This is where you can connect your app to a domain and configure its \[DNS settings\](#user-content-fn-5)\[^5\]. This is also where you set your app's email settings and \[SSL/TLS configuration\](#user-content-fn-6)\[^6\]. Article: \[Custom domain and DNS\](broken://pages/Sfb2EVgX6WfgYIibQCNa) ### Languages The Languages tab lets you translate static strings in your app into different languages and manage the settings for how users change their language. Article: \[App texts (translating your application)\](/help-guides/data/static-data/app-texts-translations.md) ### SEO / metatags This is where you'll find settings for SEO and social media sharing. In here you can manage: \* Title, description and image for social media \* Custom header and body \* 301 redirects \* Files in the root folder \* robots.txt and other SEO-related settings Article: \[Social media sharing\](broken://pages/-MUUJGGgXT-x5NrF7ttC)\\ Article: \[Email settings\](broken://pages/-MUUNYlJhe5tqMARhsWS) ### API In the API section you can modify \[your app's API settings\](#user-content-fn-7)\[^7\]. Article: \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md) ### Collaboration The Collaboration section lets you add other Bubble users to collaborate on your app, as well as controlling the access level of each collaborator. This is also where you transfer app ownership to another Bubble user. Article: \[Collaboration\](/help-guides/maintaining-an-application/collaboration.md) ## Other ways to learn Core reference \* \[The settings tab\](/core-resources/bubbles-interface/settings-tab.md) Video lessons \* \[How to set up a custom domain\](https://www.youtube.com/watch?v=vGk6nfq41L4) \[^1\]: Some of Bubble's features, such as sending emails and displaying maps, rely on external API services.\\ \\ You may need to enter your own API key for these services to work. This is handled in the general settings section. \[^2\]: Bubble comes with a lot of fonts built-in, but you can also implement your own using the custom fonts feature. Article: \[Using custom fonts\](/help-guides/design/variables-and-styles/using-custom-fonts.md) \[^3\]: Figma is a third-party design tool often used to create design drafts for applications. Using this feature you can import the design directly into Bubble.\\ \\ Article: \[Importing Figma designs\](/help-guides/design/importing-from-figma.md)\\ External page: \[Figma website\](https://www.figma.com/) \[^4\]: As you develop your app, you can end up with data that's no longer needed, such as unused styles, deleted option sets and data types and element properties. The Optimize app feature clears unused data from your app to make the codebase lighter. \[^5\]: DNS (Domain Name System) is a system that translates human-readable domain names (like bubble.io) into IP addresses (like 192.168.0.1) that computers use to identify each other on the internet. This is how a user's device connects to the correct server (identified by an IP address) when your app's URL is entered into the browser. \[^6\]: SSL (Secure Sockets Layer) and TLS (Transport Layer Security) are cryptographic protocols designed to secure network traffic by encrypting the data.\\ \\ In practice, this means that the data sent to and from the Bubble server to the user's device is encrypted and secure. Article section: \[The HTTP protocol\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol) \[^7\]: In this context, your app's API settings refer to \*inbound\* connections. You can read more about the Bubble API in the article below.\\ \\ Article: \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md)\\ \\ For outgoing requests to other systems, you need to use the API Connector plugin: Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/client-side-and-server-side.md). # Client-side and server-side Before we explore different categories of security related to Bubble directly, we need to highlight an important topic that will be mentioned repeatedly throughout this article series: the difference between \*\*client-side and server-side\*\* from a security perspective. When you run a Bubble app, two computers are working together to get the job done: \* The \*\*device\*\* you are using, such as a smart phone, tablet or computer \* The \*\*Bubble server\*\* which stores the database and performs many workflow actions Although third-party services like plugins, APIs and external database connections can introduce more systems into the mix, your device and the Bubble server are the two necessary components needed to make your app run. These two systems are what we are discussing when we're talking about client-side and server-side. ## Client-side Not all actions and expressions in Bubble need to be processed on the Bubble server. Client-side is an umbrella term for all operations that are handled on the user's device. While Bubble is a no-code platform, your app runs in all major web browsers: this means that we have to make the final app use code that browsers can recognize. In short, client-side operations: \* Take place in the user's browser. \* Include rendering the user interface, handling user interactions, and processing data before sending it to the server. \* Generally involve visual elements and user experience, such as animations, form validation, and user input. \* Can be less secure, as the code is accessible and can be manipulated by malicious users. ### Client-side security When a user starts loading your page, the server and the device (client) work in tandem to complete the job. It's useful when discussing security to get an understanding of what happens where, because the two sides have different security profiles. After all, while the browser hides this from you, a web application in the end is a collection of files and data streams that the server sends to the user's device. These files and data are stored on the device and the browser uses them to display things on the page and accept input. On the client-side, where users interact with the data, some information must be accessible and not encrypted; otherwise, it would be unusable. However, this doesn't mean the client-side is "insecure." Instead, the key is to recognize who or what is trusted with specific information. Client-side code is secure from third parties but is controlled by the visitors to the page. The challenge, therefore, is to balance the need to provide useful information to users (such as search results) and allow input (like form submissions) with measures like privacy rules and workflow conditions. These measures ensure that the server has the final say about what information is shared and how the data from users is validated, avoiding exposing information that the user is not supposed to see or interact with. Let's first have a look at what happens when a user loads a page in your app for the first time: ### Loading the page When you load a page in a Bubble app, your browser does a few things: \* It connects to the Bubble server using the \[HTTP protocol\](#user-content-fn-1)\[^1\], encrypted with TLS (https) \* It downloads various files to the user's device: \* HTML, CSS (files that dictate the appearance of the page) \* Images, fonts, and other media displayed on the page. \* JavaScript code that enables the app to function properly. \* built-in files generated by Bubble, that are required for the app to work at all \* plugin JS code loaded from Bubble's servers, generated from what the plugin author built in the plugin editor \* third-party JS loaded by plugins or by user-added custom headers (e.g. a Google analytics plugin might load and run JS files supplied by Google) \* Renders the page: The browser interprets the downloaded files and renders the page as specified by the HTML, CSS, and JavaScript code. \* Establishes a \[WebSocket connection\](#user-content-fn-2)\[^2\] \* This allows for real-time communication between the client-side browser and the Bubble server and makes sure the data on the page is dynamic and instantly updated if something changes \* Loads any necessary data: The browser fetches data from the Bubble database (and \[third-party APIs if needed\](#user-content-fn-3)\[^3\]) and displays the data in the elements on the page that reference it \* Listens for user input: The page is now loaded and the user can start providing inputs such as data in input elements and element clicks. Some of these actions are handled on the client-side, while others are sent to the Bubble server for processing (server-side) As we can see, a lot of data is moved from Bubble's server to the user's device when the page loads, and this is necessary for the app to run. ### Loading data Let's look closer at point number 5: \*the loading of necessary data\*. This means that Bubble checks the database for any data needed to display on the page. For example, if you are loading a page that shows a list of Tasks from the database, all the fields on the Task data type that the privacy rules allow the current user to see, are downloaded. This has some implications for your security: The data is encrypted on the server and while in transit\[^4\]. It is then decrypted on the device, and stored in the browser as plaintext. Bubble downloads all fields on a given data type. In other words, if you just show the Task name on the screen, Bubble still downloads all other fields to local storage. To protect specific things or their fields, you must set up Privacy Rules to stop Bubble from downloading it. All fields stored on the Current user (except those hidden by privacy rules) are always downloaded when the page loads, regardless of how you set your app up The fact that the data is downloaded to the local device does not mean the user can freely tamper with it: that part is still securely handled on the server. It just means the data can be viewed. ### Client-side processing Many actions that you run in your app do not need to be sent to the server to be completed – indeed, many of them can't be processed on the server since they refer to things happening locally on your user's device. For example, events, actions and conditions such as the ones listed below will in many cases be completed locally: 1. Navigating between pages by use of the Go to page action. 2. Displaying or hiding elements. 3. Changing the appearance or styling of elements (colors, fonts, etc.). 4. Validating user input in forms before submitting the data to the Bubble server. 5. Performing calculations or manipulating data locally. 6. Saving custom states with local content (such as user input) 7. Triggering animations or visual effects. 8. Running custom JavaScript code within the browser. 9. Do when condition is true where the condition does not happens server-side 10. Do every X seconds This is not an exhaustive list, and plugins can add more points. The list serves to illustrate that actions and expressions that don't rely on requests to the database will often be handled client-side, and as such can theoretically be tampered with. It's important to keep in mind that workflows can mix events, actions and conditions that do or do not rely on the server to complete: for example, a client-side event can trigger a server-side action and vice versa. ## Server-side On the Bubble server, things work differently. All data on the server (stored in your app's database) is securely encrypted, and server-side workflows are executed in a manner that keeps them safe from malicious interference. In short, server-side operations: 1. Occur on the Bubble server, away from the user's browser. 2. Involve processing, aggregating, storing, and retrieving data from the app's database, as well as running server-side workflows and performing calculations. 3. They are responsible for tasks like authentication, database queries, and executing complex logic. 4. Are more secure, as they are processed in a protected environment. #### Server-side processing Just like some operations can only happen on the client, others cannot happen without involving the Bubble server. For example, events, actions and conditions such as the ones listed below will need to be handled server-side: 1. Creating, updating, and deleting items in the database 2. Running server-side workflows (workflows that involve the database and API workflows) 3. Performing complex calculations, aggregation and data processing 4. Querying the database and filtering data 5. Managing user authentication and access control 6. Integrating with \[third-party APIs\](#user-content-fn-3)\[^3\] or SQL databases 7. Sending emails or other notifications to users 8. Handling file uploads and storage ## Conclusion What we can draw from these descriptions is a few simple conclusions: \* \*\*Data that reaches the user's device can be viewed by that user, even if it's not visible on the page\*\*: you need to control the flow of data that reaches the user device to make sure you are not sending \*more\* than the user is supposed to have access to. Privacy Rules take care of this. \* \*\*Workflows and conditions performed on the device should not be considered secure\*\*: you need to be aware of what kind of processing take place on the server and what takes place on the client With that understanding, let's move on to the more practical aspects of security. \[^1\]: \*HTTP (Hypertext Transfer Protocol)\* is the foundation of data communication on the web. It's a set of rules for transferring files (text, graphic images, sound, video) on the world wide web. Think of it like the language web browsers and servers use to talk to each other.\\ \\ Article section: \[The HTTP Protocol\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#what-is-the-http-protocol) \[^2\]: \*WebSocket\* is a communication protocol that enables two-way, real-time interaction between a user's browser and a server. Unlike traditional HTTP, which requires a new request for each file or bit of data, WebSocket keeps a single connection open, allowing for faster, continuous data exchange. It's like having an ongoing chat between the browser and the Bubble server. \[^3\]: When \*Make call from the client if possible\* is checked in the API Connector and certain conditions met, the client browser will call the external API directly from the client. Otherwise (and in the majority of scenarios), the client's browser will connect to the Bubble server, and the Bubble server will pass on the call to the external API.\\ \\ Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) \[^4\]: When data is \*in transit\*, it refers to the period when data is actively being transferred between two points, such as between your computer and the Bubble server.\\ \\ Think of it like a letter being carried by a mail carrier: while it's en route from the sender to the recipient, it's "in transit." Similarly, when you send or receive information online, that data is in transit until it safely reaches its intended destination. Data in transit is automatically encrypted using TLS. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/client-side-and-server-side.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api.md). # The Workflow API ## \*\*What is the Workflow API?\*\* The Workflow API is the part of Bubble's \[built-in API\](#user-content-fn-1)\[^1\] that lets you set up workflows that can be triggered from an external application or system by sending an API request or by scheduling an API workflow in your app. By constructing \[API Workflows\](#user-content-fn-2)\[^2\] just like you construct regular workflows on a page, you can make Bubble perform any kind of action or sequence of actions based on a request that can include parameters. For example, let's imagine you have a customer contact form on a website that's not part of your Bubble application. By sending an API request from that platform that includes parameters like name, email and phone number, you can use an API Workflow to create a new lead or register a new user in your Bubble app. API Workflows also lets your app respond to webhooks\[^3\] in other systems. For example, whenever a payment is made successfully in Stripe, you can set up a webhook in Stripe to trigger a workflow in your Bubble app so that any needed action can be taken immediately. ### What's the difference between API Workflows and Backend Workflows? As you start working in the Backend Workflow section of Bubble you may find the two terms used in different contexts. While they are certainly related, they don't carry the exact same meaning: \* \*\*Backend Workflows\*\* encompass all the different events that you can add in the Backend Workflow editor: \* API Workflows \* Backend Triggers \* Recurring Events \* Custom Events \* \*\*API Workflows\*\* refer specifically to the Workflows that you add by using the \*New API Workflow\* command in the editor. They are referred to as API Workflows whether they are public\[^4\] or not. ![](https://manual.bubble.io/files/W1n9Li9HQYVt3NHnFpJR) Backend Workflows is a collective term for all the different events you can create in the Backend Editor. \## \*\*Activating the Workflow API\*\* To activate API Workflows, go to Settings - API and check the \*Enable Workflow API and Backend Workflow\*. This exposes all workflows that have \*Expose as a public workflow\* checked. This also reveals your application's Workflow API root URL. ![](https://manual.bubble.io/files/JxCu3FHh7z9wbHxYn3um) \## \*\*Accessing the backend workflow editor\*\* When the Workflow API has been enabled in your application’s settings, you can navigate to the virtual page \*Backend workflows\* by clicking the icon in the left-hand menu bar. ![](https://manual.bubble.io/files/cBzsEo6W5J1tsH7TTBGL) \## Access level In addition to user-based authentication, API workflows can also be restricted to \*admin-only access\*. This gives you more precise control over who is allowed to trigger sensitive workflows, such as administrative actions or data management operations. ![](https://manual.bubble.io/files/U01jFxTTdCcuoRAiLOSx) API workflow authentication is configured using the \*Authentication\* setting in the property editor. This setting determines what level of access is required to run the workflow and replaces the previous \*This workflow can be run without authentication\* checkbox with a clearer set of options: \* \*\*None required\*\*\\ The workflow can be triggered without authentication. This option is typically used for signup, login, or other public-facing workflows. \* \*\*User and admin\*\*\\ Any authenticated user can trigger the workflow. If access should be limited to specific users, this must be enforced using conditions, logic, or privacy rules within the workflow itself. \* \*\*Admin only\*\*\\ Only requests authenticated with an admin-level API key can trigger the workflow. Regular user authentication is not sufficient. Existing API workflows continue to behave as before unless their authentication setting is changed. Using the \*Admin only\* option is recommended for workflows that perform sensitive operations or should be accessible only to trusted systems or users with elevated permissions. This helps prevent unintended access and ensures tighter control over how and when critical workflows are executed. You can find the authentication setting by selecting an API workflow and reviewing its properties in the editor. ## Continue reading {% content-ref url="/pages/MPejx6hSBC2VNtdNxrQR" %} \[API workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md) {% endcontent-ref %} {% content-ref url="/pages/4vLfEynUyUKWLUsbVckG" %} \[Workflow API privacy rules\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules.md) {% endcontent-ref %} {% content-ref url="/pages/Ot0gk4QBuwDtwB5lrVaU" %} \[Workflow API endpoints\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-endpoints.md) {% endcontent-ref %} \[^1\]: The Bubble API lets you set up a platform to accept incoming API requests to access your database or to trigger workflows.\\ \\ Article: \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md) \[^2\]: An API Workflow is a Workflow that you can choose to expose to external apps to be able to trigger.\\ \\ Article: \[API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md) \[^3\]: A webhook is a way for an app to provide other applications with real-time information. It allows one app to send data to another app when certain events happen. \[^4\]: A public API Workflow refers to any API Workflow that has the \*Expose as a public API flow\* box checked.\\ \\ Article section: \[Exposing an API Workflow\](broken://pages/ASPrBtBQHndZ5vpaAQpm#exposing-api-workflows-for-external-use) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/web-app.md). # Web app - \[The page\](https://manual.bubble.io/help-guides/design/elements/web-app/the-page.md): The page is the blank canvas on which you design your app's user interface. - \[Containers\](https://manual.bubble.io/help-guides/design/elements/web-app/containers.md): This section covers the container elements, used to group and control the behavior of other elements - \[Groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/groups.md): This section covers Groups, that can be used to contain elements and data and control the responsive behavior of child elements - \[Repeating groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/repeating-groups.md): This section covers the container type repeating group, used to display lists of things such as records from the database - \[Table elements\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/table-elements.md): This section covers the table element, used to display lists of things such as records from the database in a table-like structure of rows and columns - \[Popups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/popups.md): This section covers the container type Popup, which is a group that hovers above all other elements on the screen - \[Floating groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/floating-groups.md): This section covers the group type Floating Group, which is used primarily for attaching a group to one of the sides of the screen, regardless of scrolling position - \[Group focus\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/group-focus.md): This section covers the group type Group Focus. This group will remain visible for as long as it is in focus, typically used for dropdown menus - \[Visual elements\](https://manual.bubble.io/help-guides/design/elements/web-app/visual-elements.md): This section describes the visual elements that are available in the Bubble editor - \[Input forms\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms.md): This section covers Input forms. These are element that accept data input from a user such as text, numbers, dates, uploads and dynamic content. - \[Text and numbers\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/text-and-numbers.md): This section covers elements that accept text and numbers as user input - \[Dates and time\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/dates-and-time.md): This section covers elements that accepts dates and time as user input - \[File uploads\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/file-uploads.md): This section covers elements that lets your users upload files and images - \[Selection controls\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/selection-controls.md): This section covers selection control elements, that lets you set up input elements with predefined options --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/web-app.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/logic/workflows/events/backend-events.md). # Backend events Backend events are the triggers that happen on Bubble's \*\*server\*\*. They can be triggered by a few different conditions: \* They can be scheduled to trigger at a specific time with the \*Schedule an API workflow\* action \* They can be triggered by an API call from an external app \* They can trigger as a response to a change in the database \* They can be set to run at a specific interval ## How are backend events different from frontend events? Backend events are handled completely by Bubble's server, and does not involve the user's device at all, whereas a frontend event will be passed from the user's device to the server. This has a few implications, the most important being that they are always accessible. A page will stop doing any work as soon as it's closed, but the server is available 24/7. \* Frontend events are the triggers that happen on a \*\*page.\*\* It's often – but not always – initiated by a user. Frontend events will only trigger as long as the page is open. \* Frontend events can still lead to actions happening on the server – but the \*event\* (or trigger) happens on the page. ## Triggering an event at a specific time You can schedule a backend event to trigger at a specific time. This is a part of the \[Bubble Workflow API\](#user-content-fn-1)\[^1\] and is done in the following away: 1. In the backend editor, create a new \[API Workflow\](#user-content-fn-2)\[^2\] that contains all the actions that you need to perform 2. Use the \*Schedule API Workflow\* to set the workflow to run at a specific time. {% hint style="info" %} If you want to learn more about how to create and schedule API Workflows, check out our dedicated articles on these subjects: Article: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) (start here if you are unfamiliar with the Workflow API) Article: \[Creating API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/creating-api-workflows.md) Article: \[Scheduling API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/scheduling-api-workflows.md) {% endhint %} Note that the \*scheduling\* is not the event – the event happens when the workflow is triggered at the specified time. As such, the scheduling can happen both on the frontend and the backend, but the \*event\* will happen on the backend. As such it's available even if the user closes your app. ## Triggering a workflow from an external application By using the Bubble Workflow API you can also trigger a workflow from an external application. To do this: \* Create an API Workflow in the backend editor, and make sure that \*Expose as a public API workflow\* is checked \* Set up the external application to send a request to the workflow's endpoint {% hint style="info" %} If you want to learn more about how to create API workflows and expose them to external apps, check out our dedicated articles covering this subject: Article: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) (start here if you are unfamiliar with the Workflow API) Article: \[API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md) Article: \[Creating API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/creating-api-workflows.md) {% endhint %} ## Triggering an event when data changes in the database You can set up an event in the backend to start running a workflow whenever something specific is changed in the database by using \[Database trigger events\](#user-content-fn-3)\[^3\]. For example, let's say you are running an eCommerce app and you want to send an email whenever a data type called \*Order\* has a field called \*Completed purchase\* set to \*yes.\* By combining a \*Database trigger event\* with an expression\[^4\], you can specify exactly what kind of changes you want the event to respond to and run a workflow accordingly. 1. Create a \*Database trigger event\* in the backend editor 2. Specify the conditions for the trigger in the \*Only when\* field Articles If you want to learn more about creating Database trigger events, check out our dedicated article: Article: \[Database trigger events\](/help-guides/logic/workflows/events/backend-events/database-trigger-events.md) \## Running a workflow at a specific interval There are two ways you can set up workflows to run at an interval such as once per day/week/month: ### Recurring events {% hint style="info" %} The settings for recurring events vary based on the plan that you have subscribed to. You can check our pricing comparison page to learn more: Page: \[Bubble pricing\](https://bubble.io/pricing/compare) {% endhint %} \[Recurring events\](#user-content-fn-5)\[^5\] are events that are built specifically to trigger: \* Daily \* Weekly \* Monthly \* Quarterly \* Yearly They consist of two parts: \* The recurring event, which contains the workflow to run and the database thing to run it on \* The action Set/Cancel a recurring event which runs the first instance of the workflow and instructs Bubble at what frequency it should run. ### Recursive workflows Recursive workflows are workflows that re-schedule themselves by using the \*Schedule API workflow\* as an action and picking the same workflow as the one that contains the action. Since you can set a dynamic time to schedule the next cycle, this gives you a way to set an interval freely. Recursive workflows are a bit more complicated to set up, but offer more flexibility than Recurring events and are available on lower-tier plans. {% hint style="info" %} To learn more about how to use recursive workflows, you can check out our dedicated article on the subject: Article: \[Recursive workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/recursive-api-workflows.md) {% endhint %} {% hint style="warning" %} Using recursive workflows can potentially lead to infinite recursion, resulting in significant workload unit (WU) consumption. Starting on \*\*July 1st, 2024\*\*, Bubble will apply a default setting to terminate recursive workflow chains at 10 iterations for all new apps. This means you need to either disable this feature or set a higher limit (recommended) if you plan to use recursion, or else any \*\*recursive workflow chain will be terminated after 10 iterations.\*\* Article: \[Infinite recursion protection\](/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection.md) {% endhint %} ## Overriding timezones {% hint style="info" %} Overriding timezones in the backend requires that you activate the advanced setting \*Enable timezone override controls\* in your app's general settings. Reference: \[Application settings: Advanced\](/core-resources/application-settings/general.md#advanced-options) {% endhint %} Some backend workflows allow you to override the \*Current user's current timezone\* by setting an alternative timezone with a static or dynamic choice. In practice, the timezone replacement works as following: \* \*\*API Workflows:\*\* override the time zone of the API request \* \*\*Recurring event:\*\* override the time zone in which the recurring event was first scheduled \* \*\*Database trigger event\*\*: Override the time zone in which the change happened (i.e. the user's timezone when the change was made) This helps you standardize the way in which your app parses and stores data. For example: \* if you parse \*\*1/1/2000 from Eastern Time\*\* and keep the default setting, Bubble will save that date as \*\*1/1/2000 12:00 AM Eastern Time\*\* \* If you instead override the client timezone with Pacific Time, selecting 1/1/2000 will save \*\*1/1/2000 12:00 AM Pacific Time\*\* This type of timezone standardization is useful in different scenarios: \* Where an external API request includes a timestamp, but not a timezone: you can set a static or dynamic timezone when that call is received to ensure its properly parsed \* Apps that deal with scheduling where the timezone of the scheduled appointment needs to remain constant: for example, if a user books a conference in London from Tokyo, your app can ensure that the timezone used is indeed London and not Tokyo. {% hint style="info" %} Overriding timezones is not just available in backend workflows. It can also be set on individual input forms and on pages. Reference: \[Input forms\](/core-resources/elements/input-forms.md) Reference: \[The page element\](/core-resources/elements/page-element.md#time-zone-selection) {% endhint %} ## Other ways to learn Articles To learn more about the different features and methods mentioned in this article, see the articles below. Article: \[Database trigger events\](/help-guides/logic/workflows/events/backend-events/database-trigger-events.md)\\ Article: \[API workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md)\\ Article: \[Recurring events\](/help-guides/logic/workflows/events/frontend-events/recurring-workflows.md) \[^1\]: The Workflow API is the part of Bubble's \[built-in API\](#user-content-fn-6)\\\[^6\] that lets you set up workflows that can be triggered from an external application or system by sending an API request or by scheduling an API workflow in your app.\\ \\ Article: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md)\\ Reference: \[The Workflow API\](/core-resources/api/the-bubble-api/the-workflow-api.md) \[^2\]: \*API workflows\* are server-side workflows that you can schedule/trigger in your application and/or expose to be triggered from an external application or system through an API request. API Workflows are part of the Bubble Workflow API.\\ \\ Article: \[API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md)\\ Article: \[The Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) \[^3\]: \*Database trigger events\* are events that watch for specific changes in the database, and trigger a workflow any time a change in data happens. \[^4\]: Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app.\\ \\ Article: Dynamic expressions \[^5\]: Recurring events are backend events that run on a thing at a specific interval such as once per day or once per week.\\ \\ Reference: \[Recurring events\](/core-resources/events/recurring-event.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/logic/workflows/events/backend-events.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/app-security.md). # App security Having made sure that your Bubble account is secure, it's time to look at the settings for each individual application. Just like your account, these overarching settings should be thoroughly set and reviewed to form the foundation of your app's security. ## Application rights Applications rights determine who has access to your app more broadly. While the collaboration feature allows you to invite and set the administrative privileges of single users, your app's application rights set the overarching access level of \*anyone\* who tries to access your app's editor. {% hint style="info" %} Bubble sets strict application rights by default: this setting is only a security concern if you have made changes to it. {% endhint %} Sharing an app publicly can be highly useful in certain situations, but it's important to consider the security implications involved. If your app contains sensitive information or you want to restrict access to specific individuals, you should implement strict application rights to protect your app and its data. ![](https://manual.bubble.io/files/rOSHmt1pVMILNBQxyWbJ) You will find the application rights setting under \*Settings - General\*. \* \*\*Private app\*\*: No one can access the app editor except for you and collaborators \* \*\*Everyone can view:\*\* Anyone can access the app editor and view it and any data, but they cannot make any changes \* \*\*Everyone can edit:\*\* Anyone can access the app editor and change anything they want ## Development and Live app access Your app can be previewed by entering the APP's URL and the name of a branch\[^1\] (with the Main branch having the default URL \*version-test\*). ![](https://manual.bubble.io/files/7DxkzyvKqfAhDre1Iydz) You can choose to set a password to protect both the Development and Live app to ensure that no one has access to one or both environments without the right credentials. By default, Bubble sets the username \*username\* and the password \*password\*, but we strongly recommend setting up your own credentials as these are the default for all new apps and can easily be guessed. ## Password policy {% hint style="info" %} The password policy applies to your \*\*app\*\* – not your Bubble account. {% endhint %} Using a password policy lets you make sure that your users use a password that meets certain requirements and is secure enough. If you want to activate this feature, check the relevant box in the General section of the Settings tab. Once you check the box, you will see a few other options that you can choose to select to vary the password policy even further. !\[\](/files/OVc1QxRLkM466EylAgY0) ## Collaboration Inviting collaborators\[^2\] into your app can be a great way to solve problems, work on separate features simultaneously and speed up development, but it's important to keep in mind what kind of privileges you are giving your collaborators. They can potentially access private data, make changes to your app and even invite other users if given the rights to do so. The list below is a set of best practices that you should keep in mind when working with collaborators: \* Make sure you know the person you invite and that you spell their email address correctly \* Never give them broader access than they need to do their job \* In many cases, there's no reason for a collaborator to have access to data in Live \* Remember that they have access and remove them from the app when they no longer need that access ### Collaborator password policy Ensure that you enforce strict password and authentication policies for collaborators too. If a collaborator with extensive access privileges has their account compromised, it can result in similar consequences as if your own account were breached. ### Copying data between databases \[Copying data\](#user-content-fn-3)\[^3\] from the Live database to the Development database can be useful to find and debug issues, but keep in mind that it may give collaborators access to the data. This can lead to unintended viewing or sharing of private user data. \[^1\]: A \*branch\* is an independent iteration of your application that can be developed in isolation.\\ \\ Article: \[Version control\](/help-guides/maintaining-an-application/version-control.md) Article section: \[Branches\](/help-guides/maintaining-an-application/version-control.md#branches) \[^2\]: \*Collaborators\* are fellow Bubble developers that you invite to work on your app. They can contribute to both the design and data aspects of your application. With Version control, you can exercise a high level of control over collaboration.\\ \\ Article: \[Collaborators\](/help-guides/maintaining-an-application/collaboration.md)\\ Article: \[Version control\](/help-guides/maintaining-an-application/version-control.md) \[^3\]: Bubble has built-in features for copying parts of or the full database between Live and Development.\\ \\ Article: \[Copying your database\](/help-guides/maintaining-an-application/database-maintenance/copying-the-database.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/app-security.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/planning-app-security.md). # Planning app security Every security and privacy measure that you choose to implement in your app starts with a decision, and these decisions are made from two different perspectives: \* \*\*Required security\*\* and privacy is the level of security and privacy that your app needs in order to stay compliant in the region(s) and sector(s) where your users come from. These are the legal requirements that govern how your app collects, stores, processes, and shares user data. \* \*\*Optional security and privacy\*\* are all the measures you as an app owner take to further protect your users privacy. This is often based on: \* Your user's expectations \* Your communication and marketing (such as using privacy as a selling point) \* Your own preferences and strategy As part of your planning, you should have a general overview of how your app should be set up to work. This will not only make your development process smoother, as you know what data should be kept private and not, but also makes clear communication with your users easier, as you'll be thoroughly familiar with your app's policy. #### User expectations Your users will come to your app with a set of expectations that you should have in mind when you plan your app. For many applications, users will naturally expect their data to remain theirs - not visible to any other users, unless they choose to share it. They may also expect to be in control of privacy settings and be able to share some things but not all, and to set a default behavior. For example, in a social media application, a user might expect that a draft to a public post is kept private and is not visible to anyone else before it is published. The same could be true for fitness trackers: a user may want the chance to share their latest workout with the world, but maybe not every workout. By putting yourself in the shoes of the user before you structure your app, you can build the app on top of a foundation that respects their needs and puts them in control. You can also consider conducting user interviews to make sure that you are making decisions based on real-life preferences and concerns. Furthermore, users expect transparency. This includes clarity about what data is being collected, why it's being collected, and how it's being used. Features such as a clear privacy policy, easily accessible user settings, and opt-in/out options for data collection practices can go a long way in meeting these expectations and building trust with your user base. #### Communication and marketing Secondly, privacy and security can be made part of your app's brand and communication. By letting your users know about your data collection and storage practices, you can consciously build trust and lower the threshold of signing up by giving a clear indication of your app's strategy and also being transparent about what the data is used for. #### Your own preferences and strategy How would you like your app to behave? What are your personal standards? Collecting and sharing user data isn't inherently a bad thing, but it warrants careful consideration before the development process begins. Are you aiming for strict user privacy, or do you plan to leverage it for various goals such as marketing, analytics, understanding user patterns, or revenue generation? None of these are negative or unethical on their own, as long as you are transparent and responsible in its management. It's all about open communication with your users, letting them know what data you collect, how it's used, and why. ### Transparency and documentation Managing user data is a responsibility, and shouldn't be taken lightly. Returning to our two perspectives from earlier, how you communicate your security and privacy policy is a mixture of legal requirements and communication strategy. Some documents need to be in place for your app to comply with laws and regulations, but you can also choose to share more than what is required about how your app manages data. ### Frequently required documents Many privacy and security legal frameworks across different industries and regions share a common requirement for documenting how your app handles data. In this section we'll highlight some of the common documents that need to be in place before your app accepts live users. {% hint style="danger" %} This list illustrates the types of documentation often required by numerous privacy and security frameworks. However, it is by no means comprehensive and should not be interpreted as legal advice. You should always seek professional legal counsel to establish a compliance strategy tailored to your region and industry. {% endhint %} | Document | Description | | --- | --- | | **Privacy Policy** | A document that discloses how you collect, use, and manage personal data of users. Required by GDPR, CCPA, and many other laws worldwide. | | **Terms of Service/Conditions** | The rules a user agrees to abide by in order to use your app. While not explicitly required for data protection regulations, it often details acceptable use, dispute resolution, and disclaimers for liability. | | **Cookie Policy** | When you use cookies, especially for EU users, a Cookie Policy is needed to explain what cookies are in use, what data they track, and how users can control these cookies. Sometimes included within the Privacy Policy. You can read more about what kind of cookies Bubble uses by default in [this article](https://manual.bubble.io/pages/-MWazsRXSRguR2m8PH5O)
. | | **Data Processing Agreement (DPA)** | If you use third-party vendors that process data on your behalf, GDPR requires a DPA between you and them. This agreement outlines the responsibilities and obligations of both parties with respect to data protection. | | **Data Breach Notification Plan** | A plan to notify users (and relevant authorities) in the event of a data breach. This is a key requirement of GDPR, though it's not usually a public document. | | **Children’s Privacy Policy** | If your web application targets children or processes children's data, regulations like COPPA in the US may require a specific policy. | \## Planning your app's structure with security in mind When discussing web app security, you'll often hear the term "privacy by design." In essence, this is a proactive approach to data protection, emphasizing the importance of building privacy and data protection measures into the development process from the very beginning. It involves considering privacy concerns and risks throughout the entire product development phase and embedding security directly into the design and architecture of the system. The goal is to minimize privacy risks, protect user data, and ensure compliance with data protection regulations. > Bubble is a fast platform to build on, but if you develop an app without taking security and privacy into account from the beginning, you can find yourself having to backtrack your work. With the wide range of different apps being developed in Bubble, this guide will not attempt to describe a plan or best practice, but instead highlight the general points that are worth taking into consideration as you plan your app's security. Some of these points may require that you get to know other sections of the Bubble manual before you start building – we recommend spending that time to know the basics of app security before you begin the development process. ### Determining your security needs The first aspect to consider is the degree of security required for your app overall. While some apps may not need strict security measures, others require a strong emphasis on data protection and privacy. What kind of app is yours? Will you only store public data in your database, or will you store data that needs to be kept securely private? Remember to consider your users' expectations – even without explicitly stating that certain data is private, users will often assume that it is. Trying to put yourself in the shoes of your users and sometimes talking to potential users directly can help you work out a policy regarding privacy and security that matches their expectations. ### The principle of least privilege The principle of least privilege is a fundamental security concept in software development, and it's no different when you're crafting apps in Bubble. The idea is straightforward: grant users only the access and rights they need to perform their tasks and nothing more. This principle applies to: \* App users \* API services (inbound\[^1\] and outbound\[^2\]) \* Collaborators\[^3\] \* You and your team In a bank, not every employee has the keys to the vault. A teller can access the cash drawer but doesn't have the authority to authorize large wire transfers. Conversely, the bank manager might have that authority but doesn't necessarily need access to every single safety deposit box. Similarly, in a Bubble app, you'd want to ensure: 1. \*\*Data Restrictions with privacy rules\*\*: Ensure users can only view or modify data relevant to their role. If they're a regular user, they shouldn't be able to access admin-level data or configurations. 2. \*\*Feature/page Access\*\*: Tailor the user interface to display only the features and functionalities each user role requires. For example, a site moderator might see options to delete comments, while regular users don't. Logged-out users might not have access to specific pages. 3. \*\*Workflow Permissions\*\*: Ensure that only the necessary users can trigger specific workflows, especially ones that might change data. This is an overarching principle that should guide your security planning. > By following the principle of least privilege, you not only enhance security but also simplify user experience. It helps to prevent accidental changes and guards against potential misuse. ## What to plan for The purpose of planning is to provide yourself with information that leads to better decisions. When you or your client has an idea for an app, it's usually on a conceptual level: in many cases it has the yin/yang relationship of \*\*what\*\* problem do I want to solve and \*\*how\*\* do I want to solve it. Together, the problem and solution make up the foundation of why the app was conceived in the first place. Then, you sit down to build it. These processes are very different, just like envisioning a great hotel is very different from drawing the architectural plans and breaking the first ground. Luckily, creating an app doesn't need the meticulous planning of constructing a building: Bubble's flexibility lets you experiment and generate ideas as you go along. The aim is to do the amount of planning needed to give your app a solid foundation, so as to save you work later. Let's look at some different important points that are worth keeping in mind before you start to build: ### Database structure The structure of your database is mainly set up to cater for the data types you need in your app: for example, if your app is managing Tasks and Projects, you will usually create these data types. Though this practice is standard and expected, we recommend that you plan thoroughly for what kind of security is needed on these data types, as this may affect how you structure them in the database. The purpose of these examples is not to encourage any kind of best practice or that the method outlined below is the only way to proceed: the point is to again emphasize the importance of planning. If you know exactly what your app is meant to behave, you can plan out your database structure to facilitate for the correct privacy rules and conditions. Let's look at a few examples to illustrate: \*\*Task owner\*\* Let's say that you want to set up privacy rules that control the access to Tasks – only the user who created the Task should have access to view and make changes to it. An obvious way to solve this is to set up a privacy rule that uses the Created by field to control access to the task. But what if you want to include a way to transfer ownership and assign tasks? The Created by field is a non-editable built-in field that makes transfer of ownership difficult: in this scenario it makes sense to set up a separate field of type User (that could be called Owner) that you can later make changes to as needed. \*\*SaaS with multiple client organizations\*\* Let's say that you offered this project management tool to multiple client organizations that each have a group of team members working together: this could be a company with a list of employees for example. In this case, each client must have their data completely siloed. What this means that is the data of one organization must never be visible to an employee that belongs to another organization (often called siloing). What does this mean for your database? It means that all the data (users, tasks and projects in our example) need to include a field for that parent organization: in other words, Bubble needs to be able to check on each database thing which organization it belongs to, and restrict access if the organization of the project or task is not the same as the organization as the user who tries to access it. \*\*Full, partial or no sharing\*\* When you plan your database, another aspect worth planning for is how specific things will be shared. With any piece of data, you basically have three options: \* Sharing it with no-one \* Sharing it with selected groups or people \* Sharing it with everyone The three points can of course overlap. Think of a document stored in a cloud service like Google Docs for example; they are normally shared with no-one, but Google offers flexible sharing where you can pick a select number of users, add one or more groups or set up a link that gives anyone with the URL access. Sometimes, things are shared with different privileges, such as: \* Viewing, but not editing \* Viewing and commenting, but not editing \* Full editing rights \* Publish status Some database things will also have a sort of lifecycle where its visibility is determined by where it is in that cycle Let's look at some examples: \* A blog post or article could have a draft and published status that determines whether it can be viewed by other users than its author. It could also have a publish date that lets the author share it publicly after a specified date and time. \* An e-commerce product could similarly have a draft and publish status as well as a publish date. It could also have a status like sold out to hide it when it's no longer available. ### Pages We recommend having a clear overview of what kind of content belongs on each Page in your app before you start building that page. The reason is simple: some pages are public, others are not, and by knowing in advance what category a page belongs to, it's easier to build it the right way from scratch. You can read more about page security in general in our \[article in Page Security\](/help-guides/security/page-security.md). ### Saving data #### Auto-binding Auto-binding\[^4\] allows your users to instantly save changes to any input field where they have made changes, as soon as that field loses focus. This is not only a quick way to save changes, but it comes with the upside of being protected by \[privacy rules\](#user-content-fn-5)\[^5\] - by setting up the correct rules, a user will never be able to save changes to a thing or field to which they don't have access. #### Workflows The second alternative to saving data is to use workflows, often triggered by a user interaction such as a button click. Database changes made in workflows are not protected by privacy rules in the same way, and need server-side conditions to offer the same protection. One method is not better than the other – they are purely a user interface decision where you should take into consideration what's right for your app. But by planning it in advance, you can decide whether to protect data by use of conditions in your workflows, or by using Privacy Rules. ### User roles In many applications, you have different types of users, such as: \* Users being logged in or out \* Users with administrative privileges \* Users who create things and users who only read \* You and your team (sometimes called super admins) There can be many more categories of course, depending on your app. User roles are often split into two parts: \* The role that the user has (such as admin, author and regular user) \* The permissions that come with that role (such as viewing specific things, making changes in the database, managing other users, etc) Already we can see how important it is to understand the different roles in your app, as both your database and pages need to be designed around the permissions and restrictions on each role. Here are some questions you can ask to help you set up that structure: \* What kind of roles does my app have? (remember to include the built-in role of being logged in or out) \* How do I separate the different user roles from each other? (for example, a user could have a yes/no field called admin or you could save different roles in an option set) \* What permissions and restrictions come with each role? \* How does that affect: \* Privacy Rules \* Database structure \* Workflows \* Conditions \* Page access \* Do I and/or my team need a separate role and pages to manage the app and its data? Depending on the nature of your app, this list can be irrelevant or not exhaustive enough, but it gives you an idea of what we mean by user roles: sometimes you need to restrict data by only allowing selected users access. ## Third-party security resources {% hint style="warning" %} Bubble is not responsible for the content, accuracy, or practices of third-party websites or services that are linked from our platform and website. We provide these links for your convenience. Always review the terms and conditions and privacy policies of any third-party websites or services that you visit. Some third-party services we link to may be fee-based {% endhint %} ### Tools Bubble has a large and active community, and there are third-party tools in the ecosystem that can assess an app for known security weaknesses: \* \[Flusk\](https://www.flusk.eu/)\[.eu\](https://www.flusk.eu/) \* \[Checkso Bubble security check by Tinkso\](https://check.tinkso.com/) \* \[ncScale\](https://app.ncscale.io/registration) ### Books \* \[The Ultimate Guide to Bubble Security\](https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-security/) by Petter Amlie is a 300+ page book that covers planning, designing and developing secure Bubble applications, reviewed by Bubble's top engineers. \* \[The 2023 Bubble Security Cheat Sheet\](https://www.flusk.eu/bubble-security-cheat-sheet-2023-by-flusk) by Flusk is 80+ pages of concrete examples and in-depth Bubble reverse-engineering, reviewed by Bubble and improved with the help of 15+ recognized Bubble experts. \[^1\]: \*Inbound\* API calls are requests sent \*\*to\*\* your app from an external app or service. They are communicating with the Bubble API to manage data in your database or execute workflows.\\ \\ Article series: \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md) \[^2\]: \*Outbound\* API calls are calls made \*\*from\*\* your Bubble app \*\*to\*\* an external app or service. They are made using the API Connector plugin.\\ \\ Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) \[^3\]: Every editor that you add to your app is known as a \*collaborator\*. They are connected to an app, and not to your account, meaning that if you have multiple Bubble projects, you can choose which one(s) to add one or more collaborators to.\\ \\ Article: \[Collaborators\](/help-guides/maintaining-an-application/collaboration.md) \[^4\]: \*Auto-binding\* binds a specific input form (such as a text input element) to a specific field in the database, and automatically saves any changes made in the input to that field.\\ \\ Article section: \[Auto-binding\](/help-guides/data/the-database/creating-saving-and-deleting-data.md#auto-binding) \[^5\]: Privacy Rules are conditions that you set up on each data type in order to protect the data from being viewed and edited by unauthorized users.\\ \\ Article: \[Protecting data with Privacy Rules\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/planning-app-security.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo.md). # Introduction to SEO ## How important is SEO for my app? Bubble is a flexible platform that lets you build a wide range of different applications. As such, each application's need for search engine optimization can vary greatly: for some it can be a crucial source of revenue, while for others it is irrelevant. In the first part of this article we'll go over three different categories of apps to help you determine whether SEO is relevant for your project. ### Closed apps If your app is designed to be used primarily by a closed group of users, such as a project management tool for your team or an inventory management system for your warehouse, you may not need to focus on SEO at all. Since your users are already aware of your web app and will likely access it through a direct link or bookmark, you don't need to worry about attracting new users through search engines. In some cases, you may even take active steps to hide the app from search engines. ### Public apps if your app is designed to be used by a wider audience, such as a social media platform or a marketplace, SEO should be a top priority. When users search for keywords related to your web app on search engines like Google and Bing, you want your web app to appear at the top of the search results. If this describes your app, keep reading this article series to see how to work with Bubble's SEO tools. ### Mixed apps A common solution is the mixed app, where some parts are closed (such as a project management dashboard), and others are public (such as the front page that recruits new users to the software). In this case, SEO can also be an important part of your marketing strategy, but one or more your app's pages will still be hidden to search engines (which usually means they require users to be logged in to access them). ## SEO basics in essence, SEO is a way to make sure that your website is visible and accessible to the people who are looking for it. Imagine yourself performing a search in one of the major search engines: in most cases you will find what you're looking for among the first few results. SEO is the effort to try to be one of those pages. ### How search works #### Personalized and contextualized searches Search algorithms have become incredibly complex since they were first invented. One of the major things to grasp with most modern search engines is that a page's position in the search ranking is not static or even the same for all users. \*\*Personalized\*\* means that the search engine may build a profile of your search habits and preferences and tailor the results accordingly. The degree to which a search is personalized depends on factors such as whether the user is logged in to their account with the search provider, their profile settings and their cookie settings. \*\*Contextualized\*\* means that they may also take into account different kinds of \*current\* data about you, such as the device you are using, the operating system, the geographical location of your IP address, and other pieces of information. Again, this depends on the user profile, browser- and cookie settings of the user performing the search. The reason these two points are important to keep in mind, is that they suggest a key fact in SEO: top rankings are statistical probabilities, not static positions. In other words, your SEO efforts are a mission to increase the \*likelihood\* of being the number one result, not a linear race to a top position where everyone will see you. That's why searching for your own pages does not necessarily give you any meaningful indication as to how the page is doing: Google might simply deduce that you have a high interest in it and increase its ranking for you alone, since they likely have a history of you interacting with it in the past. > Top rankings are statistical probabilities, not static positions. This is why tools like \[Google Search Console\](https://search.google.com/search-console/welcome) are useful and important, since they can give you an indication as to where the traffic to your pages comes from across potentially thousands of users, normalizing statistical outliers. #### Title and description In addition to personalizing the order of search results, search engines like Google are increasingly using their own algorithms to determine the most appropriate title and description for each search result. While Bubble provides dedicated fields for elements such as the page title and OpenGraph\[^1\] title, search engines may choose to pull a title and description from any of these fields or even generate their own based on the content of the page. This can include text from the page itself, such as headers or body content. However, this doesn’t mean that these fields aren’t important—on the contrary, they provide valuable context for search engines. It simply means that the exact title or description you “suggest” may not always appear verbatim in search results. #### Content and keywords {% hint style="info" %} Google has released an excellent guide on \*\*how to create high-quality, people-first content\*\*. If your app depends on organic traffic, we strongly recommend reviewing this guide: External page: Google:\[ Creating helpful, reliable, people-first content\](https://developers.google.com/search/docs/fundamentals/creating-helpful-content) {% endhint %} Search is based on \*keywords\* or search terms. What this means is that any user who searches for something will provide a search term like "How to make pancakes", and the search engine will go through its index looking for pages that are relevant to that term. In the early days of search engines, they simply looked for a match: "How to make pancakes" would match "How to make pancakes", and the page named "Top 10 pancake recipes" would suffer. Today, search engines are smart enough to process queries linguistically and rephrase the question, take synonyms into account and understand the \*value\* of the content on the pages it crawls through. > It used to be important to simply stuff your page with keywords, but now search engines are looking for quality content which gives users what they're looking for. This doesn't mean you should disregard keywords – they are still the bread and butter of a good SEO strategy – but you should write your content for humans to enjoy, not for bots to index. ## General SEO advice Now, let's look at some general advice on how to optimize your app and pages for SEO. Keep in mind that SEO is a wide field that's constantly evolving, so in this article we will only be able to cover the basics: still, adhering to these rules of thumb will set you off to a good start on your SEO journey: 1. \*\*First and foremost, focus on creating quality content\*\*\\ Search engine algorithms are constantly evolving, but one thing that remains consistent is the importance of valuable, informative content. Write articles, make videos, and create other content that is interesting and engaging to your target audience. 2. \*\*Use keywords strategically\*\*\\ When choosing them, make sure they are relevant to your content and that you use them in a natural way. Overusing keywords, also known as keyword stuffing, can hurt your rankings. 3. \*\*Make sure your app is mobile-friendly\*\*\\ Make sure that your app is easy to navigate on mobile devices. Google even favors mobile-friendly websites in their rankings. This even includes details like font size, contrast and download size. We recommend getting to know the \[responsive engine\](#user-content-fn-2)\[^2\] to build pages that work on all screen sizes 4. \*\*Use meta descriptions and title tags\*\*\\ Meta descriptions and title tags are snippets of text that may appear in search results. They should accurately describe the content of the page and entice people to click through to your app. You edit meta description and title tags in your \[page's SEO settings\](/help-guides/maintaining-an-application/seo/seo-page.md). 5. \*\*Build high-quality backlinks\*\*\\ Backlinks are links from other websites that point to your website. Google views backlinks as a sign of authority and relevance. However, not all backlinks are created equal. It’s important to focus on building quality backlinks from reputable websites in your industry. 6. \*\*Monitor your app's analytics\*\*\\ Tools like Google Analytics can give you valuable insight into how people are finding and using your website. Google Analytics can be implemented using our dedicated \[plugin\](https://bubble.io/plugins) or by adding a tag in your page header, and there are many other useful tools that can collect and aggregate data in different ways. 7. \*\*Make your app easy to navigate\*\*\\ Web crawlers do two things: they crawl content, and they follow links. Make sure to link pages to each other when it makes sense, and link to your most important content from your index page – search engines consider those links important. They also use the labels of your links to understand the content it leads to. You can read more about different ways of setting up links in our \[navigation guide\](/help-guides/logic/navigation.md). Remember, SEO is a long-term game. It takes time to see results, so don't get discouraged if you don't see immediate improvements. The advice above is not a complete roadmap to SEO results, but keeping these points in mind while you develop your app can help you make informed decisions about your pages ## OpenGraph ### What is OpenGraph? OpenGraph is a set of rules created by Facebook (now Meta) that helps you control how your web pages look when shared on social media. ![](https://manual.bubble.io/files/kqwgVzdXiHmt8rx2uymq) OpenGraph lets you define the data that is displayed when the page is shared on social media. This example is from Facebook. By using specific \[meta tags\](#user-content-fn-3)\[^3\] in the HTML of a page, developers can control how their content is presented when shared on social media platforms. This includes specifying the title, description, image (and sometimes more), ensuring that the content appears as intended when shared across various social networks. ### Who Developed OpenGraph? OpenGraph was developed by Facebook (now Meta) in 2010. The protocol was designed to enhance the user experience on social media platforms by enabling richer and more engaging content previews. Since its introduction, OpenGraph has become a standard in web development for controlling how web pages are represented on social networks. ### How Does OpenGraph Affect SEO? OpenGraph metadata can play an important role in SEO by influencing how your page appears in search engine results and on social media. Key OpenGraph tags, such as og:title and og:description, can directly affect the title and description displayed in search engine results pages (SERPs). These tags help search engines understand the content of your page, improving its visibility and relevance. ### What do OpenGraph tags look like? OpenGraph tags are written in HTML code in the header section of your page. Bubble automatically generates the title, description and image tags and includes it in the HTML code of the page. The code looks like this: {% code overflow="wrap" %} \`\`\`html \`\`\` {% endcode %} ### How do I use OpenGraph in Bubble Integrating OpenGraph metadata allows you to optimize how your pages are presented when shared on social media, and can have an effect on how the page is presented in the results of a search page (such as Google). OpenGraph fields are set in one of two ways (often both): #### Page level Metadata included on the page element should contain information about that specific page. If this field is left empty, the app level metadata will be used instead. Article: \[SEO: Page\](/help-guides/maintaining-an-application/seo/seo-page.md) #### App level App-level metadata will be applied whenever the metadata for a specific page is left blank. In other words, if metadata fields are filled at the page level, they will override the app-level metadata for that page. Article: \[SEO: App\](/help-guides/maintaining-an-application/seo/seo-app.md) \[^1\]: OpenGraph is a protocol that allows web pages to become rich objects in social media by defining how content (like titles, descriptions, and images) is displayed when shared on platforms like Facebook or X. It helps ensure that links appear with relevant, attractive previews. \[^2\]: Bubble's \*responsive engine\* is how you build pages that adapt to the resolution of the monitor and browser of the user. Setting up simple rules for sizing, spacing, margins and other settings, you can build complete interfaces that work on all screens.\\ \\ Article series: \[Responsive design\](/help-guides/design/responsive-design.md) \[^3\]: Meta tags are snippets of text in the HTML of a web page that provide information to search engines and browsers about the page's content. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md). # What is a RESTful API? Help us improve this article This article is part of a significant update to the Bubble manual and your feedback is critical to our efforts to continuously enhance our written documentation.\\ \\ We would greatly appreciate if you could take a moment to let us know your thoughts on the quality of it. Thank you for your support!\\ \\ \[Give feedback on this article\](https://docs.google.com/forms/d/e/1FAIpQLSfe7eaYVxkqTa\_nn3QE6VObCxWB1hgh6sHUQGQ0Eit8JlAS7g/viewform?usp=pp\_url\\&entry.619913899=https://manual.bubble.io/help-guides/apis-connect-to-other-apps/introduction-to-apis/what-is-a-restful-api\\&entry.80834677=What+is+a+RESTful+API?) {% hint style="info" %} This section covers a fairly technical topic on how the RESTful API architecture works. You may find it useful to learn more about the underlying mechanics, but if you want to skip directly to how API calls work in Bubble, follow the links below:\\ \\ Accepting incoming API Connections with the \[Data API\](/help-guides/integrations/api/the-bubble-api/the-data-api.md) and \[Workflow API\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md)\\ Setting up outgoing API requests with the \[API Connector\](/help-guides/integrations/api/the-api-connector.md) and \[plugins\](/help-guides/integrations/api/plugins-that-connect-to-apis.md).\\ \\ While reading about APIs you may also find our \[API Glossary\](/help-guides/integrations/api/api-glossary.md) useful. {% endhint %} RESTful APIs use the HTTP protocol to initiate a connection with a server and get a response. What is the HTTP protocol? Most internet users are familiar with the HTTP protocol. You see it as part of the URL of every website you visit. But what is it exactly? HTTP, or Hypertext Transfer Protocol, is a protocol: a set of rules that governs how data is shared between two systems to make sure both parties understand it. It would be difficult for two systems to communicate if they had no idea how to format the data: the HTTP protocol makes sure that they do. Whenever you open up a website, your browser is actually making an API call to the web server that hosts the page, and the server responds by sending back the needed files (such as HTML and CSS). Here's how the HTTP protocol works and the call is made: 1. A client (such as your web browser) sends a request to a server. The request contains information about what kind of action the client wants to take (such as requesting a webpage or sending data to be stored in a database) and it may also contain relevant information (such as the actual data you want to store). 2. The server receives the request and checks what kind of action the client wants to take and proceeds to process it. This might involve sending back a html file, looking for something in a database or running a workflow. 3. The server sends a response back to the client. The response usually includes a status code that indicates whether the request was successful or not, and it may also include additional data (such as the webpage the client requested). So HTTP ensures that a client and a server are able to communicate with each other in a standardized way. While the protocol in itself is pretty simple, it makes up the foundation of the entire web. \## What is a RESTful API? REST, or Representational State Transfer, is not actually a protocol, but more of a set of guidelines that define how a client and server should interact with each other. In other words, a developer can technically build an API to follow any kind of structure they want, but REST is a widely adopted style of architecting APIs that’s flexible, scalable and easy to understand. This makes it easy for different systems to talk to each other as their developers prepare it to follow the same method of communicating. The RESTful style follows a few key principles: \* The client-servers are completely independent of each other and only communicate using the REST API. \* It’s stateless: this means that the server does not store any information about the client between requests. As such, each request is completely isolated and contains all the information needed for the request to be processed. \* It’s often cacheable, meaning that the client uses a cached response if the user requests the same data multiple times. This speeds up the client application and lightens the load on the server. Bubble automatically caches data instead of repeating a request, unless it needs to. \* RESTful API’s are often described as layered since the client doesn’t necessarily have direct access to the server, but can be separated by intermediaries such as a proxy to ensure the stability and security of the server This may all sound very technical, but don’t worry: most of this is automatically taken care of and simply works. Bubble automatically generates an interface in your app that adheres to the RESTful principles, making sure that both incoming and outgoing connections are compatible with thousands of external systems. ## What a RESTful API call looks like As we’ve seen, an API request based on REST principles allows two software systems to communicate with each other in a way that both systems understand. Each request/response is made in complete isolation from each other, and the server receives all the information it needs to process the request in that request. But what does the call actually look like? What kind of information is being transmitted? A good thing about the RESTful architecture is that the data being transmitted in both directions is designed to be readable both by computers and humans. Each call consists of recognizable parts that each serve a specific purpose. The call is made using the HTTP protocol. ### The URL You have probably heard the abbreviation URL, but you may not have thought much about what it means. In the context of APIs the abbreviation makes sense: \*\*Universal Resource Locator\*\*. In the earlier section, we talked about how a resource is a specific piece of data or functionality that can be accessed through the API. It follows that the URL is the way to find that resource. In other words, the URL points the client’s request towards the right resource on the server. In Bubble’s Data API, endpoint URLs are automatically generated for each Data Type and API workflow you choose to expose. \`https://myapp.bubbleapps.io/version-test/api/1.1/obj/datatypename\`\\ \\ \`https://myapp.bubbleapps.io/version-test/api/1.1/wf/workflowname\` This is the first part of a RESTful API request. This too makes sense: in order for the server to authenticate a client and check the client’s authorization to reach a specific resource, we need to know which resource they are trying to access. ### HTTP method Now that we know which resource the client wants to access, we need to know what kind of action they want to perform. Remember that we discussed HTTP being a protocol: that means we have a set list of possible actions that we can ask of a server that is prepared to receive HTTP requests. The list of possible HTTP methods is longer than this, but the most common actions you’ll see are: | Action | Description | | --- | --- | | GET | Retrieve data | | POST | Create data | | PUT | Replace data (empty values [overwrite existing field](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#user-content-fn-1)
s) | | PATCH | Partially update data (empty values [do not overwrite existing fields](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md#user-content-fn-2)
) | | DELETE | Delete data | \\ When your browser contacts a server such as \[www.bubble.io\](http://www.bubble.io) in order to load the webpage, it’s sending a GET request to the root URL of the domain. The bubble.io server has been set up to respond to such a request by responding with the necessary data to render the page in the browser, such as a HTML and CSS file. In GET requests, the URL can sometimes contain parameters, such as the constraints for a search whereas in POST/PUT/PATCH/DELETE requests parameters are usually contained within the \[body\](#the-body). ![](https://manual.bubble.io/files/rHDivLqz1Q9zB0eGg8bU) The GET HTTP Method is used to retrieve some data. Here illustrated as the HTTP method would be specified in Bubble's API Connector. As you may have guessed by now, the same thing happens with the other actions: your browser sends POST, PUT and DELETE actions to the Bubble server to tell it to create, modify and delete things in your database. Now it’s starting to make sense why HTTP requests make up the foundation of the web: since every web browser and server speaks the language of HTTP actions to view, create, edit and delete data. ### The header Every API request and response contains a header. This is where you’ll find what’s called \*metadata\* or information about the data being exchanged between the API and its clients. A lot of different data points can be included in the header, but the most common ones you’ll come across working with Bubble are content–type and authorization\[^3\]. The Content-type is used to specify the media type of the data being transmitted so that it can be properly interpreted and processed. > For example, if a client is sending data to a server in the form of a \[JSON object\](#user-content-fn-4)\[^4\], it might include a Content-Type header with a value of ‘application/json’ to indicate that the data is in JSON format. In our earlier example of fetching the bubble.io web page, the Content-type would have a value of ‘text/html’ to indicate that the client is expecting an HTML document in response to the request. The authorization contains the information needed to authenticate the client sending the request. In the case of Bubble’s API, Bubble accepts what’s called a Bearer token. In an HTTP header, that line would look like this: \`Authorization: Bearer \` Bearer simply means that the client is a bearer of the given token. The token is a kind of password that the client has to authenticate themselves, often referred to as an API key. An API call doesn’t have to include authorization: it’s only needed when the API is not public. ### The body The body can contain additional data, such as the data being sent in a POST, PATCH or PUT request (GET requests also sometimes contain parameters in the body). After all, if you want to create or modify something in the database, you need to include the information that you want to store, such as a user’s email and name. The body is better suited than the URL to hold complex or larger volumes of data. Here's an example of what the body of a POST call might look like. In this example we're creating a rentalunit with three parameters: a name, a number and an isRented boolean\[^5\]: \`\`\`json { "unitname": "Unit A", "unitnumber": 3, "isRented": true } \`\`\` The information you see in this example is formatted in the JSON format. What is the JSON format? Bubble is built around the JSON format. This is a text-based format that is both easy for humans to read and write, and easy for machines to parse and generate. For example, let’s say we want to create a new user, we could include the following JSON-formatted text in the body: \`\`\`json { "name": "John Doe", "age": 30, "isAdmin": true, } \`\`\` As you can see, JSON is easy to understand, but even so, Bubble will mostly generate it for you. But working with APIs you may find it useful to look at the body of the request and response to learn more about what is being transmitted. What other formats can be used in the body? The format of the body is not always in JSON. Remember that in our header we can specify what the format of the body should be, so it follows that it can be other formats as well. What kind of format a server expects depends on how the server is set up. In the list below are some common formats. The most widely used format is JSON and you usually don’t need to specify any other format unless the external API documentation specifically instructs you to:\\ \\ \*\*Form data:\*\* is often used when submitting HTML forms. Form data is usually sent as key-value pairs, with the keys being the names of the form fields and the values being the data entered into the fields. \*\*XML (Extensible Markup Language)\*\* is a markup language that is often used to transmit structured data. \*\*Multipart form data\*\* is a format that is used to send large amounts of binary data, such as file uploads. \*\*Plain text:\*\* The body of an HTTP request can also be plain text, which is useful for transmitting simple data or messages. \## The full request Let’s imagine we’re building a system for keeping track of rental units, and we need to send an API call to the app to create a new rental unit. Putting together all the parts we’ve gone over the request may look something like this: \`\`\` POST https://appname.bubbleapps.io/api/1.1/obj/rentalunit Content-Type: application/json Authorization: Bearer { "unitname": "Unit A", "unitnumber": 3, "isRented": true } \`\`\` In this example, the URL contains the resource we want to access (rentalunit), the HTTP method is POST, the headers include Content-Type and Authorization, and the body contains the data being sent to create a new rentalunit. In the next sections we'll cover how you can set up incoming and outgoing requests with Bubble's different API tools. {% content-ref url="/pages/qUKrZ46apgYpRMnPhwEQ" %} \[The Bubble API\](/help-guides/integrations/api/the-bubble-api.md) {% endcontent-ref %} {% content-ref url="/pages/aHrCznvRmKoyVK3zfnIc" %} \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) {% endcontent-ref %} \[^1\]: If new data for specific fields is not included, those fields are overwritten with empty values, replacing the entire resource. \[^2\]: Unlike PUT, which replaces the entire resource, PATCH only changes the fields that are provided in the request, leaving other fields untouched. \[^3\]: \*Authorization\* is the process of determining \*\*what\*\* a client has access to when connecting to a server.\\ \\ Before authorization is done, the client must \*authenticate\* to prove \*\*who\*\* they are in order to determine what they should be given access to. This is what the \*token\* is for. \[^4\]: JSON (JavaScript Object Notation) is a simple way to store and share information in a way that both computers and humans can understand. Think of it like a code version of a Bubble database Thing where you have a field (key) such as \*first name\* and its value (value) such as \*John Doe.\*\\ \\ Jump to section: \[What is JSON?\](#what-is-the-json-format) \[^5\]: A boolean is a data type that can have two values: true or false.\\ \\ In Bubble, this is known as a yes/no field. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md). # Performance The Bubble team is constantly looking to optimize scalability and performance. This means improvements to both the Bubble platform to handle all the thousands of Bubble apps (our scalability and performance), as well as to the platform so that Bubble apps provide a good experience for their end-users. Performance and scaling of a Bubble app are heavily impacted by how the app is built. This page will give an overview of app performance and scalability as well as offer some concrete tips. ## General principles & tips about performance [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#general-principles-and-tips-about-performance) \* \*\*The less data being fetched, the faster the performance\*\* - a page often needs to fetch some data on page load; a page that fetches 100 things on page load will load faster than a page that fetches 1 million data items; similarly, fetching simple data types like numbers will be faster than fetching MBs of data \* \*\*Similarly, having many small, simple pages will be faster than having fewer, complex pages\*\* \* \*\*Keep any sorting or filtering as close to the original search as possible\*\* - Bubble already optimizes database queries in many ways, but performing a sort or filter at the database level is very efficient. This means that queries that apply :sort or :filter to them will tend to be more efficient than queries with sorting or filtering after some other kind of manipulation of the results (example: doing search:count will be more efficient than search:group by:count) \* \*\*Using advanced filters can slow queries down\*\* - An underlying principle is that if a filter (or sort) can be done "on the database", it will be faster than a filter (or sort) that Bubble has to do after retrieving an initial set of data from the database. Which filters are done on the database vs. not? Filters which show up in the Search palette (the additional sidebar which slides out when you click "Do a search for") are done on the database and are thus are generally fast. Filters which are applied with :filter are generally "advanced" filters that are generally slower. \* \*\*Chained queries run in series, not in parallel\*\* - With Bubble it's possible to use the results of one search as the constraints of another search, and so on. These searches run in series, not in parallel, so if the first search returns a lot of data, that will slow the second search down, and so on \* \*\*Bubble already does a lot of performance optimization\*\* - Bubble tries to run queries on the database, resize images on the server, tell the browser to cache Javascript, etc. as appropriate. If you're running a query that feels relatively simple and retrieves a relatively small amount of data that's running very slowly, check if there is some optimization that can be done to the app's data hierarchy or queries, based on some of the guidance here \* \*\*In general, the simpler way to express a query is faster\*\* - Not always true but a good rule of thumb. Bubble is constantly working on database optimizations for the most common patterns \* \*\*Avoid modifying data on every page load\*\* - Changing element states is more performant than making additional database calls to accomplish the same behavior \* \*\*Try moving expensive calculations to behind-the-scenes scheduled workflows\*\* - A scheduled workflow can run the heavy query then save the result somewhere to use later; this is more performant than running the heavy query on a page load \* \*\*Use the "Make changes to a list of X" workflow action cautiously\*\* - This action is great when making a quick change to a short list of things, but as the number in the list grows, it quickly raises the risk of the workflow timing out. If you're experiencing timeouts with this action, consider instead "Schedule API Workflow on a list", which is more performant because it takes the list and schedules an API Workflow to run on each item of the list, separately (i.e. lowering the risk of a timeout) {% hint style="warning" %} Watch out! Your Bubble app's database is very flexible and powerful. It can store a lot - but if you try to store too much data in one field, it can lead to performance issues relating to that field. For example, if you have a Blog data type with a field for Contents, this should be able to handle blog posts just fine. But, if you try to stuff all the contents from Wikipedia into that one field, it probably will not work as well! More realistically, if you try to store a base64-encoded image (which is a lot of text) in a text field, this can lead to slower performance and unexpected behavior. {% endhint %} ## What happens on page load? [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#what-happens-on-page-load) Here is a rough sequence of events of what happens when Bubble loads a page: 1. Bubble sends the code for all the elements (visible and invisible) 2. Bubble draws all the \*visible\* elements on the page 3. Bubble fetches all the dynamic data needed for the \*visible\* elements This means: \* Invisible elements aren't drawn until they get displayed later... \* ...unless a visible item refers to an invisible item's data source. (Note that using one visible element to cover another visible one does not make the latter one "invisible" in this context!) \* For page load speed, the number of elements is a bigger factor than the type of elements All the element types are fairly similar to each other in terms of performance, with two exceptions: 1. Repeating groups load different amounts of data depending on the Layout Style property; notes on performance of the different choices are in the \[Reference\](https://bubble.io/reference#Elements.RepeatingGroup.data\_source). Note also that the more elements there are in each cell of the repeating group, the more time it takes to render the page 1. A repeating group with 10 cells each with 2 elements is faster than 20 separate elements, but slower than 3 elements 2. A \*nested\* repeating group has a multiplicative effect on the number of elements! 2. Plugins have their code included on each page load regardless if it's used. This isn't as big a performance impact because Bubble won't \*render\* the plugin if it's not used, but in general, it's a good idea to uninstall plugins that the app isn't using ## Working with soft limits [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#additional-notes-about-performance) \### Hard vs soft limits Before we look at how different limitations might affect your project, we'd like to briefly cover the concept of hard and soft limits: \*\*Soft limits\*\* are flexible boundaries that can be exceeded in but may impact performance or stability. Soft limits are influenced by factors such as the structure of your application and your pricing plan. For instance, a large volume of database records with substantial data can result in slower search performance. \*\*Hard limits\*\* are fixed boundaries that cannot be exceeded. Some hard limits can be increased by upgrading to higher pricing plans, and others can be circumvented through thoughtful app design and optimization, but as a developer you should be aware of them and how they might affect your project. {% hint style="info" %} You can read more about hard limits in our dedicated article on the subject: Article: \[Bubble's hard limits\](/help-guides/maintaining-an-application/performance-and-scaling/hard-limits.md) {% endhint %} ### Timeouts Timeouts can happen when a specific action takes too long to complete and is terminated by the system. They are used to prevent a single request or app from monopolizing server resources, to make sure that all applications on our shared servers remain responsive and performant. ### Predicting and planning for limitations As with any database system, slowdowns, timeouts and errors when applying pressure on the Bubble server can be challenging to predict and plan for and depend a great deal on how your app is designed and the volume of data you are working on. Timeouts are rare, but can be challenging to predict and can lead to data loss and other consequences as a result of a process being terminated before it has finished. While we can document the hard limits you might encounter, soft limits are more complex as they can vary greatly depending on what your app is doing. To minimize the risk of slowdowns and timeouts, we recommend you break up complex processes into smaller chunks. ### Throttling and how it may affect timeouts If your app spends its near-maximum allotted capacity for some time (closing in one one minute), your app may be throttled to keep it running without exceeding capacity. This can lead to a negative feedback loop where workflows are slowed down and exceed their hard timeout limit as a result. Therefore, timeouts may appear to be unpredictable, as a process may complete successfully on one occasion but time out on another. We recommend thinking holistically about your app's total capacity and keep in mind that simultaneous process can affect each other. If you can, try to move heavy processes to times when your app is less active (for example at times where you have fewer active users) ## Known soft limits ### SVG image size SVG images are stored in XML code which is parsed by your browser to render a vector-based graphic that can be scaled up or down without losing resolution. This is different from raster images, such as JPEG or PNG files, that can become pixelated when scaled beyond their original size. This makes SVG files very useful in many situations, but we recommend a \*\*soft limit of 1 Mb\*\* for SVG files to avoid the local device slowing down when processing the file. ### Searches with the :advanced constraint Searches that use the :advanced operator can be more taxing on the server. While there's not a hard limit on what you can search through, we generally don't recommend using this constraint on more than 10,000 things. ## Additional notes about performance [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#additional-notes-about-performance) The power of reuse: \* If a page has the same search in more than one place, Bubble will automatically combine them to run the query once \* Leveraging Styles helps improve performance \* The first few times you run a particularly heavy search might be a bit slower than future runs, because after Bubble sees a heavy query run a few times, Bubble builds an index that should massively speed up the search in the future (building the index could take up to an hour or so) X vs Y: \* An action that changes a dozen fields is more efficient than a dozen actions that change one field \* Changing a list of things is fast for relatively small lists, but for bigger lists, an API workflow will be more scalable since it doesn't run the risk of timing out the workflow \* When changing a (large) list, recursively calling an API workflow for subsequent items on the list is more scalable, though a bit slower, than running the API workflow on the entire list at once \* Navigating to a new page via a link element is generally a little bit faster, because workflow actions that navigate will wait on other workflows to save data before changing the page \* For situations where data type A has connections to multiple Bs (e.g. posts having categories but only one category per post; A = category, B = post), having a field on B that references the A it belongs to is generally better. Having a field on A that lists out all the Bs that belong to it is not going to work as well when that list can get very long \* For API workflows, the number of items the workflow has to act upon is a bigger impact on performance than the size of each item ## Capacity [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#capacity) In non-technical terms, "capacity" measures how much "stuff" your app can do in a given period of time. A user coming to your website uses a bit of capacity; having hordes of users coming to your website uses much more capacity. Calling the database uses capacity; performing lots of heavy database queries uses much more capacity. Running certain workflows (the ones that happen on the server) uses capacity, and similarly calling an app's APIs uses capacity. Throughout Bubble, there are references to "units" of capacity. A "unit" is a weighted measure of different scarce resources that Bubble's systems use; it includes factors like server CPU time, database CPU time, other backend systems, and more. The exact formula for a "unit" will change over time as Bubble adds, removes or improves backend systems; one of Bubble's goals is to improve the amount of user-facing performance that a unit of capacity delivers. On certain Bubble \[pricing tiers\](https://bubble.io/pricing) (namely Free and Personal), the app will have "Basic" server capacity, which means it's sharing the same computing resources with all other Bubble apps of these tiers. When an app is upgraded to the "Professional" and "Production" tiers, the app gets dedicated or "reserved" units of capacity which are reserved for that app. When capacity is exceeded, the app is rate-limited; again in non-technical terms, it means the app won't be able to do as much "stuff" in a given period of time, and users' requests on the app will effectively be slowed down. Thus, having more capacity generally means that the app can do more "stuff" if a lot of "stuff" is going on. There's a slight twist to this. Capacity can be compared to how many checkout lines there are at a grocery store. If the store adds more lines, it can handle more customers checking out at the same time. But, if a customer comes along with a cart of hundreds of items, that customer will still take up a whole checkout line for a while; also, having more checkout lines doesn't mean that resource-intensive customer will finish faster. Similarly, having more capacity won't make a very complex database query run that much faster - it's like that one customer checking out with a lot of items in their cart. (There is a caveat to this: if Bubble detects that a large query will eat up all of an app's capacity, Bubble will slow down that query to try to maintain a reasonable user experience for the rest of the app. Thus, in certain situations, adding capacity \*might\* make a large query run faster.) Users can see how much capacity their apps are using by going to Logs on the left-side nav. The first chart shows how much time the app has hit its maximum capacity; the second chart shows how much capacity has been used by the app relative to its maximum capacity. Further down on the page is the server capacity usage details chart, which shows the breakdown of capacity used by different parts of the app within the past 24 hours. If an app is slow and is hitting capacity limits, purchasing reserved additional capacity may help. {% hint style="warning" %} \*\*Note:\*\* Our server logging provider, AppOptics, has limits on the metric we use for the Maximum Capacity charts. Very high-activity Bubble apps may hit this limit when trying to query the logs for a long time period (i.e. 30 days). If this happens in your app, consider setting the chart date range to a shorter duration (i.e. 7 days). {% endhint %} ## What about dedicated instances? [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#what-about-dedicated-instances) Dedicated instances can help with performance in three primary ways: 1. Geography - a dedicated instance can be located geographically closer to your users, which helps with the performance of large static assets 2. Heavy data operations - these can be substantially faster on a dedicated instance 3. Stability - with dedicated instances you can test an app on the main Bubble cluster before upgrading the dedicated instance; this can be useful for ensuring an app's stability with a new version of Bubble, as well as eliminate the risk of a Bubble-wide outage {% hint style="info" %} If you're interested in hosting your app on a Dedicated instance of Bubble and want to learn more, please contact our sales team \[here\](https://bubble.io/contact-sales). {% endhint %} ## In closing [](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md#in-closing) At the end of the day, the above are general guidelines that are meant to provide some transparency into factors impacting performance. However, these are only guidelines; if performance is critical in a particular case for your app, try testing different approaches empirically to see what's faster\\!\[ \ \](https://manual.bubble.io/architecture-optimization-and-limits-of-the-bubble-engine) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger.md). # The native mobile debugger ## Overview The Mobile Debugger lets you inspect and debug your mobile app directly in Web Preview. It includes tools for checking workflows, viewing element properties, identifying runtime issues, and testing your layout across different device sizes. The debugger appears as a persistent panel on the right side of the preview and stays visible as you interact with your app. ## Features #### Workflow debugging Run workflows in Normal, Step-by-Step, or Slow mode to see how actions execute in real time. You can trace each step, monitor values, and catch unexpected behavior. You can also add breakpoints in the workflow editor to pause execution at a specific action and inspect it at the moment it runs. #### Inspector mode Hover over elements in your mobile app to see their properties, conditional states, and dynamic values. This makes it easy to identify why something is or isn’t displaying as expected. #### Error and warning monitoring A floating panel in the debugger displays runtime errors, resource limits, and other relevant warnings. This helps you quickly spot and resolve issues during development. #### Device preview toggle Switch between common mobile screen sizes to test how your app appears across different devices. This is helpful for identifying layout issues and testing responsive behavior.\\ \\ Persistent debugger panel\\ The debugger stays docked to the right side of the screen during Web Preview, so you can inspect and interact with your app at the same time. It updates automatically as you navigate or trigger events.\\ \### How to use it 1. Open your mobile app in Web Preview from the Bubble editor. 2. Click the debugger symbol in the upper left corner of the web preview, ![](https://manual.bubble.io/files/AJYXLOZlEaEDChkDQTZw) 3\. The debugger panel appears on the right-hand side. 4\. Interact with your app and use the debugger controls to inspect elements, run workflows, and monitor errors. ![](https://manual.bubble.io/files/fucEtihMTeThyEtEn0NU) **Debugging workflows** allows you to inspect actions as they are triggered in your app. ![](https://manual.bubble.io/files/SZ2d9nzrkkjQWxjX6tYj) **Inspecting elements** lets you view the details of individual elements in your app. \## Notes \* The Mobile Debugger is only available for apps built using the mobile editor. \* It functions only in Web Preview and is not currently available in live mobile environments. The Disable Zooming property is enabled by default to prevent unintended pinch-to-zoom behavior during debugging. This can be turned off in the element’s settings if needed. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/integrations/api.md). # API {% hint style="info" %} The \[Bubble API\](/help-guides/integrations/api/the-bubble-api.md), including both the Data API and Workflow API, is only available on \*\*paid plans\*\*. See the \[pricing page\](https://bubble.io/pricing) for more information about our plans. The \[API Connector\](/help-guides/integrations/api/the-api-connector.md) is available on all plans. {% endhint %} One of Bubble's most powerful features is its ability to connect to other applications on the web. By using what's called an API connection, your application can fetch data and execute commands in external software systems and vice versa. ![Bubble API connections illustration](https://manual.bubble.io/files/QvqqzF2bXsNcJqoU9hfY) APIs let you connect to other applications and vice versa. \## Introduction to APIs In \[this section\](/help-guides/integrations/api/introduction-to-apis.md) we'll cover how APIs work in general. This is a fairly technical section that takes an in-depth look at the underlying structure and mechanics of a \[RESTful API call\](#user-content-fn-1)\[^1\]. The information in this section is not needed for you to set up incoming and outgoing API requests in Bubble, but by knowing the basics you may find it easier to understand external API documentation and Bubble's settings. {% hint style="warning" %} Bubble is a highly flexible platform. This means that while we offer robust API security features, we don't enforce their utilization. It is essential to possess an understanding of the fundamental principles of API management, such as authentication\[^2\] and authorization\[^3\], in order to effectively secure one's implementation of the platform. {% endhint %} Throughout reading this guide you may find it useful to check our \[API Glossary\](/help-guides/integrations/api/api-glossary.md) if there are terms and definitions you are unsure about. ## Getting started If you are unfamiliar with how APIs work, we recommend starting with our introductory articles. The rest of the manual and reference entries will be easier to follow with an understanding of the basic principles: While there are an abundance of different services you can connect to via an API, most of the follow the same basic architecture called \*\*REST\*\*. {% content-ref url="/pages/SvTUzKhkueDh2ZxizViM" %} \[Introduction to APIs\](/help-guides/integrations/api/introduction-to-apis.md) {% endcontent-ref %} {% content-ref url="/pages/Ec5Rmh0W3XxxVfukBzPY" %} \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) {% endcontent-ref %} {% content-ref url="/pages/0hwfp6f65g3QOddJEOp2" %} \[API Glossary\](/help-guides/integrations/api/api-glossary.md) {% endcontent-ref %} ## ## The Bubble API manual In \[this section\](/help-guides/integrations/api/the-bubble-api.md) we cover the different API tools that Bubble offers. An API is either \*\*incoming\*\* or \*\*outgoing\*\*. An \*\*incoming\*\* \*\*request\*\* means that an external system is initiating a connection with your Bubble application to read/manipulate data or start a workflow. This is handled by the Bubble API. ![](https://manual.bubble.io/files/TuoeQt5SijIhIEYGX1yM) An \*\*outgoing request\*\* means that your application initiates a connection with an external system to work with data or execute an action. This is handled by the API Connector. ![](https://manual.bubble.io/files/doPG6C6Ye9dfT1OFV7Bs) Incoming Connections (The Data API and API Workflows) Incoming requests are calls that are initiated by an external system, such as another app. They are split into two different tools: \* \*\*The Data API\*\* allows other applications to connect to your app's database to read, create, edit and delete data\\ Article: \[The Data API\](/help-guides/integrations/api/the-bubble-api/the-data-api.md) \* \*\*API Workflows\*\* allow other applications to execute workflows in your application remotely\\ Article: \[API Workflows\](/help-guides/integrations/api/the-bubble-api/the-workflow-api.md) Outgoing Connections (The API Connector and plugins) Outgoing connections mean that your Bubble application initiates a connection with an external system to work with data or execeute an action. This is handled by two different tools in Bubble: \* \*\*The API Connector\*\* allows you to establish an API Connection with any third-party app or system that adheres to the \[RESTful\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) architecture.\\ Article: \[The API Connector\](/help-guides/integrations/api/the-api-connector.md) \* \*\*Plugins\*\* are extensions that can be installed in your Bubble application to serve different functions. Many plugins allow you to easily connect to different well-known APIs without having to set it up in the API Connector.\\ Article: \[Plugins that connect to APIs\](/help-guides/integrations/api/plugins-that-connect-to-apis.md) API technical reference If you are already familiar with how APIs work and want to see our technical reference, go here.\\ \\ Section: \[API reference docs\](/core-resources/api.md) \## Other ways to learn: Video lessons Tutorials \* \[Intro to APIs and the API Connector\](https://www.youtube.com/watch?v=nO8PSqeJaWk\\&t=745s) \* \[Setting up Google API keys\](https://www.youtube.com/watch?v=ouGT55o68ho) Webinars: \* \[Bubble Webinar 2 - The API Connector\](https://www.youtube.com/watch?v=DXsL4FjAhd8) \* \[Bubble Webinar 4 - API Workflows\](https://www.youtube.com/watch?v=zoPCX34Y8Io\\&t=63s) \[^1\]: REST, or Representational State Transfer, is not actually a protocol, but more of a set of guidelines that define how a client and server should interact with each other.\\ \\ Article: \[What is a RESTful API?\](/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md) \[^2\]: Authentication is the process of determining \*\*who\*\* a client is when an API request is received. \[^3\]: Authorization is the process of determining \*\*what\*\* an API client has access to after authentication has taken place. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/integrations/api.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning.md). # Transitioning from the legacy version control {% hint style="info" %} The new version control system introduces new terminology. We have compiled a list of the terminology of the new system, as well as the terms that are no longer used: Article: \[Version control terminology\](/help-guides/maintaining-an-application/version-control/terminology.md) {% endhint %} {% hint style="info" %} The transition process described below is only relevant to existing apps with multiple development versions. If version-test is your only development version, your app will automatically be upgraded to the new version control system, and version-test will become the Main branch {% endhint %} The \[legacy version control system\](#user-content-fn-1)\[^1\] had a linear approach to managing application changes, allowing separate versions to be created and worked on in isolation. However, this method had its limitations, especially when it came to collaboration and managing the development of major new features. The new branch-based system offers a more flexible, powerful, and collaborative approach to managing app development. This article guide will give you an overview of how to transition from the old Bubble version control system to the new system. Throughout the guide, we will discuss key concepts, such as branches\[^2\], merging\[^3\], and managing conflicts\[^4\], and provide step-by-step instructions to help you get started with the new system. ## Upgrading to the new version control If you have at least one custom version in the legacy version control system, you will be asked to opt-in to the new system. {% hint style="warning" %} \*\*Note:\*\* The upgrade to the new version control system is permanent and cannot be undone. {% endhint %} You will find the button to upgrade when you click the current version control menu bar link in the upper right corner of the Bubble editor: ![](https://manual.bubble.io/files/1CXdFAU23WcB4KdepyCg) \## General advice ### Versions are now \*branches\* A key aspect of the new version control system is that what used to be called \*versions\* are now called \*branches\*. This new terminology better describes how the system works, as we have moved away from the linear systems of separate versions into a parent-child based "tree" of branches that can be added and removed as needed. This helps you work not only on new features, but it allows you to further separate development on those features into child branches that can later be merged upwards into the parent. ### No data or ongoing work will be deleted when you make the transition Before we dive into the process of transitioning to the new branch-based system, it's important to clarify that the new system is compatible with any existing versions you have. In other words, you will not lose your versions when you choose to activate the new version control system. It may still be useful to clean out your versions ahead of upgrading and to get to know our \[recommended best practices\](/help-guides/maintaining-an-application/version-control/best-practices.md). This helps you get a clean start and set up a structure that makes sense for your team. ## Transition scenarios We’ll now cover two different scenarios that require slightly different steps to getting up and running smoothly. ### Scenario 1: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and your last deploy to Live was made from \*version-test\* When you turn on new version control, you’ll notice the brand new UX and that version-test is now the Main branch. \* Any custom versions you created previously will show up below the Main branch. \* Any in-progress work remains undisturbed \* The new \*\*Main branch\*\* (formerly the \*development version\* or \*version-test\*) is the only branch that can be deployed\[^5\] to Live. The \[hotfix branch\](#user-content-fn-6)\[^6\] can also be deployed, but they are meant for quick bug only fixes in the Live environment and block other development work until the hotfix is deployed or deleted. If your last deploy to Live was made in the \*\*development version\*\* (a.k.a. version-test), and no changes were made in development since that deploy, you should be able to proceed as usual as your Main branch is up to date with Live. If your last deploy to Live was made in version-test, and there is in-progress work since the last deploy that you want to save, create a new branch off of Main. This new branch will be a mirror image of the old development version. You can then reset your Main branch to match Live by using the “Reset to Live” feature in the \*More actions\* dropdown in the top right of the version control panel. This will ensure that Main is a carbon copy of the Live branch so that any future deploys will proceed smoothly. Then, when you are ready, you can merge any changes into Main and deploy those changes to Live. ### Scenario 2: Your app is on an Agency Plan, Professional Plan, Production Plan, or Dedicated Plan and Your last deploy to Live was made from a \*custom version\* When you turn on new version control, you’ll notice the brand new UX and your development version will automatically turn into the Main branch. Any custom versions you created previously will show up as branches below the Main branch. \* Any in progress work remains undisturbed \* The \*\*Main branch\*\* is the only branch that can be deployed to Live. Hotfix branches can also be deployed, but they are meant for quick bug fixes in the Live environment and block other development work until the hotfix is deployed or deleted If your last deploy was made in a \*\*custom version\*\*, there is a good chance that version-test does not have the same changes that Live has - which will be required to deploy anything to Live in the future. Since version-test is now Main, and Main is the only branch that can be deployed to Live, you’ll want to move some things around to adjust to this new flow. \* If there is any in-progress work in version-test (now Main) that you want to save, create a new branch off of Main. This new branch will be a mirror image of the old development version. \* Navigate to the Main branch and reset the Main branch to match Live by using the “Reset to Live” feature in the More actions dropdown in the top right of the version control panel. This will ensure that Main is a carbon copy of the Live branch so that any future deploys will proceed smoothly. \* For any work in a custom branch that is ready to be deployed, first sync that custom branch with Main (using the button in that branch’s version control panel) to make sure that branch is up to date with Main/Live and then merge that branch into Main. When the branch has been merged, you can deploy Main to Live. \* For any new work, create a custom branch off of Main and use that new branch for any development work. When you are ready to merge that work and deploy to live, sync that custom branch with Main (using the button in that branch’s version control panel) to make sure that branch is up to date with Main/Live and then merge that branch into Main. When the branch has been merged, you can deploy Main to Live. {% hint style="info" %} Good luck with the transition! To further get to know the new version control system, we recommend reading our introductory article and study the new terminology. Article: \[Version control\](/help-guides/maintaining-an-application/version-control.md) Article: \[Version control terminology\](/help-guides/maintaining-an-application/version-control/terminology.md) (direct link: \[legacy terms that have been updated\](/help-guides/maintaining-an-application/version-control/terminology.md#legacy-terminology-and-replacements)) Article: \[Legacy version control documentation\](broken://pages/-MTkIpqXJeh-\_-WM8Vmc) {% endhint %} \[^1\]: The legacy version control system is an older system that has been replaced by the current one.\\ \\ Legacy documentation:\\ Article: \[Version control\](broken://pages/-MTkIpqXJeh-\_-WM8Vmc) Reference: \[Version control\](broken://pages/-MUAadN-IznA2oAdL2UA) \[^2\]: A branch is an independent iteration of your application that can be developed in isolation. You can see the creation of a branch as splitting your app into two copies, kind of like two cells dividing. The cells are genetically identical clones at first, but can keep evolving independently of each other.\\ \\ Article section: \[Environments and branches\](#environments-and-branches) \[^3\]: To merge is the process of integrating changes from the source branch into the base branch. Article section: \[Merging branches\](/help-guides/maintaining-an-application/version-control.md#merging-branches) Reference: \[Merging branches\](/core-resources/bubbles-interface/version-control-deployment.md#merge-changes-from-another-branch) \[^4\]: Conflicts arise during the merge process when the base branch and the source branch each changed the same thing (in different ways) since the last time the two branches were in sync.\\ \\ To resolve conflicts that arise during the merge process, you must select which change to favor.\\ \\ Article section: \[Merging branches\](/help-guides/maintaining-an-application/version-control.md#merging-branches) Reference: \[Merging two branches\](/core-resources/bubbles-interface/version-control-deployment.md#merge-changes-from-another-branch) Video lesson: \[Resolving conflicts\](https://youtu.be/ece8V74yltc) \[^5\]: To deploy a branch is to push changes to Live. Only the Main branch and the hotfix branches can be deployed to Live. \[^6\]: The hotfix branch is the only branch apart from Main that can be merged directly to Live. The purpose of this branch, as the name suggests, is to address urgent issues that can be fixed quickly.\\ \\ Article section: \[The hotifx branch\](/help-guides/maintaining-an-application/version-control.md#the-hotfix-branch) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/html-and-css.md). # HTML and CSS This article explores the similarities and differences between HTML/CSS and Bubble. First, let’s establish a simple fact: Bubble allows you to build web applications using the same languages that web browsers recognize – including HTML and CSS. While Bubble is often described as a no-code platform, a more accurate description in this context is that it takes the app that you have built visually, and then generates the underlying code—HTML, CSS, and JavaScript—that browsers can execute. When you view a page created in Bubble, what you see is the browser’s interpretation of this code. The JavaScript files acts as an “engine” that not only powers the page and its functions but crucially, it also manages communication between the user’s device and the Bubble server. This is useful for those with an HTML and CSS background, as you'll quickly recognize that the logic and structure are fundamentally similar. However, Bubble adapts these principles to help non-technical users easily design and style their apps. Instead of typing code, it’s all done visually, using the page editor and styles. This holistic approach means that Bubble’s way of designing and the accompanying terminology may feel somewhat different from what you are used to, but you'll quickly find that the underlying principles share many commonalities. ## Page design and styling ### Elements Building a user interface with HTML and CSS involves writing markup\[^1\] and styling code. You manually define the structure using HTML tags and style elements with CSS properties. For example, to create a button, you might write: \`\`\`html Click Me \`\`\` And then add the CSS properties: \`\`\`css .my-button { background-color: blue; color: white; padding: 10px; } \`\`\` You may also need to handle responsive design using \[media queries\](#user-content-fn-2)\[^2\] and other techniques to ensure your layout adapts to different screen sizes. Bubble moves the process of writing this code in HTML and CSS into its visual editor, essentially hiding the code from the user. You drag and drop elements\[^3\] onto the page, adjust their properties, set conditions\[^4\], and define workflows that dictate how elements behave. There is a large collection of core elements available, such as: \* Buttons \* Links \* Text elements \* Input forms and rich text input forms \* File/image uploaders \* Icons \* HTML elements \* Map elements You can read more about the built-in element types in this article series. Additionally, you can extend with more elements using plugins and/or custom code and Javascript libraries. ![](https://manual.bubble.io/files/ohuPYlRzWrER3WiIMftr) Bubble allows you to control an element's styling properties and responsive behavior in a visual manner. To create a button, you simply place a button element on the page and customize its appearance through the editor. Bubble automatically handles responsive design, allowing you to set breakpoints and adjust styles visually. ![](https://manual.bubble.io/files/SmRNpO7NsUPHybl3wt6j) Bubble has a built-in responsive editor that allows you to flexibly test your design using customizable breakpoints – and every pixel value in between. Article series: \[Elements\](/help-guides/design/elements.md) ### Containers Containers is the umbrella term for a set of elements in Bubble that includes: 1. \*\*Group:\*\* A versatile container element that can hold other elements such as text, images, and buttons. 2\. \*\*Repeating group:\*\* A dynamic container used to display a list of data from a query, or in Bubble terms, a data source. Each cell in a repeating group can contain a set of elements that are repeated for each item in the data source, making it ideal for displaying lists, tables, or galleries. 3\. \*\*Floating group:\*\* A container that remains fixed on the screen while the rest of the content scrolls. Floating groups are useful for creating sticky headers, footers, or sidebars that stay visible as users navigate through the app. 4\. \*\*Popup:\*\* A modal container that appears over the current content when triggered. Popups are used for dialogs, notifications, forms, and other content that needs to be presented in a separate layer without navigating away from the current page. Popups can also apply a whiteout effect, essentially partially/fully hiding or blurring the content below. 5\. \*\*Group focus:\*\* A container designed to display content relative to a target element. It is typically used for dropdowns, tooltips, or contextual menus that need to appear next to a specific element when triggered. Each of these containers doesn’t necessarily have a direct HTML/CSS counterpart but would instead require a combination of HTML elements and CSS properties to achieve the same functionality. In Bubble, these are set up as distinct element types to make it easier for users to make particular design decisions by picking elements with certain attributes. Article series: \[Containers\](/help-guides/design/elements/web-app/containers.md) ## Styles Bubble's Styles feature offers a user-friendly alternative to traditional CSS, allowing users to define and manage the appearance of elements through a visual interface rather than writing code. In CSS, you create class selectors and apply styles by writing and maintaining CSS rules in a stylesheet. This approach requires familiarity with CSS syntax and concepts such as specificity and inheritance. In contrast, Bubble's Styles feature lets you apply consistent formatting across your application by creating style presets for elements like buttons, text, and containers. These presets can be easily updated through the visual editor, automatically propagating changes throughout the app. When you create an app, it comes with a collection of pre-set styles that you can apply to elements right away. By using these styles (or creating your own), you can easily maintain consistency across your application. You can access the Styles tab to modify the appearance of all styled elements simultaneously by making changes in one place, similar to editing a CSS file in traditional web development. ![](https://manual.bubble.io/files/xZoRxDk24vcN4vIPIxZ5) The Styles tab in the Bubble editor lets you control the styling properties of elements in one central place. Circling back to the introduction to this article, Bubble’s aim isn’t to fundamentally replace HTML and CSS. Instead, Bubble seeks to make the design flexibility of these technologies accessible to a broader audience by providing a more visual and user-friendly approach. You can read more about styles in the article series below: Article series: \[Styling\](/help-guides/design/variables-and-styles.md) ### Font and color variables Bubble’s Styles tab includes both font and color variables that allow you to link fonts and colors with styles or directly with elements. By updating a font or color variable, you can change the appearance across your entire app. This approach is akin to defining styles in a CSS file and applying them with class selectors. For those with experience in UX design, this parallels the code concept of design tokens. Bubble’s visual interface makes this process easier, especially for non-technical users, by centralizing design management. This not only ensures consistency throughout your application but also encourages users without UX experience to consider design best practices. Article series: \[Styling\](/help-guides/design/variables-and-styles.md) | \[Font variables\](/help-guides/design/variables-and-styles/font-variables.md) | \[Color variables\](/help-guides/design/variables-and-styles/color-variables.md) ## Responsiveness If you are coming from an HTML and CSS background, you’ll know that responsiveness is a key aspect of modern web design, ensuring that applications look and function well on a variety of devices and screen sizes. Bubble addresses this need with its responsive engine, which is essentially a layer on top of Flexbox. While it follows the same principles, Bubble simplifies the process with a visual interface for working with the responsive properties of any style (similar to CSS classes) or individual container/element. This essentially means you can see the result as the properties as the properties are applied, and use Bubble’s built-in responsive viewer to test design solutions while you are building. Flexbox and Bubble's responsive engine share a lot of similarities: 1. \*\*Container-based layouts:\*\* Both Bubble’s responsive engine and Flexbox rely on containers to manage the layout of child elements. In Flexbox, a container is defined with the display: flex property, which allows you to control the alignment, direction, and distribution of the container's children. Similarly, in Bubble, you use container elements like groups and repeating groups to organize your content and control its layout. 2. \*\*Alignment and justification:\*\* Flexbox offers properties like justify-content, align-items, and align-content to control the alignment and spacing of child elements within a container. Bubble mimics this functionality with its visual settings for horizontal and vertical alignment and justification. 3. \*\*Direction and order:\*\* Flexbox uses the flex-direction property to define the direction of content flow within a container, either as a row (horizontal) or column (vertical). Bubble provides similar options, enabling you to set the direction of elements within a container. Additionally, both Flexbox and Bubble allow you to reorder elements within a container, either through the order property in CSS or by rearranging elements in Bubble by dragging and dropping or using the reorder buttons. 4. \*\*Flexibility and growth:\*\* Flexbox’s flex-grow, flex-shrink, and flex-basis properties allow child elements to grow, shrink, or maintain a fixed size based on the available space. Bubble incorporates these principles by letting you set an element’s minimum, maximum or fixed size within their containers. These settings tell Bubble that a given element should always stay within a specific pixel value or percentage of its container's width. 5. \[\*\*Breakpoints\*\*\](#user-content-fn-5)\[^5\] \*\*and\*\* \[\*\*media queries\*\*\](#user-content-fn-2)\[^2\]\*\*:\*\* While Flexbox itself does not handle media queries, responsive design often involves using them to adjust layouts for different screen sizes. In Bubble, you can define breakpoints directly within the responsive editor. At each breakpoint, you can customize the layout, visibility, and behavior of elements, similar to how you would use media queries in CSS to create responsive designs. Because you can save breakpoints in one centralized place, similar to styles and style variables, you can change the behavior of your entire app by making a single change in breakpoints. These breakpoints can be accessed through Bubble’s dynamic expression editor, making it easy to conditionally set the behavior of containers and elements. Article series: \[Responsive design\](/help-guides/design/responsive-design.md) \[^1\]: \*Markup\* is a way of writing text that defines the structure and layout of a webpage. It uses tags to specify elements like headings, paragraphs, images, and links, helping to organize and format content for the web. \[^2\]: Media queries are a way in CSS to make your website look good on different devices, like phones, tablets, and computers. They change the style of your website based on the size of the screen. \[^3\]: \*Elements\* are the building blocks that you place on the page to design your app, such as text, images, icons and buttons. Article series: \[Elements\](/help-guides/design/elements.md) \[^4\]: \*Conditions\* allow you to set rules for each element that changes how the element looks depending on whether the rule returns a yes or a no. Article section: \[Elements\](/help-guides/design/elements.md) | \[Conditions\](/help-guides/design/elements.md#conditions) \[^5\]: Breakpoints are specific points where the layout of your website changes to fit different screen sizes better. They help ensure your website looks great whether viewed on a small phone or a large computer screen. For example, a breakpoint of 320 px is often used as the smallest screen width (usually a phone) to which your app should be compatible. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/html-and-css.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/logic/conditions.md). # Conditions Conditions, or conditional expressions\[^1\], let you set up mechanisms that check whether a specific question returns a \*yes\* or a \*no\* answer and then take an action, stop an action or make a change in your app in response. {% hint style="info" %} Conditions rely heavily on the use of \*\*expressions.\*\* We recommend that you get to know how dynamic expressions work. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md)\\ Reference: \[Data sources\](/core-resources/data/data-sources.md)\\ Reference: \[Operators and comparisons\](/core-resources/data/operations-and-comparisons.md) {% endhint %} For example, if a user fills out a form but leaves a required field empty, a condition could be used to check whether the field is empty and, if so, prevent the form from being submitted until the missing information is provided. This is used in several different scenarios: \[\*\*Element conditions\*\*\](#element-conditions) lets you change the styling of an element based on the value returned by an expression. For example, you can make a button unclickable\[^2\] by asking the question "is the user logged out". ![](https://manual.bubble.io/files/MOWyATQQe9oZmzkAqaTT) Placing conditional expressions on elements let you change their styling based on whether the expression returns a yes or no answer. \[\*\*Only when-conditions\*\*\](#only-when-conditions-workflow-conditions) are placed on workflows\[^3\] or actions\[^4\] that have already been triggered, to stop them from running if the condition does not return a \*yes\*. Only when-conditions are both a useful part of Bubble's workflow logic and an important part of your app's security. For example, you can stop a \[\*Make changes to a thing\* action\](#user-content-fn-5)\[^5\] from running if an input field's value is empty. ![](https://manual.bubble.io/files/5MXUfl7XmgQiHxCuIRJ6) In this example, the _Create a new thing_ action will only run if the expression in the _Only when_ field returns a _yes_. If not, Bubble will skip it and move on to the next action in the workflow (if any). \*\*Do when-conditions\*\* are workflows that trigger automatically if an expression returns a \*yes\* value. For example you could run a specific value whenever the question "is the current user logged in" returns a \*yes\* answer. They can be set up to run once, or every time the value changes. ![](https://manual.bubble.io/files/ICmB8vcfUiUPT490FiD6) The event in this workflow checks whether the current user is logged in. When they are, the workflow will run. Note that it is set to _Run this just once,_ which means it will only run once per session (page load). {% hint style="info" %} \*\*Backend triggers\*\* are also workflows that triggers based on an expression, but they run in the backend and \*server-side\* meaning that they run independently of any page. They can be used to trigger changes in the database. \\ Article: Backend triggers {% endhint %} ## Element conditions Element conditions are used to change the properties of an element when an expression returns a \*yes.\* Element conditions consist of two steps: ![](https://manual.bubble.io/files/LEgXYkhYk5V2MSzUNFvR) 1\. The expression that defines when the properties in point 2 apply 2. The properties that should be modified when the expression in point 1 returns a yes In the example above, we make a button unclickable if the user is logged out. The styling is dynamic and instant, meaning that whenever data in the conditional expression changes, the styling of the element is immediately applied. You can place multiple conditions on the same element, and more than one can be active at once (for example, one condition could make the button unclickable and another could change its color). If there are conflicting style options, the condition at the bottom will override those at the top since conditions are read top-down (as such, the bottom condition is applied last). ### Applying styles with conditions Conditions can also apply a style to an element if certain criteria are met. For example, you can set up one style for "light mode" and one style for "dark mode", and when a condition is met, such as \`Current user's dark mode = yes\`, then the dark mode style is applied. ### Previewing conditions When editing an element's condition, you can click ON/OFF to preview what the element will look like with its properties changed. This has no effect on the element in Run-mode. {% embed url="" %} Our Academy quick tip on how to preview conditions on an element {% endembed %} ## Run-mode debugging As an element can have more than one condition, several conditions can be evaluated to yes on the same element. You will often have to debug an element's behavior when it involves conditions to understand its behavior, we recommend using the Debugger to inspect an element and figure out which condition is evaluated to true and how it impacts the element's appearance. ## Only when conditions (workflow conditions) \*Only when conditions\* are applied to workflows and actions to ensure they only execute when certain conditions are met. For example, if you have a button that triggers a workflow you can instruct Bubble to check every time the button is clicked whether to proceed running the workflow. ![](https://manual.bubble.io/files/x80x0cr21j215Ew1UdEU) In this example we have created a yes/no field called _Admin_ on the user and we check that it's set to yes on the current user. If a condition is applied to a \*workflow\*, it will prevent all actions within that workflow from being executed. It's also possible to apply a condition to an individual \*action\*, which will only prevent that specific action from running. ### Alternating workflows and actions You can also use conditions to alternate between different workflows depending on specific conditions. For example, you could have one workflow that completes a database operation like \[\*Create a new thing\*\](#user-content-fn-6)\[^6\] \*only when\* when current user is logged in and another workflow that shows an error message \*only when\* the current user is logged out. ![](https://manual.bubble.io/files/ZKgmsYfeRGJO4lfCVOXY) Here we have two workflows with the same trigger (button clicked) but only one of them will ever run, depending on the admin status of the user. The same can be achieved by placing conditions on individual actions. If you have workflows with multiple action steps, we recommend keeping the two alternatives in separate workflows as it makes it easier to manage. ## Creating efficient expressions {% hint style="info" %} To learn more about how expressions are evaluated, we recommend reading the section \*\*How expressions are processed\*\* in our article about dynamic expressions. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md)\\ Article section: \[How expressions are processed\](/help-guides/logic/dynamic-expressions.md#how-expressions-are-processed) {% endhint %} An expression is processed until it reaches a definitive yes or no answer. This means that if an earlier part of the expression provides the necessary response, Bubble will not evaluate the remaining parts. This is to optimize for efficiency, as it reduces the amount of work needed. You can further optimize your app by giving careful thought as to how your expressions are built. Knowing that Bubble evaluates from left to right and only processes what it needs to, we can make the app as efficient as possible by placing the fastest part of the expression in the beginning. It's difficult to set a hard rule for what makes an expression slow down, but we can give some general guidelines: \* Expressions that evaluate something based on information already on the page are generally the fastest. For example: \* Current user is logged in \* Element is visible/invisible \* Element's value is X \* Database operations such as \*Do a search for\* need to be sent to the server, processed and sent back to the device, meaning it can slow the expression down. The more complex the search, the slower. \* Operations that are processed on the device are generally very fast, but can become slow if they are doing complex processing. For example, if you have two repeating groups holding hundreds or thousands of things and you use the \*intersect\* operator on it (repeatinggroup1's list of things intersect with repeatinggroup2's list of things) you can end up with a process that takes some time to finish. ![](https://manual.bubble.io/files/cfSogiZqcCERrh2Ibpl2) Click the image to enlarge. In this example we are checking two things to verify if the task should proceed. The first is information that Bubble already has and can quickly check client-side. The second is a search that has to be performed on the server – it will take longer. By placing it last we can avoid having to check the last step if the user is logged out. By determining which components of an expression are likely to take up the most time, you can strategically arrange them such that the quicker parts are positioned at the beginning. By doing so, Bubble has a higher chance of finding the required answer in a shorter amount of time. ## Using conditions for security Conditional expressions are an important part of your app's security, but it's important to understand how some conditions provide proper security while others only provide obfuscation. ### Obfuscation versus security The phrase "Obfuscation is not security," is common when discussing security, and this holds true for Bubble as well. While obfuscation may increase the difficulty for an attacker to exploit vulnerabilities, it cannot provide sufficient security to be deemed truly secure. That's not to say that you should \*avoid\* obfuscation. It's always a good thing to make it more challenging for attackers to exploit vulnerabilities and it can also be an important part of the user experience. The important thing is to be aware of what can be considered and what can't. ### Element conditions Using conditions to hide/show element, make them unclickable/uneditable and/or changing their styling is a common way of providing and communicating security. ![](https://manual.bubble.io/files/MOWyATQQe9oZmzkAqaTT) It's a good practice to implement styling conditions as a part of your UX, but it should not be considered a secure way to stop a workflow from running. While this makes good sense from a UX perspective, it's important to note that it should not be considered secure. Since the elements on your page are part of the downloaded application code, a technical user could be able to find ways to change the styling, such as showing an element that is supposed to be hidden. As such, this should be considered \*\*obfuscation\*\*. ### Workflow conditions Placing conditions on your workflows and/or actions are a more secure way of stopping unathorized use and are, along with Privacy Rules\*,\* a central part of your security. Still, there are some guidelines you should follow to increase security: \* Conditions that can be checked server-side\[^7\] are more secure than conditions that rely on something on the \[client side\](#user-content-fn-8)\[^8\]. \* A typical example involving the server is to check something in the database, such as \*Current User's Admin = yes.\* Since Bubble can check this without relying on anything on the client's device, it can be considered secure \* An example of the opposite is to check something on the page, such as "Element X is visible" or similar things. This would rely on information on the user's device, and is easier to circumvent \* If you have multiple courses of action depending on a condition, it's easier to stay on top of your security if you place them in separate workflows, rather than in one workflow with conditions placed on each action. This minimizes the number of conditions you have to update if something changes. Always remember to test your app as different users to verify that conditions are working properly. \[^1\]: Dynamic expressions are like "live" formulas that update in real-time based on user input, database updates and other changes in your app. Article: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) \[^2\]: Note that making a button unclickable through styling can be overridden by a highly technical user, and should be considered a UX decision and not a security measure.\\ \\ To stop any workflow on a button from running, you should place a condition on that workflow too. This is the secure way of stopping a user from running a workflow they are not authorized to run. \[^3\]: A \*workflow\* is the combination of an \*event\* and one or more \*actions\*.\\ \\ The event triggers the actions to run and together they make up the workflow. For example, clicking a button could lead to deleting a database thing. The button click is the event, deleting the thing is the action and together they make up the workflow.\\ \\ Article: \[Workflows\](/help-guides/logic/workflows.md) \[^4\]: An \*action\* is a part of a workflow that performs a specific task. For example, when a user clicks a button (event) a thing is deleted in the database (action). The event and the collection of actions make up a \*workflow\*. \[^5\]: The \*Make changes to a thing\* action writes changes to a specific record in your database, such as saving a name on a user or an image on a produt.\\ \\ Reference: \[Make changes to a thing\](https://manual.bubble.io/help-guides/logic/pages/-MTujs88N9W-2FUmQGag#make-changes-to-thing...) \[^6\]: The \*Create a new thing\* action creates a new database record and optionally writes data to its fields.\\ \\ Article: \[The database\](/help-guides/data/the-database.md)\\ Reference: \[The Create a new thing action\](https://manual.bubble.io/help-guides/logic/pages/-MTujs88N9W-2FUmQGag#create-a-new-thing...) \[^7\]: \*Server-side\* describes things that happen on the server, as opposed to on the user's device.\\ \\ In the context of conditions, server-side conditions are those that can be verified on the server, such as checking something in the database. \[^8\]: \*Client-side\* describes anything that happens on the user's device, as opposed to on the server.\\ \\ In the context of conditions, client-side means checking whether something on the page (such as an element being visible) is true. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/logic/conditions.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md). # SQL If you are accustomed to working with \[SQL databases\](#user-content-fn-1)\[^1\], Bubble may feel both familiar and different at the same time. In this article, we’ll explore the similarities and differences between these two approaches, and how a small shift in mindset can help you understand the nuances of Bubble’s approach to data management. One key point to remember is that Bubble acts as a layer over SQL. It employs its own terminology and automates many SQL processes, including table joins, to make database construction intuitive, even for those without a technical background. Despite the different visual interface, Bubble’s database technology is built on PostgreSQL\[^2\], so the underlying logic remains the same. However, your SQL background might require a bit of adaptation, as Bubble’s automation and visualization of data management offer a unique approach compared to traditional SQL practices. ## Terminology Before diving into the specifics of database management, let’s examine how Bubble’s terminology differs from traditional SQL. These terms \*\*\*are not direct synonyms\*\*\* but reflect how each concept is applied within Bubble compared to SQL. Click any underlined term for more contextual information. | SQL | Bubble counterpart | | --- | --- | | [Database record](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-3) | Thing | | [Table](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-4) | [Data type](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-5) | | Column | [Field](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-6) | | Primary key | [Unique ID](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-7) | | Query | [Search/Do a search for](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-8) | | [Join](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-9) | [Custom field](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-10) | | Insert | [Create a New Thing](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-11) | | Update | [Make Changes to a Thing](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md#user-content-fn-12) | | Delete | Delete a Thing | \## Database setup The first difference you’ll notice is that databases are created automatically. When you create a new application, Bubble creates one database for the \[development environment and one for the live environment\](#user-content-fn-13)\[^13\], and the two operate independently of each other. Upon \[deploying your application\](#user-content-fn-14)\[^14\], the structure of both databases is synchronized, but their data content remains separate. In other words, unlike traditional SQL where setting up a database requires manual configuration, Bubble automates the process. With traditional SQL, you must install and configure a database server, create the database, and define the schema manually. This setup is typically done through command-line interfaces or SQL editors, using SQL syntax and commands. Additionally, in traditional SQL, you need to manually define tables, columns, data types, indexes, and relationships by writing SQL scripts or using database management tools. Creating separate environments for development and production involves setting up different instances or databases, configuring connections, and managing migrations and synchronizations between them. In contrast, Bubble handles all of this for you in the editor. You can define your data types (equivalent to tables) and fields (equivalent to columns) without writing any SQL code. Bubble’s built-in features for data management allow you to create, modify, and delete data records without needing to write custom queries, making the process more intuitive and accessible for beginners. ### Users Bubble automatically generates a User data type when you create a new application. This data type includes an email field and secure handling of passwords. The User data type integrates with Bubble's built-in authentication system, making it easy to implement user login, sign-up, password reset, and other authentication features without manual setup or compromising security. ![](https://manual.bubble.io/files/SpgdGOWiEvvVaNr9wiBY) The User type is automatically set up in all apps. It comes with a set of built-in fields, but can be extended with custom fields as needed. Illustrated above with the _Name_ field of type _text_. While you can add as many additional fields (columns) to the User data type (table) as you want, there's no need to manually define the schema or relationships for user data—Bubble handles these aspects internally. ### Built-in fields Every data type in Bubble automatically includes a list of built-in fields that are pre-configured and managed by Bubble, providing useful metadata without requiring additional setup. \* \*\*Creator:\*\* Identifies the user who created the thing. \* \*\*Modified date:\*\* Automatically updates to reflect the last modification date of the thing. \* \*\*Created date:\*\* Automatically sets to the date and time the thing was created. \* \*\*Slug:\*\* A URL-friendly identifier that can be used for SEO and navigation. \* \*\*Unique ID:\*\* A unique identifier of each single thing, comparable to a primary key in SQL The data in these fields are populated and updated automatically, with the exception of the slug, which is set according to specific rules to ensure it remains URL-friendly. In contrast with traditional SQL, there’s no need for explicit schema definitions and additional logic to achieve the functionality offered by the built-in fields. The User type comes with the additional \*email\* field. \## Backups Bubble automatically handles database backups. They are handled at the platform level, meaning that Bubble will create incremental backups of both your app’s databases for every change that happens, without requiring user action. This also means you can restore backups to any specific point in time, within the timeframe allowed by your plan. The automated backup system is designed to be user-friendly, requiring no technical knowledge or configuration from the user. However, it differs from traditional methods in that you don’t have direct access to the backup files, but you can rewind to any point in time in your plan’s retention window, as well as export one or more tables to CSV. You can read more about how Bubble backs up both the app and its databases in this article. Article series: \[Restoring database backups\](/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups.md) ## Joining tables Joining tables in SQL and Bubble involves fundamentally different approaches due to the nature of each platform. In SQL, joining tables is an explicit, manual process. You write SQL queries using commands like JOIN, INNER JOIN, LEFT JOIN, and RIGHT JOIN to combine rows from two or more tables based on related columns. This process requires specifying the exact columns and conditions for the join, making it flexible but necessitating a solid understanding of SQL syntax and database relationships. In contrast, Bubble abstracts much of this complexity. Instead of writing queries, you create relationships between data types using custom fields (which are akin to foreign keys in SQL). When you need to combine data from different types, Bubble handles the underlying logic for you. This means you interact with a visual interface to define relationships between data types. ![](https://manual.bubble.io/files/oFo4LGqaqaAZTNTpvBmz) In the example above, we have set up a custom field on the User data type that links it to a company. In plain English, this means we can easily see which company any user is associated with. In Bubble, every "thing" (record) in the database has its own unique ID, similar to a primary key in SQL. However, unlike traditional SQL databases, you don’t need to reference this unique ID directly in the same way. Bubble simplifies data management by allowing you to create relationships between data types using custom fields, which acts more like foreign keys in SQL but with less manual effort. Let’s explore how different types of relationships can be handled in SQL and Bubble. While this is not an exhaustive list of all possible scenarios or methods, it illustrates how Bubble manages relationships in a more visual manner, helping you adapt to its approach. ### One-to-many In SQL, a one-to-many relationship is established by adding a foreign key in the table representing the “many” side that references the primary key of the table on the “one” side. For example, if you have a \*Projects\* table and a \*Tasks\* table, each task would include a project\\\_id column to indicate which project it belongs to. You would then write SQL queries to join these tables when you need to fetch related data. ![](https://manual.bubble.io/files/ozLlyTYMLMv9in1PYmo9) In this example (similar to the _User_ example above) we have linked a _Task_ with a _Project_. In Bubble, creating a one-to-many relationship is handled through the visual interface. For example, if you have two data types called \*Project\* and \*Task\*, you would add a field of type Project to the Task data type to link each task to a specific project. Conversely, you can add a field of type Task (as a list) to the Project data type to maintain a list of tasks associated with each project. ![](https://manual.bubble.io/files/Bb4FgM21Gu4YHDe9V6eN) In this example, we have linked the _Task_ and _Project_ data type from the Project data type instead. Note the second rectangle, showing the one-to-many relationship between the two: in plain English, a project can contain a list of tasks. \### Many-to-many In SQL, a many-to-many relationship is typically implemented using a join table (sometimes called a junction table). This join table contains foreign keys referencing the primary keys of the two related tables. For example, if you have \*Tasks\* and \*Projects\* tables, a TaskProjects join table would contain student\\\_id and course\\\_id columns to represent the many-to-many relationship. ![](https://manual.bubble.io/files/Bb4FgM21Gu4YHDe9V6eN) In Bubble, creating a many-to-many relationship involves adding a list field to both data types. For instance, if you have \*Task\* and \*Project\* data types, you could add a field of type Projects (as a list) to the Task data type, and a field of type Task (as a list) to the Project data type. This allows each task to be associated with multiple projects and each project to be associated with multiple tasks. ![](https://manual.bubble.io/files/6YTnTuggNtmUJ91Y2qAP) \### One-to-One In SQL, a one-to-one relationship is created by ensuring that both tables have unique constraints on their foreign keys, typically by using primary keys. For example, if you have a Users table and a Profiles table, each user would have a unique profile, and the Profiles table would include a user\\\_id column with a unique constraint to ensure one-to-one mapping. In Bubble, a one-to-one relationship is achieved by adding a custom field of one data type to another data type. For example, if you have User and Profile data types, you can add a field of type Profile to the User data type and a field of type User to the Profile data type. This setup ensures that each user is linked to a single profile and vice versa. ![](https://manual.bubble.io/files/agtbmDznJBwlYLFJ3VqT) Again, we are using a custom field to link two data types. If needed, you can add a _User_ field on the _Profile_ data type to link the other way too. \## Searching for data Instead of performing queries using SQL syntax, using commands like SELECT, WHERE, and JOIN, Bubble has a visual interface that lets you build dynamic expressions. Dynamic expressions let you set up data sources, of which a database search is a potential source. Searches in Bubble are configured using constraints, which act as filters to refine the data retrieved from the database. You specify these constraints visually, selecting fields and setting conditions without needing to write SQL queries. One key advantage of Bubble’s approach is how it handles relationships between data types. In SQL, you need to explicitly write JOIN commands to combine data from related tables, specifying the exact columns and conditions for the join. In Bubble, as we explored in the earlier section, relationships between data types are created through custom fields, which act like foreign keys. When you perform a search or build a dynamic expression, Bubble automatically manages these relationships, effectively handling the joins for you. For example, if you have two data types, Project and Task, you can link tasks to projects by adding a Tasks list field to the Project data type. When you search for projects, Bubble will include related project data without requiring you to write any join queries. ![](https://manual.bubble.io/files/sy20lVIXeS3LQSZCHXrE) In this _Do a search for_ expression we are querying the database for projects related to a specific task. Dynamic expressions in Bubble are designed to automatically reflect the latest data changes, ensuring your app always shows the most up-to-date information. Bubble accomplishes this by using a WebSocket connection to manage real-time updates. Whenever the database is modified, updates are instantly pushed through the WebSocket to all relevant users and pages. This process keeps your displayed data current without the need for manual refreshes or additional queries. ## Data security In traditional SQL databases, managing data privacy involves defining roles and permissions through SQL commands. Administrators write queries to specify which actions (like SELECT, INSERT, UPDATE, DELETE) users can perform on tables or views. Advanced security features, such as row-level security and view restrictions, require detailed planning and technical expertise, often handled by database administrators. Bubble simplifies data privacy with privacy rules. Instead of writing SQL commands, you define who can view, modify, and interact with data based on user roles and conditions. This intuitive approach makes it easy for users of all technical levels to implement robust access controls, ensuring data security without the need for deep technical knowledge. Bubble’s privacy rules automatically enforce these settings, providing a straightforward and secure way to manage data privacy. Article series: \[Protecting data with privacy rules\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md) ### Data API Additionally, Bubble offers a built-in inbound API feature that enables you to grant external systems and applications access to your app’s database through the Data API, allowing them to read and manage some or all of your database’s data. This access is also governed by privacy rules, allowing you to configure specific permissions based on the identity of the client, ensuring secure and controlled data interactions. You can read more about the Data API in the article series below. Article: \[The Data API\](/help-guides/integrations/api/the-bubble-api/the-data-api.md) \[^1\]: An SQL database is a system that uses Structured Query Language (SQL) to store, manage, and retrieve data. It organizes data into tables with rows and columns. \[^2\]: PostgreSQL is an open-source relational database management system that uses SQL to interact with data. It is widely used for both small and large applications in traditional code environments. \[^3\]: In this context, a “database record” refers to a single entry within a table. \[^4\]: In this context, “table” refers to the structure used to store and organize data. \[^5\]: You can set up as many custom data types as you need in your Bubble database. A data type is any isolated type of data that can include one or more fields, such as User, Task, Project, etc. Article series: \[The database\](/help-guides/data/the-database.md) \[^6\]: A \*field\* is a pie \[^7\]: Every thing (database record) in the Bubble database is assigned a Unique ID. This is akin to a primary key in traditional SQL development. \[^8\]: A \*Search\* is a query to the database to fetch data based on specific constraints. \*Do a search for\* is the name of the actual data source in Bubble. Reference: \[Do a search for\](/core-resources/data/data-sources.md#do-a-search-for)\\ Article: \[Finding data\](/help-guides/data/the-database/finding-data.md) \[^9\]: In this context, “join” refers to linking data from different tables through related fields. \[^10\]: In this context, “custom field” refers to a field set to a custom data type, meaning another data type that you have created in the database. Generally, custom fields refer to any field that is not built-in. \[^11\]: \*Create a new Thing\* is an action that creates a new thing (database record) and optionally populates its fields with data. Reference: \[Create a new Thing\](/core-resources/actions/data-things.md#create-a-new-thing) \[^12\]: \*Make changes to a Thing\* is an action that updates an existing thing (database record) with new information. Reference: \[Make changes to a Thing\](/core-resources/actions/data-things.md#make-changes-to-thing) \[^13\]: All Bubble apps are create with one development version and one live version. The article series below covers this in-depth.\\ \\ Article series: \[Version control\](/help-guides/maintaining-an-application/version-control.md) \[^14\]: \*Deploying\* your app in Bubble means publishing your application to a live environment, making it accessible to users. Article: \[Deploying your app\](/help-guides/publishing-your-app/deploying-your-app.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/variables-and-styles/font-variables.md). # Font variables Font variables allow you to centralize font settings and make changes to the font across multiple elements and styles. Instead of having to manually adjust font families in each instance they are used, you can simply modify the font variable in one place and watch the change propagate throughout your app. ![Font variable settings in Bubble](https://manual.bubble.io/files/2YvxdYUgvj4pUfR5VsIl) For newly created apps, the default styles will be set to the "App Font" by default. ### Do font variables apply to styles? Yes, Font variables apply to styles\[^1\], meaning that if you update a Font variable it will automatically be updated on all styles that use that variable. By combining the two you can set up a flexible styling system that lets you make future changes with ease. \[^1\]: The Styles tab in Bubble provides you with a centralized place to define and manage all of your app's styles. Styles create a consistent, visually appealing design for your app while making it easier to update that design in the future.\\ \\ Article: \[Styles\](/help-guides/design/variables-and-styles/styles.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/variables-and-styles/font-variables.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer.md). # Issue explorer {% hint style="info" %} The Issues Explorer scans for various types of issues. Refer to the article below to see which security checks are included with each plan. Article: \[Security dashboard plan features\](/help-guides/security/security-dashboard/security-dashboard-plan-features.md) {% endhint %} The Issues Explorer is the security dashboard's generated security report, displaying potential vulnerabilities in a detailed, line-by-line format. The report is organized in a table format with the following columns: \* \*\*Type:\*\* This column categorizes the type of vulnerability each row addresses, helping you quickly identify the nature of the issue. \* \*\*Item:\*\* This column specifies the exact part of your app to which the vulnerability applies, such as a particular data type or an app setting. \* \*\*Severity:\*\* This shows the security dashboard’s assessment of the vulnerability’s importance, rating each as low, medium, or high. This rating helps prioritize which vulnerabilities may require the most immediate attention. \* \*\*Affected branches:\*\* This shows the app branch(es) to which the issue applies. \* \*\*Assigned:\*\* This optional setting lets you designate a specific team member to investigate and address the issue. ### Filtering issues At the top of the issue explorer, you’ll find different filters to help you narrow down specific issues that you’d want to focus on. The following filters can be applied: \* \*\*Location:\*\* This lets you specify where in your app a category of issues occurs. For example, you can choose to show only issues related to APIs or the Database. \* \*\*Branch:\*\* This lets you filter issues by a specific branch \* \*\*Assigned:\*\* This lets you show only issues assigned to a specific user. \* \*\*Filters:\*\* This lets you assign more complex filters, such as whether or not an issue is resolved, its type, or its severity. {% hint style="warning" %} Note that changing the filters on this top row doesn’t change or resolve any issues, but only filters which are displayed in the list. {% endhint %} ### Revealing issue details Clicking on each row of the issues explorer reveals more information about that specific issue. This provides the following additional information: \*\*Actions\*\*: \* \*\*Ignore for 2 days:\*\* this lets you exclude the issue from the current scan and scans within the next two days. \* \*\*Ignore for 7 days:\*\* this lets you exclude the issue from the current scan and scans within the next week. \* \*\*Ignore forever:\*\* this lets you exclude the issue from all future scans. \* \*\*Issue description\*\*: The issue description gives you a more in-depth explanation of what exactly the issue is about, and can point you towards a recommended fix See also \[Issue details\](/help-guides/security/security-dashboard/security-tests/issue-details.md). \* \*\*History\*\*: The history tab gives you a timeframe of when the issue was first revealed, what actions have been taken on it, and when it’s been resolved or reappeared. ## Test settings ### Privacy ratings You can rate the privacy level of pages and data types to help the security dashboard identify which parts of your app—both pages and database content—should be treated as sensitive. \* Article: \[Test settings\](/help-guides/security/security-dashboard/security-tests/test-settings.md#pages) \* Article: \[Test settings\](/help-guides/security/security-dashboard/security-tests/test-settings.md#data-types) ### Configure versions The Configure Versions setting controls which branches are included in security tests. By default, only the Live and Main branches are tested. To include other branches, make sure to update this setting. Article: \[Configure versions\](#configure-versions) ## Issues The Security Dashboard highlights a variety of issues related to your app’s security. For a detailed explanation of each issue—including what it means, what triggers it, and how to resolve it—refer to the \[Issue details article\](/help-guides/security/security-dashboard/security-tests/issue-details.md). To learn which security checks are available with each Bubble plan, see the \[Security Dashboard Plan Features article\](/help-guides/security/security-dashboard/security-dashboard-plan-features.md). --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings.md). # Test settings {% hint style="info" %} \*\*Running your first test:\*\* if you are accessing the security dashboard for a specific app for the first time, you may need to run an initial test before you have access to all settings. {% endhint %} The security dashboard allows you to specify which parts of your app you want to focus on. The settings are divided into three fundamental components in Bubble: branches\[^1\], pages\[^2\], and \[data types\](#user-content-fn-3)\[^3\]. ## Accessing security dashboard test settings To access the settings, click the gear icon in the upper right corner of the security dashboard. ![](https://manual.bubble.io/files/duWgqkahG1lg5kaNmLvZ) \## Test settings {% hint style="info" %} Settings applied in the \*Test settings\* popup also apply to automated tests. {% endhint %} ### Selected branches If you work across multiple branches\[^1\], you can choose which branch or branches the tests should run on. Running a security test on just one branch helps you focus on the version of your app that actually matters right now—typically the branch that’s about to be merged or released. It reduces noise from in-progress work on other branches, makes results easier to interpret, and saves time and resources by scanning only branch or branches that are relevant for your next deployment. ![](https://manual.bubble.io/files/5W3FspXyklPBlBqIFg9x) In the example above, the security test will only run on the main branch, and not on Live. To add or remove a branch, simply check or uncheck the box next to its name. ### Selected pages and data types You can also select which page(s) and data type(s) are included in the test. If a page or data type is intentionally public, or doesn’t handle sensitive data, you can exclude it from the scan. This keeps the results meaningful, reduces false positives, and helps you concentrate on the areas that truly require protection. #### Pages To decide whether a page should be included in a security check, it helps to think in terms of public and private pages. Public pages—like a home page, a password-reset page, or a 404 page—are meant to be accessible without logging in, so scanning them for restricted access isn’t usually necessary. Private pages, such as dashboards or any area that requires a login, should not be accessible to anyone who isn’t authorized. These are the pages that benefit most from security testing. ![](https://manual.bubble.io/files/bjHfetciwkqD5nNW8JpW) In this example, only the private pages will be checked. Bubble’s AI has determined that the index, reset\_pw, and 404 pages don’t need to be included, but you can override this by checking additional boxes if needed. To keep scans efficient and reduce false positives, you can uncheck pages that are intentionally public. #### Data types To decide which data types to include in a security check, consider whether they store information that should remain private or restricted. Data types containing sensitive or user-specific information—such as profiles, orders, messages, or internal records—should be treated as private. These are the types that benefit most from permission checks and secure privacy rules. Some data types, however, are meant to be publicly accessible. For example, items displayed on a public landing page—such as blog posts, product listings, or marketing content—may not require strict privacy rules if they’re intended for anyone to view. To keep your scan focused and avoid unnecessary warnings, you can exclude data types that are intentionally public. This helps the test concentrate on the data that truly requires protection. \[^1\]: A branch is a separate copy of your app’s development version that you can use to build, test, or experiment without affecting the main development workflow. It lets you work safely in parallel and merge changes back when you’re ready. Article series: \[Version control\](/help-guides/maintaining-an-application/version-control.md) \[^2\]: To read more about page security, see our dedicated article on the subject below:\\ \\ Article: \[Page security\](/help-guides/security/page-security.md) Article: \[The page element\](/help-guides/design/elements/web-app/the-page.md) \[^3\]: To read more about database security, see our dedicated article on the subject below:\\ \\ Article: \[Database security\](/help-guides/data/the-database/protecting-data-with-privacy-rules.md)\\ Article: \[The database\](/help-guides/data/the-database.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq.md). # Publishing FAQ ## iOS (Apple App Store) FAQ How do I get started with submitting my Bubble Mobile app to the App Store? Start by reading the\[ Bubble Mobile documentation\](broken://pages/a15eAr6NLeD4KM3Gyx9j). You’ll need an active Apple Developer account and to upload the required certificate and provisioning files through the Bubble interface. Bubble handles the rest of the build process for you. How do I generate the certificates required for iOS submission? Use your Apple Developer account to generate the .p8 key. Follow Bubble's documentation to upload them correctly. How long does it take to publish to the App Store once everything is set up? Once your files are uploaded and settings are configured, it can take about 45 minutes to generate the build, upload it to TestFlight, and submit it for review. Can I update my iOS app without resubmitting it to the App Store every time? Yes. If you're only changing content inside your Bubble app (text, workflows, UI), those updates happen instantly and don’t require a rebuild. You only need to resubmit if you're changing the native shell—such as the app icon, splash screen, or plugins. What are common issues users face when submitting to iOS? Several users have run into challenges during their iOS submission process. Here are the most common ones: #### App metadata errors: Apple has strict requirements for what needs to be included in your App Store listing. Users have encountered rejections due to: \* Missing or improperly sized screenshots. \* Incomplete descriptions or keywords. \* Mismatched app names or bundle identifiers. \* Choosing an incorrect app category or age rating. #### Certificate and key setup confusion: While Bubble streamlines most of the native build process, you still need to manually generate and upload: \* A \`.p8\` key from Apple (App Store Connect API key). \* Associated App ID and bundle identifier. \* Apple Developer Team ID. Users often get stuck if any of these values are incorrect or missing during the setup. #### Misunderstanding the Update Process: It's common to assume that any change to your Bubble app requires a new app submission. However: \* \*\*Web-based changes\*\* (like UI edits or logic updates inside Bubble) do not require resubmission. \* \*\*Native changes\*\* (like splash screen, icons, or plugin settings) do require generating a new build and re-submitting through App Store Connect. #### Waiting for Apple Review: After submission, there is often a 1–3 day waiting period for Apple to approve your app (or longer if it’s your first submission). Users sometimes mistake this delay for a technical issue. #### Unexpected Rejections: Apple may reject your app for reasons that aren’t clearly explained. Common rejection reasons include: #### Privacy policy issues. \* Unsupported content. \* Incomplete functionality (e.g., submitting a shell without full content). \*\*\* ## Android (Google Play Store) FAQ Is Android publishing supported by Bubble Mobile? Yes, you can publish directly to the Google Play Store. Bubble handles the build generation and provides an AAB (Android App Bundle) file that you can upload to Google Play. Can I submit to other Android stores (like the Amazon Appstore)? Not officially. Right now, Bubble only supports publishing to the Google Play Store. What steps are involved in submitting to Google Play? 1. Set up a\[ Google Play Developer account\](https://play.google.com/console/about/). 2. Use Bubble to generate the Android build and download the \`.aab\` file. 3. Upload your build to the Google Play Console. 4. Complete the store listing (title, description, screenshots, privacy policy, etc.). 5. Submit for review. Do I need to resubmit the Android app for every Bubble change? No. Just like iOS, if your updates are within the Bubble editor (like text, logic, or layout changes), you don’t need to rebuild. Only changes to the native build require a new submission. What are common issues users face when submitting to Google Play? While Android submissions tend to be more forgiving than iOS, there are still several common pitfalls Bubble users have run into: #### Incorrect Keystore Setup: When generating the app build in Bubble, you need to download and securely store your keystore file. Common issues include: \* Misplacing the keystore or password (you can't update the app without it). \* Uploading a build signed with a different keystore (Google will reject it). \* Confusion around which signing method to choose (Bubble signs it, but you may opt into Google Play App Signing). \* Java is not installed #### Store Listing Rejections: Google requires a full store listing before publishing, and apps can be rejected or delayed if anything is missing or unclear. Frequent issues include: \* No privacy policy listed (especially for apps with data input or login). \* Missing or inappropriate screenshots. \* Generic or incomplete app descriptions. #### Permissions Disclosure Problems: If your app uses sensitive permissions (like location, camera, or file access), Google Play requires clear justification and explanation in the store listing. Apps without this are often rejected. #### Policy Violations: Google has strict policies around content, ads, and functionality. Users have run into issues where: \* Placeholder content or "coming soon" pages trigger rejection. \* Your app links to websites that aren't mobile-friendly or that violate Google’s policies. \* Apps require login but don’t offer a test account for reviewers. #### APK vs AAB Confusion: Bubble exports your app as an AAB (Android App Bundle) — the current required format for Google Play. Some users mistakenly expect an APK and run into trouble trying to upload it. Misunderstanding the Update Process: \* Like with iOS, many assume any Bubble change means a new app submission. In reality: \* Web-based changes inside Bubble (design, workflows, content) update instantly without needing a new app build. \* Native build changes (icons, splash screen, plugin updates) do require generating a new build and uploading to Google Play again. \## Common Publishing Setup Errors Developer account setup To publish your app to the Apple App Store or Google Play Store, you need to set up developer accounts outside of Bubble: \*\*Apple App Store\*\*\\ Enroll in the Apple Developer Program. This requires identity verification and an annual membership fee.\\ Ensure that your Apple account has the appropriate permissions—\*Administrator\* or \*Account Holder\*—as this may be required for key-based authentication to work correctly. \*\*Google Play Store\*\*\\ Create a Google Play Console account. You'll use this to manage your app’s presence on the Play Store. \*\*Permissions and access tips\*\* \* Double-check that your \*\*Key ID\*\* and \*\*Private Key\*\* are connected to the correct Apple account and have the right permissions. \* \*Note\*: Using a key tied to a user with only developer permissions (instead of admin) can cause build issues Common configuration issues in the Bubble editor Even small formatting issues in your mobile settings can cause build failures. Here are some of the most common ones to check: \* \*\*App Scheme\*\*\\ Make sure the App Scheme is defined and doesn’t end with \`://\`. This value should be lowercase and alphanumeric (plus hyphens and periods if needed). \* \*\*Whitespace issues\*\*\\ Extra spaces in your app’s mobile settings can lead to build errors. Double-check all fields for trailing or unintended spaces. \* \*\*Keystore alias (Android)\*\*\\ This must be written in all lowercase letters. \* \*\*Bundle ID\*\*\\ Your Bundle ID must follow reverse domain format: \`com.yourcompany.yourappname\`. \* \*\*Device-specific settings\*\*\\ Ensure all required fields for iOS and Android builds are properly filled out—especially any that relate to native permissions or identifiers. \* \*\*iOS Private Key\*\*\\ When pasting your private key into the editor, include the full key contents, including the headers and footers.\\ \\ For example: \`\`\` -----BEGIN PRIVATE KEY----- \[key content\] -----END PRIVATE KEY----- \`\`\` External issues outside Bubble Some issues may relate to your external configuration or app history: \* You're attempting to deploy to an \*\*existing app\*\* on the App Store that previously included support for iPads or used a custom wrapper. \* You've \*\*deleted a required distribution certificate or key\*\* from your Apple Developer account. If so, a new certificate will need to be created and uploaded in the Bubble editor. \--- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app.md). # Native mobile app ## Getting Started with Mobile App Publishing Publishing a native mobile app is a bit different than publishing a web app. Deploying a web app through Bubble means clicking the Deploy button, while releasing a native mobile app requires additional steps involving third-party platforms: the Apple App Store and Google Play Store. Each store has its own setup processes, requirements, and guidelines that must be fulfilled independently of Bubble. This guide covers each step you'll need to follow to successfully publish your native mobile app, including understanding essential terminology and navigating the approval processes for both the Apple App Store and Google Play Store. ## Overview of the publishing process Turning your Bubble app into a native mobile experience involves several key steps, from building your app with Mobile views, to the initial setup for the App Store and Google Play Store, testing and finally submitting for approval. To begin, we will get familiar with the differences between distributing on the web vs mobile, and how mobile publishing works step by step. You will be going back and forth between your app, and your store(s) of choice throughout this process, so keep your tabs organized as you begin. First, with Mobile development, it’s important to recognize that \*publishing\* is \*\*different\*\* from deploying. Publishing your app involves several steps: 1. Preparing necessary assets like icons, descriptions, screenshots, privacy policy, etc. 2. Configuring your Bubble app for mobile deployment 3. Registering developer accounts with Apple and or Google 4. Deploying to the app stores 5. Testing your build 6. Submitting your app for review 7. Publishing and making it available for users ## Understanding deployment for Mobile Deploying and publishing are often used interchangeably, but they have distinct meanings. Traditionally, deploying in a web context means pushing updates live from your main branch, making them instantly available to users. In mobile, this concept applies less directly because updates often require a new build. A \*\*build\*\* is a packaged version of your app that is required for submission to the App Store or Google Play Store that we will learn more about soon. Over-the-Air (OTA) updates allow you to make some changes without a \*\*full\*\* app store resubmission, though most updates still require a new build file that must be published to the App Store or Google Play. In short, deployment in mobile development is preparing your app for release. True availability happens only after it’s published. ## iOS vs. Android: Key Differences in Submission and Approval When publishing a mobile app, it's important to be aware of the costs and differences between iOS and Android, especially regarding approval processes, developer accounts, and compliance requirements. ### Developer account requirements To publish an app, you must sign up for a developer account for each platform: \* \*\*Apple Developer Program:\*\* Requires an annual fee of $99 and identity verification. \* \*\*Google Play Console:\*\* Requires a one-time registration fee of $25. ### Approval process: Apple vs. Google Once signed up, and ready to submit, Apple and Google have distinct review and approval workflows: \* \*\*Apple App Store:\*\* Stricter guidelines with a manual review process, leading to longer approval times (typically 1–3 days, but may take longer if revisions are required). \* \*\*Google Play Store:\*\* Generally more lenient on design quality and content restrictions. Review includes both automated and manual steps, with approval timelines that are often similar to Apple’s. ### Key compliance requirements Both platforms enforce specific policies to ensure apps meet security and content guidelines: \* \*\*Privacy Policy\*\*: A publicly accessible page detailing how user data is collected and used. \* \*\*Permissions\*\*: Apps must justify the use of sensitive data (e.g., location, camera, contacts). \* \*\*Content Guidelines\*\*: Apps must not include misleading content, harmful functionality, or policy violations. By preparing for these requirements in advance, you can avoid common rejections, reduce delays, and ensure a smoother submission process. ## Understanding Builds, OTA Updates, and Live Versions for deployment Here’s a key glossary of concepts to understand before signing up for a developer account. Familiarizing yourself with these will give you a solid foundation in mobile development and help you navigate the publishing process when you're ready to launch your app on the app store. ### What is a Build? A build is a packaged version of your app that is required for submission to the App Store or Google Play Store. Each build is assigned a version number, following a semantic format (e.g., 1.0.0 → 1.1.0 → 1.2.1). | Version Type | Example | Purpose | Requires App Store / Play Store Resubmission? | | --- | --- | --- | --- | | Major | 1.0.0 → 2.0.0 | Significant updates, breaking changes, or major new features | Yes | | Minor | 1.0.0 → 1.1.0 | Smaller feature additions or improvements that maintain compatibility | Yes | | Patch | 1.0.0 → 1.0.1 | Bug fixes, security updates, or minor tweaks | Yes | Key facts about builds: \* Necessary for first-time app submission and for major updates. \* Each build requires App Store & Play Store approval before going live. \* Users must download a new build from the store to receive updates. ### How OTA (Over-the-Air) updates work OTA updates allow you to deliver changes to the latest live version of your app without submitting a new build to the app store. These updates function similarly to web app deployments—users will see the changes the next time they open the app. To reiterate OTA updates only are sent to the latest built version, even if that built version is not in the app store. Key facts about OTA updates: \* Instant update: Users on the latest version get the update without needing to download anything and without the developer needing to submit a new version of the app. \* Note: OTA updates, don’t have version numbers. \* Great for bug fixes and content changes that don’t require new native functionality. \* Unlimited OTA updates can be applied to the latest build. \* No resubmission needed to the App Store or Google Play. ### Differences between OTA updates and Builds | Feature | OTA Updates | Builds | | ---------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------- | | Approval Needed | Typically deploys within 5-10 minutes | Yes (App Store / Play Store) | | User Download Required | No | Yes | | Use Case | Bug fixes, content tweaks, minor UI improvements | Major updates, new features, important security updates | | Deprecation | Not automatically discontinued when multiple live versions are supported; must be deprecated manually | Older builds remain unless removed | ### What is a Live version? A live version refers to the version of your app that users are currently running on their devices. Each live version is tied to a specific build (what’s installed from the App Store, Play Store, or distributed via testing tools like TestFlight), and is connected to a version of your app’s backend (the server-side logic and data). \*\*Key things to know:\*\* \* A live version is always tied to a specific build of your app. \* OTA updates apply only to the latest built version, even if it hasn’t been submitted to the app store. \* Bubble checks if the user's app is on a supported live version on app load. \* Users on older builds will not receive OTA updates unless they update to the latest build. \* When a user installs the app for the first time, or updates to a new build that includes an OTA, the OTA is applied immediately. This can add a small amount of time to the initial load (usually around one second), but it ensures that the user’s first experience with that build is seamless and doesn’t show the update screen. \* If a user is already running a build and an OTA update becomes available, the update downloads in the background when the app is opened and is applied the next time the user re-opens the app. If the live build has been deprecated, the user will see the update screen, prompting them to apply the OTA on the next re-open. \* Bubble supports multiple live builds running simultaneously, which means users on older builds can continue using your app without breaking — but you’ll need to manually manage and deprecate older versions over time. #### Managing version support & deprecation Supporting multiple versions ensures a smooth user experience, as not all users update their apps immediately. #### Why support multiple builds? Supporting multiple builds ensures a smoother experience for your users — especially since not everyone updates their app right away. Bubble allows multiple live builds to run in parallel, giving you more flexibility and control over how and when users receive updates. \* Users don’t update immediately: some users may stay on older builds for weeks (or longer), so it’s important that those builds continue to work correctly. \* Testing before release: you may want to roll out and test a new build (via TestFlight or internal testing) before making it widely available in the App Store or Play Store. \* OTA updates are build-specific: OTA updates only apply to the latest built version. If a user is on an older build, they won’t receive the update—so keeping older builds functional is essential. \* Smoother user experience: requiring users to download a new version for every update can cause friction. Supporting multiple builds lets you avoid that for minor updates or bug fixes.\\ App store delays: since store reviews can take time, keeping older builds live ensures your app remains usable while newer builds wait for approval. Deprecation tip: While Bubble supports multiple live builds, older versions are not deprecated automatically. You’ll need to manually deprecate any versions you no longer want users to access. #### Bubble’s Live version limits Bubble limits the number of concurrent live versions you can support, meaning you must manage updates carefully. #### Best practices for deprecating old builds \* Encourage updates: Use in-app messaging or push notifications to inform users of new builds. \* Gradually phase out older versions rather than forcing instant updates. By understanding builds, OTA updates, and live version management, you can maintain a smooth deployment process and keep your app updated efficiently. Now that you have a better understanding around Mobile publishing and deployment, it’s time to learn how to publish step by step to iOS and Android. ## Operating system compatibility Our current version of React Native will support: \* iOS devices running version 15.1 and later \* Android devices running version 12 and later. Devices running unsupported OS versions are not guaranteed to work as expected. Please be aware that certain native features may only be supported by later OS versions as well. The oldest supported version will be noted per feature in the documentation. As we stay up to date with the latest versions, these versions are bound to change. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection.md). # Infinite recursion protection Infinite Recursion Protection helps prevent runaway recursive workflows from causing large, accidental spikes in workload or CPU consumption.\\ \\ This feature allows you to set an app-level limit on workflow “depth”, which is the number of times workflows schedule themselves (direct recursion) or another workflow (indirect recursion) consecutively. Any workflow that is scheduled beyond the maximum depth you set will be terminated automatically. While workflow-level constraints on scheduling remain the primary method for managing recursion, this feature creates a backstop for the entire app. ## How it works You can now set a maximum depth for your entire app. If any workflow exceeds this limit, it will automatically stop. When a workflow is terminated it's captured in the server logs under Workflow errors and an automated email notification is sent to the app admins. Note that we limit these notifications to once per day, so there may be additional terminations occurring. To check, you can review the Workflow errors in your server logs. \*\*Getting started:\*\* 1. Find the feature in the \*\*API subtab\*\* under \*\*Settings.\*\* 2. If you're not using recursive workflows, we recommend starting with the default limit of 10. 3. If you are using recursive workflows, set a limit that accommodates your longest intentional recursive chain. \*\*As of July 1, 2024\*\*, all new Bubble apps will have this feature enabled with a default limit of 10. Apps created before July 1 won't have any limit applied automatically, but you can enable it any time. ![](https://manual.bubble.io/files/WCrA0A0E8KlwVi8Ezz4o) To cover this more in-depth, we’ll introduce a few new phrases: ## Terminology ### Recursive workflows Recursive workflows in Bubble involve one or more API workflows scheduling themselves to run again, typically over a list of database items. There are two types of recursive workflows: \* Direct recursive workflow: An API workflow that runs through a list of actions, and then schedules itself at the end \* Indirect recursive workflow: A set of two or more API workflows that schedule each other in a circular fashion Either type of recursive workflow has the potential to lead to a scenario where a misconfigured constraint or scheduling logic results in the workflow chain running indefinitely. They require carefully set conditions to avoid creating infinite recursions. Mitigating the impact of unintentionally ending up in this scenario is what infinite recursion protection is for. ### Workflow Chain A workflow chain refers to the entire sequence of workflows triggered by a common root workflow or any part within it. It can be a straight line of workflows (like a single API workflow that schedules itself), but doesn’t have to be: at any point, a workflow can trigger multiple other workflows, forming a workflow chain that includes all of them. This can include simple chains with just a few processes or more complex ones, like the examples shown in the diagram. ### Depth Depth represents the total number of workflows in the direct scheduling sequence from a given workflow back to the root workflow. In a simple case of direct recursion like in our example, the maximum depth can be equal to the total number of workflows in the chain. However, in other cases a single workflow may schedule multiple other workflows, which would each be assigned the same depth. In this case, the total number of workflows in the workflow chain is not equal to the maximum depth. Think of it like family generations: your parents are one generation before you, and your grandparents are two generations before you. While you may have siblings, aunts, uncles, and cousins, they do not change your generation. The illustration below shows how works in different scenarios. ### Depth limit The depth limit refers to the total depth you allow for an individual chain of workflows to go to. Since each workflow is assigned a depth number, a depth limit enables you to instruct Bubble to stop the process at a specified number. This prevents the chain from continuing indefinitely. ## Understanding workflow depth Workflow depth applies whenever a workflow schedules other workflows, regardless of whether it's a single workflow scheduling itself repeatedly, or a collection of workflows that are being scheduled in a cascading fashion. To illustrate how this depth level is determined for workflows in your app, we can evaluate some example workflow chains below:\\ ![](https://lh7-us.googleusercontent.com/docsz/AD_4nXd5QbBA0o96An_wgnIDtjUe-CuD2eOZJ_ZNiyMgWDvl9TtjwAT16LqBF3u8xW0By3WDfYcD3Lf-vL9C9rSf4eXonJ1OcGJwnhC0daomf6-Px8I5L3xSH6WNAymLfEekZJj5PcNMp4P9g0oZeM7-V8cMGFuF?key=J0ms4LS5wIkro0Y4rlqu4A) Note that each box in the diagram represents a workflow; an arrow indicates a workflow scheduling another workflow In the example, we are assuming a depth limit of 10, resulting in the following: \* The Direct Recursion Example would result in creating 10 things before hitting the depth limit \* The Complex Direct Recursion Example would result in creating 8 things because the first iteration of the direct recursion workflow for creating things didn’t start until a depth of 3 \* The Indirect Recursion Example has two workflows that both include an action to schedule the other; this workflow chain would result in creating 5 things because a thing is only created every other level of depth (when the ‘create\\\_thing’ workflow runs) until it reaches the limit of 10 \* The Schedule API Workflow on a List Example would successfully create 1000 things; this is because all 1000 ‘create\\\_thing’ workflow runs are scheduled by the same root workflow and therefore all have the same depth of 1 ## Setting the right depth limit {% hint style="info" %} Many apps don’t use recursive workflows, and if that’s the case, you can simply leave the setting at the default of 10, as there are vanishingly few examples of non-recursive workflows getting to depths of 10 or higher. {% endhint %} If you use recursive workflows, we recommend setting a buffer above the longest expected chain. Predicting the number of times a recursive chain will run can be imprecise, but the key to protecting yourself from infinite recursion is to have some (any!) limit in place to prevent them from running infinitely. Recursive workflows are often used for bulk operations, and canceling one midway can be difficult to correct, especially with live data. Therefore, if you are unsure about what value to set, it’s safer to go higher. The tradeoff is that as the limit is increased, any accidental recursive workflow chains will be terminated later than they would have if the setting was lower. However, WU consumption from accidents will still be significantly less than it would have been otherwise, so the protection is still valuable even at a high limit. Remember, we offer different depth limit settings for development and live environments. Misconfigured recursive workflows often occur during testing, and restoring a test database after an early cancellation is generally easier in the Development environment. Let’s have a look at a few different scenarios, and how you can approach setting a depth limit for each one: ## Examples: ### Scenario 1: Your longest recursive workflow schedules itself iteratively until it has processed all items on a list. In this case, depth is equal to the number of items on the list because there is one workflow run for every item. Therefore, the maximum depth in this setting should be greater than the longest list that you expect it to process. #### Example: Your longest recursive chain is a recursive workflow that iterates over a list of things and processes each item, where the list is typically around 500 things; we would recommend setting the limit at 1,000 or higher. ### Scenario 2: You build a pair of API workflows in a modular way in order to accomplish different aspects of an operation. To implement the full operation over a list, you’ve configured your workflows to schedule each other in a circular pattern as they iterate through the list. Because there would be two workflow runs for each item on the list, if this was your longest chain then you’d configure your depth setting based on 2x the longest list that you expect it to process. #### Example: Let's say the list of things to process with this pair of circular workflows is around 500. Since there are two workflow runs per item, the typical depth is around 1,000. In this case, we would recommend you set the limit at 5,000 or higher. \--- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/data/images.md). # Images When you upload an image, Bubble does not modify the original file. This means no resizing, compressing, or altering takes place during the upload process. The original file is stored exactly as it was uploaded. However, Bubble automatically generates optimized copies of the uploaded file for performance reasons. They are generated at run-time and cached. ## Image caching While Bubble doesn’t natively support image modification, it offers a \[CDN transformation layer\](#user-content-fn-1)\[^1\] for rendering images dynamically in your app. This transformation is used specifically for images displayed inside image elements or backgrounds\[^2\] under the following conditions: 1. \*\*Public images:\*\* The image is not attached\[^3\] to any private Bubble “thing.” 2. \*\*Bubble storage:\*\* The image is stored within Bubble’s file storage system. 3. \*\*File type:\*\* \[SVG files\](#user-content-fn-4)\[^4\] are not compressed\[^5\]. SVGs are vector-based, which means they are inherently scalable without quality loss When displaying an image, Bubble’s run-mode engine determines the optimal size and compression needed based on the container or device resolution. It uses the transformation layer to create a temporary resized or compressed copy of the original image. Each time the image is rendered in a new context—whether in a differently sized container or on a device with a different resolution—a new copy is generated on the fly. For example: \* Displaying the same image in a small icon versus a full-width banner will create two differently resized versions. \* High-resolution devices may trigger higher-quality copies compared to standard-resolution devices. These transformations ensure efficient loading and optimal display quality across various devices and layouts. Copies generated through the transformation layer are stored temporarily in Bubble’s caching system for up to 30 days. This caching applies even if the original image is deleted during this period, meaning the transformed versions can still be accessed for up to 30 days after deletion. Cached image copies do not count toward your storage limit because they are managed within Bubble’s performance infrastructure. If a cached version is unavailable, Bubble automatically generates a new resized copy from the original file to ensure the image is always displayed correctly. **Advanced:** how Bubble determines image sizes for caching and rendering \*\*Resizing\*\* When an image is displayed in a responsive layout, its size is often proportional to its parent container. This results in a variety of sizes across devices, with widths ranging continuously, for example, from 150px to 2000px. To manage this variability, Bubble uses a systematic approach to limit the number of image copies generated. The system rounds each size up to the nearest value in a predefined sequence of widths: \* 128px \* 192px \* 256px \* 384px \* 512px \* 768px \* 1024px \* 1536px \* 2048px \* 3072px This sequence ensures no more than approximately 10 resized copies of an image are stored, striking a balance between performance and storage efficiency. \*\*Rendering\*\* When rendering an image, Bubble determines the closest size in this sequence that is slightly larger than the container dimensions. For example, in a Full HD viewport (1920px width), if the image container is sized at 768x512 pixels, the system rounds up to the next size in the sequence: 1024px width. Bubble then scales the container dimensions proportionally, requesting an image at 1024x683 pixels. To ensure a proper fit, Bubble’s engine retrieves the “max fit” version of the image, which is the largest size that fits within the specified dimensions. In this case, the final image served might be slightly adjusted, such as 1024x585 pixels, preserving aspect ratio and ensuring optimal display quality. This process minimizes unnecessary resizing operations while delivering the best visual results for the user’s specific device and layout. This method of resizing and caching is key to Bubble's performance infrastructure, enabling efficient image handling without compromising on quality \### Should I compress images before uploading? Compressing and resizing images before uploading is generally unnecessary for performance reasons, as Bubble automatically optimizes images for display through its CDN caching and transformation process. However, if conserving storage space is a priority, resizing and compressing images to the size they’ll most frequently be displayed at can be beneficial. When doing so, ensure that the images are large enough to accommodate screens larger than your own. For example, if you’re using a full HD monitor to test a background image, a higher-resolution image may be necessary to maintain quality for users with 4K monitors. For apps where image quality is crucial, we recommend uploading images at the maximum resolution they will be viewed. This ensures the best possible experience for all users, regardless of their device’s screen size. ### What about user-uploaded images? When users upload an image, you may lose control over the initial file size, potentially leading to larger storage consumption than intended. Since Bubble does not include native image processing features, you may need to address this in one of two ways: #### Set a Maximum File Size You can configure the picture uploader element to enforce a maximum file size. This ensures users reduce their file size before uploading, helping you maintain control over storage limits. #### Use a Plugin Plugins can provide features like image compression before uploading. For the best results, choose plugins that store the compressed image in Bubble’s file storage. This allows the image to benefit from Bubble’s caching and transformation process, as described earlier, ensuring optimal performance and flexibility. ### Is compression and resizing applied when using the file uploader element? Yes, compression and resizing are applied when the image is first loaded, rather than during upload. This means the optimization process also applies to images uploaded through the file uploader element. The same rules \[described above\](#image-caching) apply to files uploaded this way. Since the file uploader supports a wider range of file formats, some files may not be optimized, such as SVGs and animated GIFs. Additionally, HEIC and HEIF (Apple formats) are not officially supported. ## Images uploaded via plugins Images uploaded through a plugin follow the same behavior as other uploads, as long as they are stored in Bubble’s file storage. However, if a plugin stores the image in an external storage service, the caching and transformation process will not occur. Bypassing the CDN transformation layer If you want to bypass the automatic optimization of images in your app, you can append the following parameter to the image URL: \`?ignore\_imgix=true\` This advanced feature disables Bubble’s image optimization for that specific image. Use this feature with caution, as it may impact performance and loading times. If you’re unsure about its purpose, it’s best to avoid using it. \[^1\]: A CDN transformation layer dynamically adjusts images for optimal display by resizing or compressing them based on the user’s device or container size. This ensures faster load times and reduced bandwidth usage without altering the original image file. \[^2\]: When used as background in an element, such as setting an image as a background in a group element. \[^3\]: When a file is “attached” to a thing, it means the file is protected by the privacy rules applied to that thing. As a result, the file will be inaccessible to users who do not meet the conditions defined by those rules. For more details on file security, refer to the article section below:\\ \\ Article section: \[Uploading private files\](/help-guides/data/files.md#uploading-private-files) \[^4\]: SVG files are Scalable Vector Graphics, a file format for two-dimensional images. Unlike raster images, they use XML-based code to define shapes and paths, allowing them to scale without losing quality. \[^5\]: Keep in mind that while SVG files \*can\* be compressed, Bubble’s CDN does not provide this functionality. To minimize file size, consider compressing your SVG files before uploading them. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/data/images.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/security/security-dashboard/overview.md). # Overview The security dashboard offers a comprehensive suite of tools to audit and monitor your app. In this article, we’ll go over the available features, and link to more in-depth content for each section. ## Security The security dashboard equips you with two different tools for performing tests on demand. ### Issues explorer The Issues explorer runs a test across a range of different categories and ranks them by criticality. Each of the categories are explained in-depth in the sub-articles in this series. Article: \[The issues explorer\](/help-guides/security/security-dashboard/security-tests/issue-explorer.md) ## Privacy rules checker The privacy rules checker quickly shows which of your data types are publicly accessible. Article: \[The privacy rules checker\](/help-guides/security/security-dashboard/security-tests/privacy-rules-checker.md) ## Automated tests Automated tests enable you to run security tests automatically. Article: \[Automated tests\](/help-guides/security/security-dashboard/security-tests/automated-tests.md) ## Resources ### Scheduled deployments Bubble allows you to schedule deployments in advance, so your app is deployed automatically at a specific date and time. This is useful for coordinating releases or planning updates outside of working hours. {% hint style="warning" %} \*\*Bubble deployments and issue checker:\*\* Scheduled deployments will proceed even if there are unresolved issues in the editor. This means it's important to review and fix any issues before scheduling a deployment, as they won't block the process or trigger a warning automatically. {% endhint %} ### Alerting The \*\*alerting\*\* feature allows you to notify collaborators when key events occur in your app. You can send alerts via email or trigger a custom webhook when your app is deployed to the live environment Use this feature to keep your team informed during deployment or when working across multiple . --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/security/security-dashboard/overview.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/workload/understanding-workload/the-workload-calculation.md). # The workload calculation In the last article, we looked at the activity types that are part of the workload calculation. In this article, we'll look closer at how the actual calculation happens. ## The entrance ticket metaphor To get an understanding of why the values in the table don't necessarily represent what you see in the final logs, we'll use the theme park metaphor. Imagine the workload table values as entrance tickets to a theme park. While the ticket gets you into the park, each ride inside might have its own additional cost, which can vary depending on the details and specifics of that activity. Just as some roller coasters might have a higher fee due to their popularity or thrill factor, certain operations in your Bubble app can be more resource-intensive based on how they're executed. In other words, the value in the table represents the \*starting\* cost of an operation – but the complexity of that operation determines the final value. ## Examples Having established that metaphor, let's have a look at some examples to further illustrate the point: ### Each item written to or modified in the database This item in the table is easy to understand: for each item that you write to in the database (For example using the \[\*Make changes to a thing\*\](#user-content-fn-1)\[^1\] action), a cost of 0.5 workload units is incurred. Now, let's return to the theme park metaphor: 0.5 is the price of the entrance ticket to the theme park called \*Make changes to a thing\*. Within that theme park, we may still have to pay for the rides inside. Let's imagine that we are storing some statistical information in the database. We want to count all the registered users in our app, and save them on a data type called \*Statistic.\* ![](https://manual.bubble.io/files/SL0gFvQE4J5JW55WhXUM) We've already paid our 0.5 for the entrance ticket (starting the \*Make changes to a thing\* action), now let's see what rides in the theme park we have to pay for. In the example above, we're asking the server to do three things: 1. Search for a \*Statistic\* thing and return the first result 2. Search for the \*User\* thing and return the count 3. Make changes to the field \*Number of users,\* using the result of step 2 So while our ticket allows us to enter the park, at the end of the day we can also look back at having paid for three different rides with varying costs. This is why, as we mentioned in the opening of this article, it's important to understand the \*total\* server load rather than just the cost of starting a process. In the above example, you are not asking the server to do \*one\* thing, but three. The final load on the server also depends on the number of \*Users\* and \*Statistics\* in the database, and how much data they contain. ### Performing an aggregate query in the database This point too is pretty easy to read: to \*perform an aggregate query\* means to take a list of data and make an aggregation such as a \*count\* or calculating an \*average\*. This is listed with a cost (entry ticket) of 0.2, but again we need to take every detail of the operation into account. Starting the aggregation calculation has a cost of 0.2, but the data to be aggregated needs to come from a \[data source\](#user-content-fn-2)\[^2\]. In many cases, this will be the result of a dynamic expression using the \[\*Do a search for\*\](#user-content-fn-3)\[^3\] data source. What this means, is that \*this\* operation needs to be added to the total calculation. According to the activity type chart, a database search has a starting cost of 0.3. The complexity\[^4\] of that search can add to the cost of it. Returning data from the database also has a cost of 0.000003 per character of data transmitted. Since we are returning a number in this case, that cost would be very low, but still a part of the full picture. Let's sum up what we are adding to workload in this example: \* A \*Do a search\* for query (cost: 0.3 per operation) \* An \*aggregation\* of the results of that data (cost 0.2 per operation) \* Sending the data to the user's device (cost 0.000003 per character) Again, it's important to understand that the \*total\* cost can increase, depending on the complexity of an operation. If the \*Do a search for\* includes advanced filters performed server-side, then that will be calculated into the total. Again, it may seem like we are performing one action, but technically, Bubble's server is performing the three listed above. ## How to think about the total Workload is a calculation of the total work the server has to do to power your app. Our goal in sharing these examples is to give you basic understanding of how workload is calculated behind the scenes and help you see activity types as the building blocks for more complex operations in your app. Because Bubble is so flexible, there’s also usually more than one way to achieve a certain outcome - and those different ways could be implemented invoking different basic activity types that can result in different workload calculation. With this information in mind as you plan and build your app, you can take into account how different activity types are combined inside of a single action or expression to make up a total. For example, knowing that an complex search as part of an action is a fairly heavy database operation, you can take steps to find alternative solutions that consume less workload while retaining the same functionality. ## Backend versus front-end and workload Workload is all about \*server\* work; in other words, things happening client-side don't cost workload at all, unless it involves some work from the server. Let's illustrate with an example: #### Example 1: Setting a custom state containing text Custom states are saved on the user's device, and as such do not involve the server. Thus, the action to set a custom state in itself does not incur any WU. Let's say you want to set a custom state of type \*text\* and assign it the value "Example". In this case, the workload consumption would be 0. #### Example 2: Setting a custom state containing data from the database In our second example, we want to use a custom state with a custom data type that we need to fetch from the database. In this case, the \*Set state of a custom element\* action would still be free, but searching for the data would incur a cost, in two steps: \* Using \*Do a search for\* incurs a starting price (the "entry ticket") \* The complexity of the search and volume of data returned is calculated into the total \* The data returned from the server incurs a cost per character returned As we can see in this example, since the client-side action (setting the custom state) requires an additional server-side action (searching for and returning data), it will incur a small WU cost. #### Example 3: Using the Go to page action to navigate within the same page The \*Go to page\* can be used to assign URL parameters to the URL and navigate a single-page application. As long as you are staying on the same page and not loading a different page, this too is a purely client-side action and does not incur any WU consumption. (keep in mind that workflows that execute on page load might still be repeated and consume WU. We cover this in-depth in the article below). Article: \[Page load and workload\](/help-guides/workload/optimizing-workload/optimization-checklist/page-load.md) #### Example 4: Using the Go to page action to change the \*Page thing\* In this example, we're using the \*Go to page\* action to change the Page thing. In this case, even though we are still on the same page, Bubble will need to fetch the data for the new Page thing and spend some WU on it. How much depends on how you instruct Bubble to find the data. For example, if you use \*Do a search for\* you may be consuming a bit more WU than if you reference it directly, such as \*Current user's Active project.\* #### Example 5: Using the Go to page action to navigate to a different page If you are using the \*Go to page\* action to navigate to a different page, you're again asking the server for some information: \* Loading the page itself (generating the code and sending it to the browser) \* Loading the data needed for the page (searches, repeating groups, aggregated numbers and other dynamic expressions) \* Running workflows set to execute on page load Again, page load is covered more in-depth in the article below: Article: \[Page load and workload\](/help-guides/workload/optimizing-workload/optimization-checklist/page-load.md) \[^1\]: The \*Make changes to a thing\* action is used to write in the database on an existing thing (record). Article: \[Creating, saving and deleting data\](/help-guides/data/the-database/creating-saving-and-deleting-data.md) Reference: \[Make changes to a thing\](https://manual.bubble.io/help-guides/workload/understanding-workload/pages/-MTujs88N9W-2FUmQGag#make-changes-to-thing...) \[^2\]: A \*data source\* is any source from which Bubble can fetch data, such as the current user, a database search or the response to an API call. Article series: \[Dynamic expressions\](/help-guides/logic/dynamic-expressions.md) \[^3\]: \*Do a search for\* is a data source that performs a database search with specific constraints and sorting\*.\* It returns a list of things from the database. Article: \[Finding data\](/help-guides/data/the-database/finding-data.md) \[^4\]: \*Complexity\* in this context refers to adding the \*:filtered\* operator to the search. This can sometimes force Bubble to perform additional tasks on a search, leading to an a separately calculated WU cost. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/workload/understanding-workload/the-workload-calculation.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/visual-native-app-elements.md). # Visual elements ### WebView The Web View element allows you to display one of your app’s pages inside an element within your mobile app. You can set its responsive behavior just like any other element, ensuring it adapts well to different screen sizes. ![](https://manual.bubble.io/files/OGFnDgz3OlP2qU63cvkU) Keep in mind that users won’t be able to navigate to other pages while using the Web View, so it’s important to design the page with all necessary content on a single page. The Web View element is limited to displaying pages from your own app, meaning external URLs cannot be used. {% hint style="warning" %} The Web View element currently does not work in the web preview— it only functions properly in the BubbleGo app. {% endhint %} #### Disable zoom The \*Disable Zooming\* property in the Webview and Scrollable View elements prevents users from using the pinch-to-zoom gesture to zoom in or out. This setting is enabled by default. ![](https://manual.bubble.io/files/WJt6v70TeSujAJUKMpdg) It helps improve the user experience, particularly for apps that rely heavily on webviews, where unintended zooming can cause a disruptive interface. If you want to allow zooming, you can disable this setting in the element's properties. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/visual-native-app-elements.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/building-responsive-pages.md). # Building Responsive Pages (Legacy) Bubble pages are responsive. In other words, they will adjust to the width of the page so that they look great on mobile devices. Since you can position elements to the pixel, you may have to configure a few settings for your page to behave properly as its width changes. ## Building responsive pages You should start designing the page as it should appear on a wide screen, for instance your laptop. Then, once you're done with the wide ("laptop") design, you can start working on narrower designs. That's what the Responsive Viewer is for. The responsive view lets you modify a few parameters that will change how the page behaves when it's being squeezed. !\[\](https://gblobscdn.gitbook.com/assets%2F-M5sbzwG7CljeZdkntrL%2F-M5smrJkMfjcu6xQRWw4%2F-M5smuTUA0PIEfTN1LjL%2FResponsive.gif?alt=media) ## Using the Responsive Viewer You will find a tab above the New Element palette that lets you switch between the Builder View, where you can modify elements, drag new ones, and delete some, and the Responsive Viewer which lets you test your page under different configurations and modify the responsive behavior of each element. In this view, the ruler at the top of the page area defines the current page width. Just click or drag on the ruler to resize the page and see how the page behaves dynamically. You can also use the preset width icons on the left side of the screen to see how the page looks on iPhone in portrait mode, in landscape mode, on an iPad and on a laptop or a desktop. When you click on an element, the Responsive Palette will display the different parameters you can modify to affect its behavior. Modify the different settings and you’ll see how it impacts the page in real time. ## Understanding the Responsive Algorithm The algorithm that controls how the page is rendered follows a few core principles. While you can tweak and see in real time the impact of the responsive parameters, it is good to have an overall understanding of how the rendering engine works. 1. In general, as the page gets resized, elements shrink and expand before margins do. Bubble only expands margins if all elements on a line are at their maximum widths, and only shrinks margins if all elements are at their minimum widths and everything that could break to the next line is already on the next line. 2. By default, most elements are shrinkable and expandable. You can control this on an element-by-element basis in the Property Editor or the Responsive Viewer. 3. Overlapping elements move together: they expand or shrink together (unless one of the elements is set to fixed width or has a maximum width). In other words, overlapping elements both break, or neither breaks, and they are both shown or neither is shown by any show/hide rules. 4. Groups (and other containers, such as Repeating Groups) work like mini-pages. Elements can break to new lines inside of them. By setting a minimum width on a group, you can stop that from happening by limiting how far the group can squeeze its contents. And by setting a maximum width, you’ll limit how wide an element can be. For instance, if you want your page to not be as wide as the screen, you can put all your elements in a group and apply a maximum width for that group. ## Using the Responsive Debugger Bubble offers a responsive debugger, both in Run-mode (if the debugger is on) and in the Responsive Viewer (click on the grid icon in the Top Bar). Activating that mode will let you see how the page is structured, and how the elements on the page are grouped together. For example, this can reveal floating groups that hover over elements and make them unexpectedly unclickable, or why elements have more space than expected between them. To activate this in run mode, when the debugger is on, click "Show responsive boxes" under the "Inspect" button. This is important because behind the scenes, a Bubble responsive page is structured into lines and boxes, and these two concepts will help to refine the responsive behavior of your page. \* Elements get grouped into boxes. Everything in a box moves together (for instance, overlapping elements are always in the same box). Boxes are the things that can break to the next line, and get shown and hidden. The left-most element in a box is the one that controls its show / hide rules (see below for what these rules are about). \* Lines are horizontal rows of boxes. Lines are as tall as the tallest thing in them, and everything in the next line is below the line above it. Boxes can break to a new line if there's no space for them on their current line. !\[\](https://dd7tel2830j4w.cloudfront.net/f1460753235049x912985536735504900/Screen\_Shot\_2016\_04\_15\_at\_4.46.51\_PM.png?) ## Responsive parameters [](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/building-responsive-pages.md#responsive-parameters) You can tweak how an element/page behaves as the page is resized with the responsive parameters. They are accessible from the Property Editor and the Responsive Palette (when you’re in the Responsive Viewer). Understanding responsive settings is easier when you see the actual impact of the different settings. We strongly recommend watching this \[17-minute video\](https://vimeo.com/169882386), as it will illustrate the different options you can use as you build responsive page. ## Other {% hint style="warning" %} \*\*Note:\*\* Instagram technically uses its own browser, which is not officially supported by Bubble. Bubble pages will still load in Instagram's browser, but if this is a major use case for you, we recommend you test your pages on this browser first. {% endhint %} {% hint style="warning" %} \*\*Note:\*\* If you reference a third-party library in the raw Javascript on a page to modify an element, the way the modified element updates responsively (i.e. as the screen width changes) might not behave as expected, so it's always a good idea to test it thoroughly. {% endhint %} {% hint style="warning" %} \*\*Note:\*\* Elements that are wider than the width of the page it's on can lead to unexpected behavior with the responsive engine. Consider making all elements no wider than the page width. {% endhint %} --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/building-responsive-pages.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/the-component-library.md). # The Component Library The Component Library is a collection of pre-built User Interface (UI) components that can be dragged and dropped onto your page to help you build beautiful interfaces faster. These UI components are fully responsive and are made up of containers\[^1\], \[visual elements\](#user-content-fn-2)\[^2\], and \[form inputs\](#user-content-fn-3)\[^3\] that can be individually customized once added to your page. Each component is a fully independent unit, but can be connected to each other or other parts of your app by adding workflows\[^4\] and data. This guide will show you how to use these components to build a beautiful landing page in seconds and how to wire up the Signup and Login forms for full user authentication. ### Build with components The UI components in the Component Library allow you to build a fully responsive\[^5\] and customizable app in seconds. First, change your page layout to a Column container layout type in the page's \[property editor\](#user-content-fn-6)\[^6\]. This will allow your components to stack vertically when added to your page and the content to resize appropriately as the screen width changes. ![](https://manual.bubble.io/files/AxkpRS4zdLhaOJoa6gjs) Next, drag any number of components onto your page, one below the other. When dropping your component onto your page, the blue indicator on the editor canvas will tell you where it will land. {% hint style="info" %} Components can be added within other groups, so make sure the blue indicator is at the very bottom of the last container. {% endhint %} ![](https://manual.bubble.io/files/4p8NawzEBdoAJ2yqxgLs) Once you are done adding components, you will have a fully responsive landing page that can be customized to your liking. ### Customize your components Now that the skeleton of your landing page has been built, each element can be customized to your liking. For example, you can change the text in any of the text boxes or buttons by selecting the element and updating its Appearance or replace any of the placeholder images by selecting the image and uploading a new one. As you add additional pages to your application, you can update the placeholder links on your page to navigate to those pages by adding a \`Go to page\` workflow action when the link is clicked. ![](https://manual.bubble.io/files/TQpmyBclg7Gg2sauFTDB) To change the overall look and feel of your landing page, you can customize the font and color variables in the Style Variables subtab in the Styles tab. Since the font and colors used in each element is connected to a Variable, any changes made on the Style Variable level will cascade through your app automatically. Adjust the Style Variables so that your landing page matches your brand. ![](https://manual.bubble.io/files/EMWRPUl6ieFruHYcd92e) \### Adding workflows for user authentication User authentication is the foundation for almost every web application. By using the Header and Signup/Login components, you can set up a fully functionally signup and login flow in a handful of clicks. Once you've added the Header and Signup/Login components onto your page, you'll need to connect the Signup and Login buttons in the Header to show the Signup/Login popup or the Signup/Login page, depending on the component you selected. Most of the workflows have already added to help you get started. Open the \*Workflow\* tab of the page that contains the Signup/Login component, and you'll see two workflows titled \*When an element is clicked\*. The first workflow will control the Signup form and the second workflow will control the Login form. Select the first workflow event and change the element to "Button signup (Header)." This connects the Signup button to the workflow that opens the Signup Form. Similarly, in the second workflow event, change the element to "Button login (Header)" to connect the Login button to the workflow that opens the Login Form. ![](https://manual.bubble.io/files/HQyTkIDXBJfi0ZCiyL7R) ![](https://manual.bubble.io/files/DYzHRsQP1mTYcVdB8cOn) To sign the user up, start a workflow from the Signup button in the Signup form and add the "Sign the user up" workflow action. Here, you'll map the email input's value and password input's value to the workflow parameters so that the workflow action can register those two fields. ![](https://manual.bubble.io/files/GrkDPvDzgIT4RuYazvrp) Next, we need to add a new field to the User data type so we can capture the name of the user on signup. On the data tab, select the User data type and add a new Field of type text called "Name". Going back to the signup workflow, add a new action after "Sign the user up" called "Make changes to Current User". Here, you'll map the Name parameter to the Input Name's value to update the user you just signed up with the name they entered. ![](https://manual.bubble.io/files/fAXUMIryzhZNGMbjmZd0) As you continue building your app, you can add additional workflows here to navigate the user to the proper page after they sign up, or any other logic that your application needs. To connect the Login button, start a workflow from the Login button and add the "Log the user in" workflow action. Just like with Signup, you'll map the email and password input's value from the Login form to the Email and Password parameters. As you continue building your app, you can add additional logic here depending on what you want to happen after a user logs into your app. ![](https://manual.bubble.io/files/sIyHpTbq1x1FfNBiK7PK) There you have it, your landing page is now connected to a full user authentication workflow! \[^1\]: \*Containers\* are used to contain elements and control how they behave on the page. Bubble has six container types that behave in different ways.\\ Article series: \[Containers\](/help-guides/design/elements/web-app/containers.md) \[^2\]: \*Visual elements\* are the elements you can place on that page that cannot contain other elements (groups) and cannot accept input (input elements), such as text, images and icons. Article: \[Visual elements\](/help-guides/design/elements/web-app/visual-elements.md) \[^3\]: Input forms are the elements that you use to collect information from your users, such as text input, date pickers and file uploaders. They can be used for a simple checkbox or combined into complex forms. Article series: \[Input forms\](/help-guides/design/elements/web-app/input-forms.md) \[^4\]: \*Workflows\* are the engine of your application – they are how you instruct Bubble to respond to what the user does, such as clicking a button, with a set of actions that can do anything from hiding/showing or animating things on the page to making changes in the database and make external API calls. A \*workflow\* is the combination of an \*event\* that triggers one or more \*actions\*. Article series: \[Workflows\](/help-guides/logic/workflows.md) \[^5\]: \*Responsive design\* is a method that gives your users a great experience no matter what kind of device they are using to access your app.\\ The goal of responsive design is to create a single page that automatically adjusts its layout and content to fit the screen size and resolution of the device being used to access it. Article series: \[Responsive design\](/help-guides/design/responsive-design.md) \[^6\]: The property editor is the main tool for configuring the elements on your page. When you double-click an element on the page or single-click it in the left-hand element tree, this draggable popup appears, displaying various fields for customization. Article: \[The property editor\](/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-property-editor.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/the-component-library.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance.md). # Database maintenance {% hint style="info" %} This section covers different ways in which you can maintain your database to keep it running efficiently. If you want to learn more about the database in general and how it works, you can check out our dedicated article series below. Article series: \[The database\](/help-guides/data/the-database.md) {% endhint %} The database is the filing cabinet of your application, where all data is archived for storage. Just like a regular archive, it makes sense to keep it clean and up-to-date. This is a good idea for a few reasons: \* \*\*Performance:\*\* The more unnecessary data you keep around, the bigger your database becomes. This means more data for Bubble to search through and overall can affect your performance \* \*\*Privacy:\*\* Removing unneeded data is good from a privacy perspective \* \*\*Data integrity:\*\* As you scale and grow your app, a clean database can help you with decision making, since you can confidently make decisions based on reliable data This article series goes over a few different concepts that helps you maintain your database properly. Copying the database Copying the database means to clone the content of the development database into the live database or vice versa. This is a simple, automated operation in Bubble. Article: Copying the database Restoring database backups Bubble keeps automated \[point-in-time backups\](#user-content-fn-1)\[^1\] that can be restored back to that state with a simple operation. Article: \[Restoring database backups\](/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups.md) Running bulk operations Bulk operations means to run a workflow on multiple things in your database in sequence. This helps you perform tasks that would be tedious to do manually, such as deleting and making changes to things. Article: \[Bulk operations\](/help-guides/maintaining-an-application/database-maintenance/bulk-operations.md) Related articles \* Article series: \[The database\](/help-guides/data/the-database.md) \* Article series: \[Hosting and scaling\](/help-guides/optimizing-an-application/hosting-and-scaling.md) \[^1\]: \*Point-in-time backup\* means that for every change made to the database, a snapshot is saved. This snapshot can then be used later to restore the database to that exact point in time if something should go wrong. This is particularly useful for recovering data in the case of accidental deletion or changes. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \# Bubble Docs ## Bubble Docs - \[Introduction\](https://manual.bubble.io/master.md): Welcome to the Bubble Docs. - \[New? Start Here\](https://manual.bubble.io/new-start-here.md) - \[What is Bubble?\](https://manual.bubble.io/what-is-bubble.md) - \[The Glossary\](https://manual.bubble.io/the-glossary.md) - \[Getting started\](https://manual.bubble.io/help-guides/getting-started.md): How to use the Bubble Manual efficiently - \[Building for...\](https://manual.bubble.io/help-guides/getting-started/building-for....md) - \[Web\](https://manual.bubble.io/help-guides/getting-started/building-for.../web.md) - \[Native iOS and Android\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android.md) - \[Mobile app quick start guide\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/mobile-app-quick-start-guide.md) - \[What is a native mobile app?\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/what-is-a-native-mobile-app.md) - \[Native mobile vs. web development\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-vs.-web-development.md) - \[Differences in native and web elements\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/differences-in-native-and-web-elements.md) - \[Payments in mobile apps\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/payments-in-mobile-apps.md) - \[In-app purchases\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases.md) - \[IAP on Apple devices\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/iap-on-apple-devices.md) - \[IAP on Android devices\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/iap-on-android-devices.md) - \[Setting up subscriptions\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/setting-up-subscriptions.md) - \[Getting ready for Production\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/getting-ready-for-production.md) - \[Apple IAP checklist\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/getting-ready-for-production/apple-iap-checklist.md) - \[Android IAP checklist\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/getting-ready-for-production/android-iap-checklist.md) - \[Workflow and language\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/in-app-purchases/workflow-and-language-updates.md) - \[Native mobile app terminology\](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android/native-mobile-app-terminology.md) - \[Building your first app\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app.md) - \[Planning features\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/planning-features.md) - \[Database structure\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/database-structure.md) - \[Design and UX\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/design-and-ux.md) - \[eCommerce and payments\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments.md) - \[Shopping cart\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/shopping-cart.md) - \[Checkout page\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/checkout-page.md) - \[One-time payments\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/one-time-payments.md) - \[Subscriptions\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/subscriptions.md) - \[Marketplace\](https://manual.bubble.io/help-guides/getting-started/building-your-first-app/ecommerce-and-payments/marketplace.md) - \[Creating and managing projects\](https://manual.bubble.io/help-guides/getting-started/creating-and-managing-projects.md): This section covers how to create, manage and delete projects connected to your Bubble account - \[The Bubble editor\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor.md): This section covers how to navigate the Bubble editor - \[Tabs and sections\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections.md) - \[Property Editor Beta\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta.md): This page is dedicated to the the beta for the redesigned property editor (as of Dec 2025). - \[Quick start guide (For new users)\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/quick-start-guide-for-new-users.md): Last Updated: April 2026 - \[Overview of the property editor beta\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/property-editor.md) - \[Property editor migration guide (For existing users)\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/property-editor-beta/property-editor-migration-guide-for-existing-users.md): Last updated: April 2026 - \[Design tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab.md) - \[The element tree\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-element-tree.md): This section covers the element tree found in the Design tab of the Bubble editor. - \[The property editor\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/design-tab/the-property-editor.md) - \[Workflow tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/workflow-tab.md) - \[Data tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/data-tab.md) - \[Global tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/styles-tab.md) - \[Global expressions\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/styles-tab/global-expressions.md) - \[Plugins tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/plugins-tab.md) - \[Settings tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab.md) - \[Overview\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab/overview.md) - \[Web app\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab/web-app.md) - \[Custom domain and DNS\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab/web-app/custom-domain-and-dns.md) - \[Native mobile\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/settings-tab/native-mobile.md) - \[Logs tab\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/logs-tab.md) - \[Tools\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools.md) - \[Key features\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/key-features.md) - \[The search tool\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/the-search-tool.md) - \[The Issue Checker\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/the-issue-tracker.md) - \[The debugger\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/using-the-debugger.md) - \[Notes\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tools/notes.md): This section covers how to add notes to different parts of your Bubble app to document your work - \[Previewing your app\](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/previewing-your-app.md) - \[Transitioning to Bubble from...\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from.md) - \[JavaScript\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/javascript.md) - \[HTML and CSS\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/html-and-css.md) - \[SQL\](https://manual.bubble.io/help-guides/getting-started/transitioning-to-bubble-from/sql.md) - \[Design\](https://manual.bubble.io/help-guides/design.md): At the heart of Bubble's capabilities is the ability to effortlessly create designs with precision: from basic forms to professional websites and SaaS applications - \[Elements\](https://manual.bubble.io/help-guides/design/elements.md): This section covers elements – the building blocks that make up your application's user interface - \[Web app\](https://manual.bubble.io/help-guides/design/elements/web-app.md) - \[The page\](https://manual.bubble.io/help-guides/design/elements/web-app/the-page.md): The page is the blank canvas on which you design your app's user interface. - \[Containers\](https://manual.bubble.io/help-guides/design/elements/web-app/containers.md): This section covers the container elements, used to group and control the behavior of other elements - \[Groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/groups.md): This section covers Groups, that can be used to contain elements and data and control the responsive behavior of child elements - \[Repeating groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/repeating-groups.md): This section covers the container type repeating group, used to display lists of things such as records from the database - \[Table elements\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/table-elements.md): This section covers the table element, used to display lists of things such as records from the database in a table-like structure of rows and columns - \[Popups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/popups.md): This section covers the container type Popup, which is a group that hovers above all other elements on the screen - \[Floating groups\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/floating-groups.md): This section covers the group type Floating Group, which is used primarily for attaching a group to one of the sides of the screen, regardless of scrolling position - \[Group focus\](https://manual.bubble.io/help-guides/design/elements/web-app/containers/group-focus.md): This section covers the group type Group Focus. This group will remain visible for as long as it is in focus, typically used for dropdown menus - \[Visual elements\](https://manual.bubble.io/help-guides/design/elements/web-app/visual-elements.md): This section describes the visual elements that are available in the Bubble editor - \[Input forms\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms.md): This section covers Input forms. These are element that accept data input from a user such as text, numbers, dates, uploads and dynamic content. - \[Text and numbers\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/text-and-numbers.md): This section covers elements that accept text and numbers as user input - \[Dates and time\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/dates-and-time.md): This section covers elements that accepts dates and time as user input - \[File uploads\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/file-uploads.md): This section covers elements that lets your users upload files and images - \[Selection controls\](https://manual.bubble.io/help-guides/design/elements/web-app/input-forms/selection-controls.md): This section covers selection control elements, that lets you set up input elements with predefined options - \[iOS and Android app\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app.md) - \[The view\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/the-view.md) - \[Containers\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/containers.md) - \[Visual elements\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/visual-native-app-elements.md) - \[Input forms\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/input-forms.md) - \[Mobile reusable elements\](https://manual.bubble.io/help-guides/design/elements/ios-and-android-app/mobile-reusable-elements.md) - \[The element hierarchy\](https://manual.bubble.io/help-guides/design/elements/the-element-hierarchy.md): This section covers the logic of the hierarchy that is structured on your page as you add elements to it. - \[Reusable Elements\](https://manual.bubble.io/help-guides/design/elements/reusable-elements.md): This section covers reusable elements: elements that can be using in multiple places in your app - \[Variables and styles\](https://manual.bubble.io/help-guides/design/variables-and-styles.md): This section covers the different styling properties that can be applied to elements, such as colors, borders, shadows and fonts. - \[Color variables\](https://manual.bubble.io/help-guides/design/variables-and-styles/color-variables.md): This section covers Color variables, used to set a palette of colors that can be applied throughout your app - \[Font variables\](https://manual.bubble.io/help-guides/design/variables-and-styles/font-variables.md): This section covers font variables, used to manage a collection of fonts that can be applied to elements and styles throughout your app - \[Styles\](https://manual.bubble.io/help-guides/design/variables-and-styles/styles.md): This section covers styles, which is Bubble's tool for managing centralized stylesheets that can be applied to elements across your app - \[Custom fonts\](https://manual.bubble.io/help-guides/design/variables-and-styles/using-custom-fonts.md) - \[Responsive design\](https://manual.bubble.io/help-guides/design/responsive-design.md) - \[Building responsive pages\](https://manual.bubble.io/help-guides/design/responsive-design/building-responsive-pages.md) - \[Legacy articles\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles.md) - \[The Basics (Legacy)\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/the-basics.md): This page covers educational material relevant to the Legacy Bubble Editor. - \[Building Responsive Pages (Legacy)\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/building-responsive-pages.md): This page covers educational material relevant to the Legacy Bubble Editor. - \[Migrating Legacy Pages\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/migrating-legacy-pages.md) - \[Tips When Designing (Legacy)\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/tips.md) - \[Templates\](https://manual.bubble.io/help-guides/design/using-a-template.md) - \[The Component Library\](https://manual.bubble.io/help-guides/design/the-component-library.md) - \[Importing from Figma\](https://manual.bubble.io/help-guides/design/importing-from-figma.md) - \[Auto layout\](https://manual.bubble.io/help-guides/design/importing-from-figma/auto-layout.md) - \[Custom elements\](https://manual.bubble.io/help-guides/design/importing-from-figma/custom-elements.md) - \[Data\](https://manual.bubble.io/help-guides/data.md): This section covers the different ways you work with data in Bubble - \[The database\](https://manual.bubble.io/help-guides/data/the-database.md): This section covers different aspects of how the Bubble database works - \[Data types and fields\](https://manual.bubble.io/help-guides/data/the-database/data-types-and-fields.md): This section covers what data types are and how you can set up custom types of data with fields holding different kinds of information - \[Creating, saving and deleting data\](https://manual.bubble.io/help-guides/data/the-database/creating-saving-and-deleting-data.md): This article covers how to work with the data in your database by creating, changing and deleting things - \[Finding data\](https://manual.bubble.io/help-guides/data/the-database/finding-data.md): This section covers how to search for data using constraints - \[Displaying data\](https://manual.bubble.io/help-guides/data/the-database/displaying-data.md): This section covers how to display data from the database in your app - \[Protecting data with privacy rules\](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules.md): This section covers how to use privacy rules to protect private data - \[The database editor\](https://manual.bubble.io/help-guides/data/the-database/managing-data.md): This section covers Bubble's built-in database editor that lets you manage all the data in your app from one central place - \[Export/import data\](https://manual.bubble.io/help-guides/data/the-database/export-import-data.md) - \[Exporting data\](https://manual.bubble.io/help-guides/data/the-database/export-import-data/exporting-data.md) - \[Importing data (CSV)\](https://manual.bubble.io/help-guides/data/the-database/export-import-data/importing-data-csv.md) - \[Working with location data\](https://manual.bubble.io/help-guides/data/the-database/working-with-location-data.md) - \[Using Algolia\](https://manual.bubble.io/help-guides/data/the-database/using-algolia.md): This section covers how to use the third-party search provider Algolia with Bubble - \[Database structure by app type\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type.md) - \[Marketplace Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/marketplace-apps.md) - \[Directory & Listings Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/directory-and-listings-apps.md) - \[Social Network Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/social-network-apps.md) - \[SaaS Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/saas-apps.md) - \[Project Management Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/project-management-apps.md) - \[CRM Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/crm-apps.md) - \[Professional Services Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/professional-services-apps.md) - \[On-demand Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/on-demand-apps.md) - \[Documentation/ CMS Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/documentation-cms-apps.md) - \[Applicant Tracking System (ATS) Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/applicant-tracking-system-ats-apps.md) - \[Portfolio Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/portfolio-apps.md) - \[Gallery Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/gallery-apps.md) - \[Online Store / Ecommerce Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/online-store-ecommerce-apps.md) - \[Blog Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/blog-apps.md) - \[Messaging App\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/messaging-app.md) - \[Dashboards\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/dashboards.md) - \[Building Block Apps\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/building-block-apps.md) - \[Bubble as a backend\](https://manual.bubble.io/help-guides/data/the-database/database-structure-by-app-type/bubble-as-a-backend.md) - \[Files\](https://manual.bubble.io/help-guides/data/files.md): This section covers how Bubble handles uploaded files and images and - \[Images\](https://manual.bubble.io/help-guides/data/images.md) - \[Static data\](https://manual.bubble.io/help-guides/data/static-data.md): This section covers different ways of saving static data in Bubble - \[App texts (translations)\](https://manual.bubble.io/help-guides/data/static-data/app-texts-translations.md): This section covers how to translate your app into multiple languages - \[Option sets\](https://manual.bubble.io/help-guides/data/static-data/option-sets.md): This section covers option sets, used to store a static list of options in a database-like structure - \[Temporary data\](https://manual.bubble.io/help-guides/data/temporary-data.md): This section covers temporary data, which is different types of variables that you can use to store data temporarily. - \[Custom states\](https://manual.bubble.io/help-guides/data/temporary-data/custom-states.md): This section covers custom states, that are used to store temporary variables of different kinds - \[URL parameters\](https://manual.bubble.io/help-guides/data/temporary-data/url-parameters.md) - \[User accounts\](https://manual.bubble.io/help-guides/data/user-accounts.md): This article covers how you create and manage Users in your app - \[Authentication plugins\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins.md) - \[Facebook plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/facebook-plugin.md) - \[Fitbit plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/fitbit-plugin.md) - \[Google plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/google-plugin.md) - \[Instagram plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/instagram-plugin.md) - \[LinkedIn plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/linkedin-plugin.md) - \[Pinterest plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/pinterest-plugin.md) - \[Slack plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/slack-plugin.md) - \[Wistia plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/wistia-plugin.md) - \[YouTube plugin\](https://manual.bubble.io/help-guides/data/user-accounts/authentication-plugins/youtube-plugin.md) - \[Cookies set by Bubble\](https://manual.bubble.io/help-guides/data/user-accounts/cookies-set-by-bubble.md) - \[Time, dates and time zones\](https://manual.bubble.io/help-guides/data/time-dates-and-time-zones.md) - \[Logic\](https://manual.bubble.io/help-guides/logic.md): This section covers Logic - the expressions and workflows that makes your app do the things you want it to do - \[The frontend and backend\](https://manual.bubble.io/help-guides/logic/the-frontend-and-backend.md): This section describes the difference between workflows running on the frontend and backend - \[Workflows\](https://manual.bubble.io/help-guides/logic/workflows.md): This section explores workflows — the driving force that powers your app and brings its functionality to life. - \[Events\](https://manual.bubble.io/help-guides/logic/workflows/events.md): This section covers events, which are the triggers that start a workflow - \[Frontend events\](https://manual.bubble.io/help-guides/logic/workflows/events/frontend-events.md): The section covers frontend events, which are the events that are triggered on a page. - \[Recurring workflows\](https://manual.bubble.io/help-guides/logic/workflows/events/frontend-events/recurring-workflows.md): This section covers recurring client-side workflows - \[Custom events\](https://manual.bubble.io/help-guides/logic/workflows/events/frontend-events/custom-events.md): This section covers Custom events. They are events that can be triggered by other workflows to avoid duplicating workflows, as well as triggered inside a reusable element. - \[Backend events\](https://manual.bubble.io/help-guides/logic/workflows/events/backend-events.md): This section covers backend events, which are events that trigger on Bubble's server - \[Database trigger events\](https://manual.bubble.io/help-guides/logic/workflows/events/backend-events/database-trigger-events.md): This section covers database trigger events, which are events that trigger whenever some specific data in the database changes - \[Backend custom events\](https://manual.bubble.io/help-guides/logic/workflows/events/backend-events/backend-custom-events.md) - \[Actions\](https://manual.bubble.io/help-guides/logic/workflows/actions.md): This section covers actions, which are the steps in a workflow that perform different tasks - \[Dynamic expressions\](https://manual.bubble.io/help-guides/logic/dynamic-expressions.md): This section covers how to set up dynamic expressions in Bubble - \[Conditions\](https://manual.bubble.io/help-guides/logic/conditions.md) - \[Navigation\](https://manual.bubble.io/help-guides/logic/navigation.md): This section covers how to navigate between sections and pages in your app - \[Single-page applications (SPA)\](https://manual.bubble.io/help-guides/logic/navigation/single-page-applications-spa.md): This section covers navigation of single-page applications - \[Multi-page applications\](https://manual.bubble.io/help-guides/logic/navigation/multi-page-applications.md): This section covers navigation of multi-page applications - \[Page slugs\](https://manual.bubble.io/help-guides/logic/navigation/page-slugs.md) - \[Device resources\](https://manual.bubble.io/help-guides/logic/device-resources.md) - \[Location services\](https://manual.bubble.io/help-guides/logic/device-resources/location-services.md) - \[Camera/photo library\](https://manual.bubble.io/help-guides/logic/device-resources/camera-photo-library.md) - \[Workload\](https://manual.bubble.io/help-guides/workload.md) - \[Understanding workload\](https://manual.bubble.io/help-guides/workload/understanding-workload.md) - \[Activity types\](https://manual.bubble.io/help-guides/workload/understanding-workload/what-contributes-to-workload.md): This section covers how different activity types contribute to your app's total workload - \[The workload calculation\](https://manual.bubble.io/help-guides/workload/understanding-workload/the-workload-calculation.md) - \[Client-side and server-side processing\](https://manual.bubble.io/help-guides/workload/understanding-workload/client-side-and-server-side-processing.md) - \[Tracking workload\](https://manual.bubble.io/help-guides/workload/tracking-workload.md) - \[Measuring\](https://manual.bubble.io/help-guides/workload/tracking-workload/measuring-workload.md) - \[Using App Metrics\](https://manual.bubble.io/help-guides/workload/tracking-workload/measuring-workload/using-app-metrics.md): This section covers how to use App metrics to analyze how different activities contribute to your app's total workload over a given period of time - \[Monitoring\](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload.md) - \[Workload notifications\](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/workload-notifications.md) - \[Infinite recursion protection\](https://manual.bubble.io/help-guides/workload/tracking-workload/monitoring-workload/infinite-recursion-protection.md) - \[Optimizing workload\](https://manual.bubble.io/help-guides/workload/optimizing-workload.md) - \[Optimization framework\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-framework.md) - \[Optimization checklist\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist.md) - \[Page load\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/page-load.md) - \[Searches\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/searches.md) - \[Workflows and actions\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/workflows-and-actions.md) - \[Backend workflows\](https://manual.bubble.io/help-guides/workload/optimizing-workload/optimization-checklist/backend-workflows.md) - \[Agency showcases\](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases.md) - \[Minimum Studio\](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/minimum-studio.md) - \[Neam\](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/neam.md) - \[Support Dept\](https://manual.bubble.io/help-guides/workload/optimizing-workload/agency-showcases/support-dept.md) - \[Security\](https://manual.bubble.io/help-guides/security.md) - \[Bubble's security features\](https://manual.bubble.io/help-guides/security/bubbles-security-features.md) - \[Planning app security\](https://manual.bubble.io/help-guides/security/planning-app-security.md): This section explores how you can work to establish a policy around privacy and security for your app - \[Client-side and server-side\](https://manual.bubble.io/help-guides/security/client-side-and-server-side.md): This section covers the difference between client-side and server-side operations in your app - \[Bubble account security\](https://manual.bubble.io/help-guides/security/bubble-account-security.md): This section covers how to keep your Bubble account secure - \[App security\](https://manual.bubble.io/help-guides/security/app-security.md): This section covers security applied on an app level - \[Page security\](https://manual.bubble.io/help-guides/security/page-security.md): This section covers security on pages, elements and workflows - \[API security\](https://manual.bubble.io/help-guides/security/api-security.md): This section covers security related to incoming and outgoing API calls - \[API Connector security\](https://manual.bubble.io/help-guides/security/api-security/api-connector-security.md): This section covers security related to the API Connector plugin. - \[Data API security\](https://manual.bubble.io/help-guides/security/api-security/data-api-security.md): This section covers security related to the Data API. - \[Workflow API security\](https://manual.bubble.io/help-guides/security/api-security/workflow-api-security.md): This section covers security related to the Workflow API. - \[Security dashboard\](https://manual.bubble.io/help-guides/security/security-dashboard.md) - \[Overview\](https://manual.bubble.io/help-guides/security/security-dashboard/overview.md) - \[Security dashboard plan features\](https://manual.bubble.io/help-guides/security/security-dashboard/security-dashboard-plan-features.md) - \[Security tests\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests.md) - \[Privacy rules checker\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/privacy-rules-checker.md) - \[Automated tests\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/automated-tests.md) - \[Issue explorer\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-explorer.md) - \[Issue details\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/issue-details.md) - \[Test settings\](https://manual.bubble.io/help-guides/security/security-dashboard/security-tests/test-settings.md) - \[Security checklist\](https://manual.bubble.io/help-guides/security/security-checklist.md) - \[Previewing your app\](https://manual.bubble.io/help-guides/previewing-your-app.md) - \[Previewing a web app\](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-web-app.md) - \[Previewing a mobile app\](https://manual.bubble.io/help-guides/previewing-your-app/previewing-a-mobile-app.md) - \[Publishing your app\](https://manual.bubble.io/help-guides/publishing-your-app.md) - \[Web app\](https://manual.bubble.io/help-guides/publishing-your-app/deploying-your-app.md) - \[Native mobile app\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app.md) - \[Global native mobile settings\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/global-native-mobile-settings.md) - \[iOS App Store\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/ios-app-store.md) - \[Google Play Store\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/google-play-store.md) - \[Publishing FAQ\](https://manual.bubble.io/help-guides/publishing-your-app/native-mobile-app/publishing-faq.md) - \[AI\](https://manual.bubble.io/help-guides/ai.md) - \[Bubble AI Agent\](https://manual.bubble.io/help-guides/ai/bubble-ai-agent.md) - \[Generate apps with AI\](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator.md) - \[About AI app generation\](https://manual.bubble.io/help-guides/ai/bubbles-ai-app-generator/about-ai-app-generation.md) - \[Generate data types from the Data tab\](https://manual.bubble.io/help-guides/ai/generate-data-types-from-the-data-tab.md) - \[AI page designer\](https://manual.bubble.io/help-guides/ai/ai-page-designer.md) - \[Connect to AI models\](https://manual.bubble.io/help-guides/ai/connect-to-ai-agents.md) - \[Maintenance\](https://manual.bubble.io/help-guides/maintaining-an-application.md) - \[Collaborators\](https://manual.bubble.io/help-guides/maintaining-an-application/collaboration.md): This section covers collaboration, which is how you invite other Bubble users to edit your application and its data - \[Version control\](https://manual.bubble.io/help-guides/maintaining-an-application/version-control.md): This section covers the version control system. - \[Best practices: Version control\](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/best-practices.md): This section covers best practices for using the version control feature with one or more teams - \[Transitioning from the legacy version control\](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/transitioning.md): This section includes tips for transitioning from the legacy to the new version control system - \[Terminology: Version control\](https://manual.bubble.io/help-guides/maintaining-an-application/version-control/terminology.md): This section contains terminology related to the version control system - \[Commenting\](https://manual.bubble.io/help-guides/maintaining-an-application/commenting.md): This section covers how to leave comments in your Bubble app to help with future modification and collaboration - \[Database maintenance\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance.md): This section covers copying, restoring and running bulk operations on the database - \[Copying the database\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/copying-the-database.md): This section covers how to copy the content of the Development database to the Live database, and vice versa - \[Restoring database backups\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/database-copy-and-backups.md): This section covers how you can copy the contents of your database, as well as restore it to a snapshot of what it looked like at a specific date and time - \[Bulk operations\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations.md): This section covers the bulk operations, which lets you run API workflows on a list of things directly from the Bubble database editor - \[Bulk operation methods compared\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/bulk-operations/bulk-operation-methods-compared.md): This article compares the two methods for large bulk operations. - \[Wiping change history\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history.md) - \[Performance\](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling.md) - \[Hard limits\](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits.md) - \[Capacity Usage (legacy)\](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/capacity-usage.md) - \[Notes on queries\](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/notes-on-queries.md) - \[SEO\](https://manual.bubble.io/help-guides/maintaining-an-application/seo.md): This section covers how to work with SEO in Bubble. - \[Introduction to SEO\](https://manual.bubble.io/help-guides/maintaining-an-application/seo/introduction-to-seo.md): This page gives a general overview of what SEO is and some tips on how to plan your SEO efforts - \[SEO: App\](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-app.md): This section covers the app-wide SEO features that Bubble offers - \[SEO: Page\](https://manual.bubble.io/help-guides/maintaining-an-application/seo/seo-page.md): This section covers the SEO settings for the page and how they can affect your rankings - \[Testing and debugging\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application.md): This section covers how to preview and debug your app to prepare it for live users - \[Introduction to testing and debugging\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-basics.md): This section covers general advice for testing and debugging your app - \[The native mobile debugger\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/the-native-mobile-debugger.md) - \[The server logs\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/using-server-logs.md): This section covers how to use the Server Logs for debugging your app - \[Supported browsers\](https://manual.bubble.io/help-guides/maintaining-an-application/testing-an-application/supported-browsers.md): This section covers the browsers that are officially supported by Bubble - \[API workflow scheduler\](https://manual.bubble.io/help-guides/maintaining-an-application/scheduler.md): This section covers the scheduler, which lets you view, pause and delete upcoming scheduled workflows - \[Integrations\](https://manual.bubble.io/help-guides/integrations.md): This section covers different ways to integrate your application to other apps on the web - \[API\](https://manual.bubble.io/help-guides/integrations/api.md): Unlock the power of APIs in your Bubble application - \[Introduction to APIs\](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis.md): In this section we will go over what an API is and how you can use it in your Bubble application. - \[What is a RESTful API?\](https://manual.bubble.io/help-guides/integrations/api/introduction-to-apis/what-is-a-restful-api.md): This section covers what it means that an API is RESTful and how a RESTful API call is structured - \[The Bubble API\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api.md): This section covers the different ways in which Bubble can set up API endpoints to allow other applications to read and edit your database, as well as execute workflows. - \[Bubble API terminology\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/bubble-api-terminology.md): This section covers the specific Bubble-related terminology concerning APIs - \[Authentication\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication.md): This section covers how to authenticate clients that initiate a connection to your Bubble application. - \[How to authenticate\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/how-to-authenticate.md): This section covers what kind of authentication method the Bubble API accepts. - \[No authentication\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/no-authentication.md): This section covers how to set up incoming API connections that don't require any authentication. - \[As a user\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/as-a-user.md): This section covers how to authenticate an API client as a user logged in to your application, allowing you to protect your data with privacy rules - \[As an admin\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/authentication/as-an-admin.md): This section covers how to authenticate API clients making incoming requests with full administrative access using a Bubble API token. - \[The Data API\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api.md): This section covers the Data API, which lets you set up your application to accept incoming requests to read, create, edit and delete records in your database. - \[Data API Privacy Rules\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-privacy-rules.md): This section covers the Privacy Rules settings for the Data API - \[Data API endpoints\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-endpoints.md): This section covers how to identify the correct endpoint when using the Bubble Data API. - \[Data API requests\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-data-api/data-api-requests.md): This section covers the different requests that you can make with the Data API. - \[The Workflow API\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api.md): This section covers how to use API workflows to allow external applications to execute workflows in your Bubble app. - \[Workflow API privacy rules\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-privacy-rules.md): This section covers how API Workflows are affected by privacy rules. - \[Workflow API endpoints\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/workflow-api-endpoints.md): This section covers how to identify the correct endpoint for a given API Workflow - \[API workflows\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows.md): This section covers API workflows and how to set them up in your application. - \[Creating API workflows\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/creating-api-workflows.md): This section covers how to create and setup an API Workflow. - \[Scheduling API workflows\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/scheduling-api-workflows.md): API Workflows can be triggered or scheduled internally in your app - \[Recursive API workflows\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/recursive-api-workflows.md): This section describes what recursive workflows are and how to set them up - \[Case: Stripe notifications\](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/examples-and-walkthroughs.md) - \[The API Connector\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector.md): This section covers Bubble's API Connector. The API Connector is used to make outbound connections to external applications and use it as a data source or trigger actions. - \[Authentication\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/authentication.md): This section covers the different authentication methods the API Connector offers. - \[API guides\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides.md) - \[OpenAI\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai.md) - \[Authentication\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai/authentication.md) - \[Calls\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai/calls.md) - \[ChatGPT\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai/calls/chatgpt.md) - \[Chat\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/openai/calls/chatgpt/chat.md) - \[Google Translate\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/case-google-translate.md): Use Bubble's API Connector to connect to Google's Translate API and automatically translate text strings in your app. - \[How to setup Google API keys\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/api-guides/case-google-translate/how-to-setup-google-api-keys.md): The video guide below will help you set up API keys in Google Cloud. - \[Streaming API\](https://manual.bubble.io/help-guides/integrations/api/the-api-connector/streaming-api.md) - \[Plugins that connect to APIs\](https://manual.bubble.io/help-guides/integrations/api/plugins-that-connect-to-apis.md): This section covers plugins that offer API-related services - \[API Glossary\](https://manual.bubble.io/help-guides/integrations/api/api-glossary.md): This section covers widely used API terminology. - \[Plugins\](https://manual.bubble.io/help-guides/integrations/using-plugins.md) - \[What Plugins Can Do\](https://manual.bubble.io/help-guides/integrations/using-plugins/what-plugins-can-do.md) - \[Installing and using Plugins\](https://manual.bubble.io/help-guides/integrations/using-plugins/installing-and-using-plugins.md) - \[Special Plugins\](https://manual.bubble.io/help-guides/integrations/using-plugins/special-plugins.md) - \[SQL Database Connector\](https://manual.bubble.io/help-guides/integrations/sql-database-connector.md): This section covers the SQL Database Connector plugin, which lets you connect with external SQL databases - \[Bubble App Connector\](https://manual.bubble.io/help-guides/integrations/bubble-app-connector.md): This section covers the Bubble App Connector plugin, used to connect two Bubble applications to each other - \[WorkOS\](https://manual.bubble.io/help-guides/integrations/workos.md) - \[WorkOS SSO\](https://manual.bubble.io/help-guides/integrations/workos/workos-sso.md) - \[WorkOS API\](https://manual.bubble.io/help-guides/integrations/workos/workos-api.md) - \[Infrastructure\](https://manual.bubble.io/help-guides/optimizing-an-application.md) - \[Sub-apps\](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps.md) - \[Bubble release tiers\](https://manual.bubble.io/help-guides/optimizing-an-application/bubble-release-tiers.md) - \[Hosting and scaling\](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling.md): This section explores how Bubble hosts your app - \[How Bubble hosting works\](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling/how-bubble-hosting-works.md): This section explores how Bubble hosting works and what kind of services you get with the hosting - \[Scaling with Bubble\](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling/scaling-with-bubble.md): This section covers what it means to scale your Bubble app, and the tools we provide to ensure that scaling happens smoothly - \[CDN (Cloudflare)\](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling/cdn-cloudflare.md) - \[Bubble app names\](https://manual.bubble.io/help-guides/optimizing-an-application/hosting-and-scaling/bubble-app-names.md) - \[Compliance\](https://manual.bubble.io/help-guides/optimizing-an-application/compliance.md): This section covers how Bubble works with different compliance frameworks - \[GDPR\](https://manual.bubble.io/help-guides/optimizing-an-application/compliance/gdpr.md): The General Data Protection Regulation - \[SOC 2 Type II\](https://manual.bubble.io/help-guides/optimizing-an-application/compliance/soc-2-type-ii.md): This section covers Bubble and SOC 2 compliance - \[HIPAA\](https://manual.bubble.io/help-guides/optimizing-an-application/compliance/hipaa.md): This section covers Bubble and HIPAA compliance - \[Other frameworks and standards\](https://manual.bubble.io/help-guides/optimizing-an-application/compliance/other-frameworks.md) - \[Bubble for Enterprise\](https://manual.bubble.io/help-guides/bubble-for-enterprise.md) - \[Hosting and infrastructure\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure.md) - \[Dedicated instance\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance.md) - \[The Dedicated editor experience\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/the-dedicated-editor-experience.md) - \[Technical specs\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/technical-specs.md) - \[Main cluster dependencies\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/main-cluster-dependencies.md) - \[Customizable options\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/customizable-options.md) - \[Migration process\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/migration-process.md) - \[Pre-migration\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/migration-process/pre-migration.md) - \[During migration\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/migration-process/during-migration.md) - \[Post-migration\](https://manual.bubble.io/help-guides/bubble-for-enterprise/hosting-and-infrastructure/dedicated-instance/migration-process/post-migration.md) - \[Security and compliance\](https://manual.bubble.io/help-guides/bubble-for-enterprise/security-and-compliance.md) - \[Single sign-on (SSO)\](https://manual.bubble.io/help-guides/bubble-for-enterprise/security-and-compliance/single-sign-on-sso.md) - \[Admin and collaboration\](https://manual.bubble.io/help-guides/bubble-for-enterprise/admin-and-collaboration.md) - \[Priority support\](https://manual.bubble.io/help-guides/bubble-for-enterprise/priority-support.md) - \[Billing and Payment Guideline for Dedicated Instances\](https://manual.bubble.io/help-guides/bubble-for-enterprise/billing-and-payment-guideline-for-dedicated-instances.md) - \[Using the core reference\](https://manual.bubble.io/core-resources/using-the-core-reference.md) - \[Bubble's Interface\](https://manual.bubble.io/core-resources/bubbles-interface.md) - \[Design tab\](https://manual.bubble.io/core-resources/bubbles-interface/design-tab.md) - \[Design tab (Legacy)\](https://manual.bubble.io/core-resources/bubbles-interface/design-tab-1.md) - \[Workflow tab\](https://manual.bubble.io/core-resources/bubbles-interface/workflow-tab.md) - \[Data tab\](https://manual.bubble.io/core-resources/bubbles-interface/data-tab.md) - \[Global tab\](https://manual.bubble.io/core-resources/bubbles-interface/global-tab.md) - \[Styles tab (legacy)\](https://manual.bubble.io/core-resources/bubbles-interface/styles-tab.md) - \[Plugins tab\](https://manual.bubble.io/core-resources/bubbles-interface/plugins-tab.md) - \[Settings tab\](https://manual.bubble.io/core-resources/bubbles-interface/settings-tab.md) - \[Logs tab\](https://manual.bubble.io/core-resources/bubbles-interface/logs-tab.md) - \[Template tab\](https://manual.bubble.io/core-resources/bubbles-interface/template-tab.md) - \[Toolbar\](https://manual.bubble.io/core-resources/bubbles-interface/toolbar.md) - \[Top and context menu options\](https://manual.bubble.io/core-resources/bubbles-interface/top-and-context-menu-options.md) - \[Deployment and version control\](https://manual.bubble.io/core-resources/bubbles-interface/version-control-deployment.md) - \[Notes\](https://manual.bubble.io/core-resources/bubbles-interface/comments-and-notes.md) - \[Elements\](https://manual.bubble.io/core-resources/elements.md) - \[Native mobile elements\](https://manual.bubble.io/core-resources/elements/native-mobile-elements.md) - \[View element\](https://manual.bubble.io/core-resources/elements/native-mobile-elements/view-element.md) - \[Navigation elements\](https://manual.bubble.io/core-resources/elements/native-mobile-elements/view-element/navigation-elements.md) - \[List component\](https://manual.bubble.io/core-resources/elements/native-mobile-elements/list-component.md) - \[Visual elements\](https://manual.bubble.io/core-resources/elements/native-mobile-elements/visual-elements.md) - \[Input forms\](https://manual.bubble.io/core-resources/elements/native-mobile-elements/input-forms.md) - \[General properties\](https://manual.bubble.io/core-resources/elements/shared-properties.md) - \[General properties (Legacy)\](https://manual.bubble.io/core-resources/elements/shared-properties-1.md) - \[Styling properties\](https://manual.bubble.io/core-resources/elements/styling-properties.md) - \[Styling Properties (Legacy)\](https://manual.bubble.io/core-resources/elements/styling-properties-1.md) - \[Responsive Properties\](https://manual.bubble.io/core-resources/elements/responsive-properties.md) - \[Responsive Properties (Legacy)\](https://manual.bubble.io/core-resources/elements/responsive-properties-1.md) - \[Conditional formatting\](https://manual.bubble.io/core-resources/elements/conditional-formatting.md) - \[States\](https://manual.bubble.io/core-resources/elements/states.md) - \[Page Element\](https://manual.bubble.io/core-resources/elements/page-element.md) - \[Page Element (Legacy)\](https://manual.bubble.io/core-resources/elements/page-element/page-element.md) - \[Visual Elements\](https://manual.bubble.io/core-resources/elements/visual-elements.md) - \[Containers\](https://manual.bubble.io/core-resources/elements/containers.md) - \[Container Layout Types\](https://manual.bubble.io/core-resources/elements/container-layout-types.md) - \[Containers (Legacy)\](https://manual.bubble.io/core-resources/elements/containers-1.md) - \[Input Forms\](https://manual.bubble.io/core-resources/elements/input-forms.md) - \[Reusable Elements\](https://manual.bubble.io/core-resources/elements/reusable-elements.md) - \[Element Templates (legacy)\](https://manual.bubble.io/core-resources/elements/element-templates.md) - \[Workflows\](https://manual.bubble.io/core-resources/workflows.md) - \[Events\](https://manual.bubble.io/core-resources/events.md): Events trigger workflows. - \[General events\](https://manual.bubble.io/core-resources/events/general-events.md): Events that are triggered upon specific conditions not necessarily initiated by the user interacting with an element. - \[Element events\](https://manual.bubble.io/core-resources/events/element-events.md): Events that are triggered when the user interacts with an element on the page. - \[Custom events\](https://manual.bubble.io/core-resources/events/custom-events.md): Events that can be triggered by other workflows. - \[Recurring event\](https://manual.bubble.io/core-resources/events/recurring-event.md): Events that trigger on the Bubble server at a specific interval. - \[Database trigger event\](https://manual.bubble.io/core-resources/events/trigger-event.md): Database trigger events execute server-side when a specific change happens in the database, regardless of how the change was made. - \[In-app purchase events\](https://manual.bubble.io/core-resources/events/in-app-purchase-events.md) - \[Actions\](https://manual.bubble.io/core-resources/actions.md): Actions are the tasks that Bubble performs. All actions are part of a workflow. - \[Account\](https://manual.bubble.io/core-resources/actions/account.md): Signing up and logging in users is handled automatically by Bubble. - \[Navigation\](https://manual.bubble.io/core-resources/actions/navigation.md): Actions that instructs Bubble to navigate between pages and pause/cancel workflows - \[Data (things)\](https://manual.bubble.io/core-resources/actions/data-things.md): Things are unique records in your database that can be created, edited and deleted with actions. - \[Email and notifications\](https://manual.bubble.io/core-resources/actions/email.md): Actions that send emails. - \[Element\](https://manual.bubble.io/core-resources/actions/element.md): Actions that manipulate elements on the page. - \[Custom\](https://manual.bubble.io/core-resources/actions/custom.md): Actions that trigger, schedule and cancel custom events and API workflows. - \[In-app purchase actions\](https://manual.bubble.io/core-resources/actions/in-app-purchase-actions.md) - \[On-device resources\](https://manual.bubble.io/core-resources/on-device-resources.md) - \[Data\](https://manual.bubble.io/core-resources/data.md): Creating, reading and changing data. - \[Data Sources\](https://manual.bubble.io/core-resources/data/data-sources.md) - \[Operators and comparisons\](https://manual.bubble.io/core-resources/data/operations-and-comparisons.md): Aggregating, manipulating and comparing data. - \[Search\](https://manual.bubble.io/core-resources/data/search.md) - \[Privacy\](https://manual.bubble.io/core-resources/data/privacy.md) - \[Styles\](https://manual.bubble.io/core-resources/styles.md): Defining named styles with properties that can be applied to multiple elements. - \[API\](https://manual.bubble.io/core-resources/api.md): Bubble's API features allow you to set up incoming and outgoing requests to communicate with other applications and services - \[The Bubble API\](https://manual.bubble.io/core-resources/api/the-bubble-api.md): The Data API allows other systems to search for, read, create, modify and delete data in your application’s database via a RESTful interface. - \[The Data API\](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api.md): The Data API allows other systems to search for, read, create, modify and delete data in your application’s database via a RESTful interface. - \[Authentication\](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/authentication.md): This reference entry covers how to authenticate with the Bubble Data API - \[Data API endpoints\](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-endpoints.md): This section describes how to identify the correct endpoints when using the Data API - \[Data API requests\](https://manual.bubble.io/core-resources/api/the-bubble-api/the-data-api/data-api-requests.md): The different resources availabe in the Bubble Data API. - \[The Workflow API\](https://manual.bubble.io/core-resources/api/the-bubble-api/the-workflow-api.md): The Workflow API lets you set up server-side workflows that can be scheduled in your app or triggered from an external application. - \[The API Connector\](https://manual.bubble.io/core-resources/api/the-api-connector.md): The API Connector allows you to set up connections to external APIs from your Bubble application. - \[Authentication\](https://manual.bubble.io/core-resources/api/the-api-connector/authentication.md): The API Connector supports a range of different authentication methods. - \[Adding calls\](https://manual.bubble.io/core-resources/api/the-api-connector/adding-calls.md): After authentication is set up, you can add as many calls as you need to the API provider. - \[Bubble-made Plugins\](https://manual.bubble.io/core-resources/bubble-made-plugins.md) - \[AddtoAny Share Buttons\](https://manual.bubble.io/core-resources/bubble-made-plugins/addtoany-share-buttons.md) - \[Airtable\](https://manual.bubble.io/core-resources/bubble-made-plugins/airtable.md) - \[API Connector\](https://manual.bubble.io/core-resources/bubble-made-plugins/api-connector.md) - \[Blockspring\](https://manual.bubble.io/core-resources/bubble-made-plugins/blockspring.md) - \[Box\](https://manual.bubble.io/core-resources/bubble-made-plugins/box.md) - \[Braintree\](https://manual.bubble.io/core-resources/bubble-made-plugins/braintree.md) - \[Bubble App Connector\](https://manual.bubble.io/core-resources/bubble-made-plugins/bubble-app-connector.md) - \[Chart.js\](https://manual.bubble.io/core-resources/bubble-made-plugins/chart.js.md) - \[Circle Music Player\](https://manual.bubble.io/core-resources/bubble-made-plugins/circle-music-player.md) - \[Draggable Elements\](https://manual.bubble.io/core-resources/bubble-made-plugins/draggable-ui-elements.md) - \[Dropzone\](https://manual.bubble.io/core-resources/bubble-made-plugins/dropzone.md) - \[Facebook\](https://manual.bubble.io/core-resources/bubble-made-plugins/facebook.md) - \[Fitbit\](https://manual.bubble.io/core-resources/bubble-made-plugins/fitbit.md) - \[Full Calendar\](https://manual.bubble.io/core-resources/bubble-made-plugins/full-calendar.md) - \[Google\](https://manual.bubble.io/core-resources/bubble-made-plugins/google.md) - \[Google Analytics\](https://manual.bubble.io/core-resources/bubble-made-plugins/google-analytics.md) - \[Google Optimize\](https://manual.bubble.io/core-resources/bubble-made-plugins/google-optimize.md) - \[Google Places\](https://manual.bubble.io/core-resources/bubble-made-plugins/google-places.md) - \[Ionic Elements\](https://manual.bubble.io/core-resources/bubble-made-plugins/ionic-elements.md) - \[iTunes\](https://manual.bubble.io/core-resources/bubble-made-plugins/itunes.md) - \[Slidebar Menu\](https://manual.bubble.io/core-resources/bubble-made-plugins/slidebar-menu.md) - \[LinkedIn\](https://manual.bubble.io/core-resources/bubble-made-plugins/linkedin.md) - \[Localize Translation\](https://manual.bubble.io/core-resources/bubble-made-plugins/localize-translation.md) - \[Mixpanel\](https://manual.bubble.io/core-resources/bubble-made-plugins/mixpanel.md) - \[Mouse & Keyboard Interactions\](https://manual.bubble.io/core-resources/bubble-made-plugins/mouse-and-keyboard-interactions.md) - \[Multiselect Dropdown\](https://manual.bubble.io/core-resources/bubble-made-plugins/multiselect-dropdown.md) - \[Progress Bar\](https://manual.bubble.io/core-resources/bubble-made-plugins/progress-bar.md) - \[Rich Text Editor\](https://manual.bubble.io/core-resources/bubble-made-plugins/rich-text-editor.md) - \[Rich Text Editor (Legacy)\](https://manual.bubble.io/core-resources/bubble-made-plugins/rich-text-editor-legacy.md) - \[Screenshotlayer\](https://manual.bubble.io/core-resources/bubble-made-plugins/screenshotlayer.md) - \[SelectPDF\](https://manual.bubble.io/core-resources/bubble-made-plugins/selectpdf.md) - \[Slack\](https://manual.bubble.io/core-resources/bubble-made-plugins/slack.md) - \[Segment\](https://manual.bubble.io/core-resources/bubble-made-plugins/segment.md) - \[Slick Slideshow\](https://manual.bubble.io/core-resources/bubble-made-plugins/slick-slideshow.md) - \[SQL Database Connector\](https://manual.bubble.io/core-resources/bubble-made-plugins/sql-database-connector.md) - \[Star Rating\](https://manual.bubble.io/core-resources/bubble-made-plugins/star-rating.md) - \[Stripe\](https://manual.bubble.io/core-resources/bubble-made-plugins/stripe.md) - \[Tinder-like Element\](https://manual.bubble.io/core-resources/bubble-made-plugins/tinder-like-element.md) - \[Twitter\](https://manual.bubble.io/core-resources/bubble-made-plugins/twitter.md) - \[YouTube\](https://manual.bubble.io/core-resources/bubble-made-plugins/youtube.md) - \[Zapier\](https://manual.bubble.io/core-resources/bubble-made-plugins/zapier.md) - \[Application Settings\](https://manual.bubble.io/core-resources/application-settings.md): General application settings by tab. - \[My plan\](https://manual.bubble.io/core-resources/application-settings/app-plan.md) - \[General\](https://manual.bubble.io/core-resources/application-settings/general.md): General Bubble settings. - \[Domain / email\](https://manual.bubble.io/core-resources/application-settings/domain-email.md) - \[Languages\](https://manual.bubble.io/core-resources/application-settings/languages.md): Translating your app's text strings and error messages into different languages. - \[SEO / metatags\](https://manual.bubble.io/core-resources/application-settings/seo-metatags.md) - \[API\](https://manual.bubble.io/core-resources/application-settings/api.md) - \[Collaboration\](https://manual.bubble.io/core-resources/application-settings/collaboration.md): Adding collaborators in your app to speed up development. - \[Sub-apps\](https://manual.bubble.io/core-resources/application-settings/sub-apps.md) - \[Versions\](https://manual.bubble.io/core-resources/application-settings/versions.md) - \[Elements (PE beta)\](https://manual.bubble.io/core-resources/bubble-elements.md) - \[The element property editor\](https://manual.bubble.io/core-resources/bubble-elements/the-element-property-editor.md) - \[Element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties.md) - \[Web element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties.md) - \[Page properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/page-properties.md) - \[Container properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties.md) - \[Group element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/group-element.md) - \[Repeating group element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/repeating-group-element.md) - \[Popup element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/popup-element.md) - \[Floating group element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/floating-group-element.md) - \[Group focus element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/group-focus-element.md) - \[Table element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/table-element.md) - \[Table row/column\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/table-element/table-row-column.md) - \[Table row/column cell\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/table-element/table-row-column/table-row-column-cell.md) - \[Table row/column repeating\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/table-element/table-row-column-repeating.md) - \[Table repeating row/column cell\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/container-properties/table-element/table-row-column-repeating/table-repeating-row-column-cell.md) - \[Visual element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties.md) - \[Text element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/text-element.md) - \[Button element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/button-element.md) - \[Icon element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/icon-element.md) - \[Link element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/link-element.md) - \[Image element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/image-element.md) - \[Shape element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/shape-element.md) - \[Map element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/map-element.md) - \[Alert element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/alert-element.md) - \[HTML\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/html.md) - \[Video element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/video-element.md) - \[Built on Bubble\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/visual-element-properties/built-on-bubble.md) - \[Input form properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties.md) - \[Input element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/input-element.md) - \[Multiline input element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/multiline-input-element.md) - \[Checkbox element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/checkbox-element.md) - \[Dropdown element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/dropdown-element.md) - \[Searchbox element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/searchbox-element.md) - \[Radio buttons element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/radio-buttons-element.md) - \[Slider input element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/slider-input-element.md) - \[Date/time picker element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/date-time-picker-element.md) - \[Picture uploader element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/picture-uploader-element.md) - \[File uploader element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/input-form-properties/file-uploader-element.md) - \[Bubble-made plugin element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/web-element-properties/bubble-made-plugin-element-properties.md) - \[Native mobile element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties.md) - \[The view element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element.md) - \[View properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/view-properties.md) - \[App bar element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/app-bar-element-mobile.md) - \[Leading/trailing app bar button (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/app-bar-element-mobile/leading-trailing-app-bar-button-mobile.md) - \[Vertical list\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/vertical-list.md) - \[Vertical list item element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/vertical-list/vertical-list-item-element-mobile.md) - \[Swipe action (vertical list element) (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/vertical-list/vertical-list-item-element-mobile/swipe-action-vertical-list-element-mobile.md) - \[Section list element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/section-list-element-mobile.md) - \[Section header element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/section-list-element-mobile/section-header-element-mobile.md) - \[Section list item element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/section-list-element-mobile/section-list-item-element-mobile.md) - \[Swipe action (section list element) (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/section-list-element-mobile/section-list-item-element-mobile/swipe-action-section-list-element-mobile.md) - \[Tab bar element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/tab-bar-element.md) - \[Tab item element\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/the-view-element/tab-bar-element/tab-item-element.md) - \[Container properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile.md) - \[Group element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/group-element-mobile.md) - \[Floating group element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/floating-group-element-mobile.md) - \[Short list element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/short-list-element-mobile.md) - \[Short list item element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/short-list-element-mobile/short-list-item-element-mobile.md) - \[Horizontal list element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/horizontal-list-element-mobile.md) - \[Horizontal List Item element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/horizontal-list-element-mobile/horizontal-list-item-element-mobile.md) - \[Sheet element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/container-properties-mobile/sheet-element-mobile.md) - \[Mobile visual elements\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile.md) - \[Text element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/text-element-mobile.md) - \[Button element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/button-element-mobile.md) - \[Icon element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/icon-element-mobile.md) - \[Image element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/image-element-mobile.md) - \[Map element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/map-element-mobile.md) - \[Shape element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/shape-element-mobile.md) - \[Web view (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/visual-element-properties-mobile/web-view-mobile.md) - \[Input form properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile.md) - \[Input element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/input-element-mobile.md) - \[Multiline input (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/multiline-input-mobile.md) - \[Checkbox element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/checkbox-element-mobile.md) - \[Selectable list element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/selectable-list-element-mobile.md) - \[Selectable list item element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/selectable-list-element-mobile/selectable-list-item-element-mobile.md) - \[Date/time picker element (mobile)\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/native-mobile-element-properties/input-form-properties-mobile/date-time-picker-element-mobile.md) - \[Reusable element properties\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/reusable-element-properties.md) - \[Reusable element instance\](https://manual.bubble.io/core-resources/bubble-elements/element-properties/reusable-element-properties/reusable-element-instance.md) - \[Conditional element properties\](https://manual.bubble.io/core-resources/bubble-elements/conditional-element-properties.md) - \[Workflows (PE beta)\](https://manual.bubble.io/core-resources/bubble-workflows.md) - \[The workflow property editor\](https://manual.bubble.io/core-resources/bubble-workflows/the-workflow-property-editor.md) - \[Events and properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events.md) - \[Frontend event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/frontend-event-properties.md) - \[General event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/frontend-event-properties/general-event-properties.md) - \[Element event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/frontend-event-properties/element-event-properties.md) - \[Custom event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/frontend-event-properties/custom-event-properties.md) - \[Backend event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/backend-event-properties.md) - \[API workflow properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/backend-event-properties/api-workflow-properties.md) - \[A thing is modified event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/backend-event-properties/trigger-event-a-thing-is-modified.md): A thing is modified events execute server-side when a specific change happens in the database, regardless of how the change was made. - \[Recurring event properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/backend-event-properties/recurring-event-properties.md): Events that trigger on the Bubble server at a specific interval. - \[Bubble-made plugin events\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/bubble-made-plugin-events.md) - \[In-app purchase events\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-events/in-app-purchase-events.md) - \[Actions and properties\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions.md) - \[Account actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/account-actions.md) - \[Navigation actions in web apps\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/navigation-actions-in-web-apps.md) - \[Navigation actions in mobile apps\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/navigation-actions-in-mobile-apps.md) - \[Database actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/database-actions.md) - \[Element actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/element-actions.md) - \[Email and notification actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/email-and-notification-actions.md) - \[Native mobile actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/native-mobile-actions.md) - \[Custom actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/custom-actions.md) - \[Backend workflows\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/backend-workflows.md) - \[Bubble-made plugin actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/bubble-made-plugin-actions.md) - \[In-app purchase actions\](https://manual.bubble.io/core-resources/bubble-workflows/bubble-actions/in-app-purchase-actions.md) - \[Conditional workflow properties\](https://manual.bubble.io/core-resources/bubble-workflows/conditional-workflow-properties.md) - \[Account and billing\](https://manual.bubble.io/account-and-marketplace/account-and-billing.md) - \[Pricing and plans\](https://manual.bubble.io/account-and-marketplace/account-and-billing/pricing-plans.md): This section covers Bubble's pricing plans and how workload usage is calculated - \[Plans and billing\](https://manual.bubble.io/account-and-marketplace/account-and-billing/pricing-plans/plans-and-billing.md): This section covers how to manage your plan, workloads, payments and invoices - \[Billing cycle\](https://manual.bubble.io/account-and-marketplace/account-and-billing/pricing-plans/billing-cycle.md) - \[FAQ: Pricing and Workload\](https://manual.bubble.io/account-and-marketplace/account-and-billing/pricing-plans/pricing-faq.md): This section covers frequently asked questions about workload and our pricing plans - \[Account Management\](https://manual.bubble.io/account-and-marketplace/account-and-billing/account-management.md) - \[Building Apps for Others\](https://manual.bubble.io/account-and-marketplace/account-and-billing/building-apps-for-others.md) - \[Selling on the Marketplace\](https://manual.bubble.io/account-and-marketplace/account-and-billing/selling-on-the-marketplace.md) - \[Plans & Billing (legacy)\](https://manual.bubble.io/account-and-marketplace/account-and-billing/plans-and-billing-legacy.md) - \[Official Bubble Certification\](https://manual.bubble.io/account-and-marketplace/official-bubble-certification.md) - \[Hiring certified developers\](https://manual.bubble.io/account-and-marketplace/official-bubble-certification/hiring-certified-developers.md) - \[Building Plugins\](https://manual.bubble.io/account-and-marketplace/building-plugins.md) - \[The Plugin Editor\](https://manual.bubble.io/account-and-marketplace/building-plugins/the-plugin-editor.md) - \[General Settings\](https://manual.bubble.io/account-and-marketplace/building-plugins/general-settings.md) - \[Updating to Plugin API v4\](https://manual.bubble.io/account-and-marketplace/building-plugins/updating-to-plugin-api-v4.md): This documentation covers how to update your server-side actions to be compatible with plugin API v4, which runs on Node 18. - \[Adding API Connections\](https://manual.bubble.io/account-and-marketplace/building-plugins/adding-api-connections.md) - \[Building Elements\](https://manual.bubble.io/account-and-marketplace/building-plugins/building-elements.md) - \[Building Actions\](https://manual.bubble.io/account-and-marketplace/building-plugins/building-actions.md) - \[Loading Data\](https://manual.bubble.io/account-and-marketplace/building-plugins/loading-data.md) - \[Publishing and versioning\](https://manual.bubble.io/account-and-marketplace/building-plugins/publishing-and-versioning.md) - \[Github Integration\](https://manual.bubble.io/account-and-marketplace/building-plugins/github-integration.md) - \[Building Templates\](https://manual.bubble.io/account-and-marketplace/building-templates.md) - \[Application and data ownership\](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership.md) - \[Marketplace policies\](https://manual.bubble.io/account-and-marketplace/marketplace-policies.md) - \[Bug reports\](https://manual.bubble.io/account-and-marketplace/bug-reports.md) - \[Vulnerability Disclosure Policy\](https://manual.bubble.io/vulnerability-disclosure-policy.md) - \[About the Beta features section\](https://manual.bubble.io/beta-features/about-the-beta-features-section.md) - \[Native mobile apps\](https://manual.bubble.io/beta-features/native-mobile-apps.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on a page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/master.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history.md). # Wiping change history {% hint style="danger" %} \*\*NOTE:\*\* Wiping your change history is permanent and cannot be undone. This action deletes all database backups, and you will no longer be able to restore your database to any prior state. By proceeding, you acknowledge that you understand the consequences and accept responsibility for this action. {% endhint %} Bubble allows you to clear your database change history. This article will delve into the implications of this action and weigh its advantages and drawbacks. ## What does it mean to wipe the change history The databases (Development and Live) in your app are both continually backed up for every change that you make (often called real-time backup). This allows you to revert the database to any specific moment in the past, right down to the exact second. The length in time you can go back depends on the plan you are on. The change history represents the records from these backups. By erasing this history, you forfeit the option to restore your database to any previous state. Once wiped, the real-time backups resume, setting your earliest possible restore point to the moment immediately after the wipe. ## Why would you want to wipe the change history? In the majority of cases, there is no reason to erase these backups. They are there to make sure that in the case that you have any reason to revert your database to a previous state, you can do so quickly and without having to export or import any data. With that said, there are a few scenarios where you may consider this option: \* If you have data that you are completely comfortable erasing; for example, you may have test data in one or both of your databases that you want to erase forever \* Clearing the change history might slightly improve your database's performance due to reduced data. However, this potential minor speed boost must be balanced against the significant downside of losing your backup history. Though there might be a marginal benefit for extensive databases, we typically advise against erasing the change history solely for performance gains. \* If your app is on the Enterprise plan, clearing database history can save storage space \* If you wish to permanently remove data, purging the database history is essential to ensure the data cannot be restored by rolling back to a previous state. ## How to wipe the database change history To wipe the database change history, follow these steps: 1. Go to \[\*Data\*\](#user-content-fn-1)\[^1\] \*- App data\* in the Bubble editor 2. \*\*Make sure\*\* you have the correct database (development/live) selected using the \*Switch to live database/Switch to development database\* in the upper right corner of the \*App data\* section. 3. Click \*Copy and restore database\* 4. In the bottom part of the popup, follow the on-screen instructions and click \*Confirm\* 5. Wiping the change history can take a few minutes, depending on the size of your database ## FAQ: Wiping the database change history #### Will wiping change history affect both databases? Wiping your database change history will affect the database you are currently viewing in the \*App data\* section. See the \[instructions above\](#how-to-wipe-the-database-change-history) for how to switch between the two. #### I accidentally wiped the change history – is there any way to get it back? No, this action is permanent and cannot be undone. Before proceeding, confirm that you have the correct database selected and that you understand the consequences. #### Does wiping the change history disable the continuous backups? No. Continuous backups resume immediately after the wipe.You will be able to restore to any point after the wipe, but not before. #### Can I select what data to purge? I.e. only erase data of a specific data type? No, wiping the database change history will affect all data types in that database. \[^1\]: The \*Data tab\* is where you view and manage your app's database, files and option sets. Reference: \[The data tab\](/core-resources/bubbles-interface/data-tab.md) --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/maintaining-an-application/database-maintenance/wiping-change-history.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Unknown \> For the complete documentation index, see \[llms.txt\](https://manual.bubble.io/llms.txt). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as \[Markdown\](https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/the-basics.md). # The Basics (Legacy) The Bubble Visual Editor is based on the What You See Is What You Get (WYSIWYG) principle. You can position elements where you want, down to the pixel, and your app will look like that in Run-mode. These are the basics to keep in mind when you are building an interface. ## Parent-Children relationship Some elements can be containers (found in the container section of the New Element palette), and all elements in Bubble belong to a parent. The page itself is the top parent, and all elements on the page will have the page as their parent. To draw an element inside a container, move your mouse over the container, and you'll notice the borders turn red. Once an element is inside a container, its behavior will follow the parent's behavior, both in Edit and Run-mode. For instance, if you move an element in the editor, the children will stay at the same place relative to their parent. In Run-mode, if you hide a parent, any element inside the container will be hidden as well and, if you show a parent, any element inside it will become visible too. Dragging an element lets you change its parent. The Elements Tree on the left lets you see the structure of your page, and also show/hide elements to better edit and organize them. Many elements will be hidden by default, and you will be able to access them clicking on the eye icon (this will show all parent elements that are also hidden, if necessary). !\[\](/files/-M5sc6ESUPjtKCRepQ2P) The Element Tree has two modes. You can either decide to show all elements on the page in a tree view, with parents and children, or only show hideable elements. Hideable elements are elements that are hidden on page load (from which you have unchecked the box 'This is element is visible on page load'). In other words, you will only see these elements in the list when the option 'only show hideable elements' is checked. This is a useful feature when editing a page because it lets you quickly show elements that aren't visible for editing purposes, while the other mode is useful to get a full view of the page. ## Absolute positioning Elements in Bubble are positioned absolutely, using coordinates (X, Y) that position the element relative to its parent. That way, you have full freedom to position elements wherever you want on the page. This is different from many visual HTML/CSS editors that constrain you to position elements inside some boxes on the page. While it offers more freedom, it also means you need to be careful to have a clean design, and will need to understand Bubble's responsive page settings. ## Responsive design Bubble pages are responsive. In other words, they will adjust to the width of the page so that they look great on mobile devices. Since you can position elements to the pixel, you may have to configure a few settings for your page to behave properly as its width changes. ## Editing elements You add a new element on the page by clicking the type of element you want to add on the visual element panel on the left-hand side (the New Element Palette), and then drawing that element on the page. Once an element is drawn on the page, you can move it by dragging it around, and edit its properties by double-clicking on it. With a few exceptions, most elements are draggable and resizable; Popups are modal containers that appear on the top of the page, and are always centered on the page. Therefore, they are not draggable. When you double click on an element, it reveals the Property Editor, which lets you modify the element fields. ## Naming elements {% embed url="" %} Watch our Academy quick tip for recommendations on naming your elements {% endembed %} You can edit the name of your element in the top of its Property Editor. Select the existing name and start typing. Conventions for naming your elements is entirely up to you. For example, you could simplify each element name and write what it does next to it, such as “btn submit," or you could capitalize the first word all together or use underscores. Whichever convention you pick, make sure to use it throughout your app. The consistency will help you locate your elements and debug your design as your app grows. By default, Bubble names new elements by its type. If we add a button, Bubble will name it "Button A" if there are no other buttons on the page, or "Button B" if there is a button already. If you change the contents of that element to include text, Bubble will take that text and change the name of the element for you. For example, if we change this button's text to "Submit," the name will update to "Button Submit." You might have several "Submit" buttons throughout your application, so it's a good practice to name your elements as you go along so that you can keep track of each. ## Types of Elements There are three main types of elements: Visual elements, Containers, and Input forms. \* Visual elements are elements that display some information, or UI elements that users can interact with by clicking. However, users will usually not be able to type any information into them. \* Containers are elements that contain other elements. Their visibility will impact the visibility of their children, and they can have a defined type of content. \* Input forms are elements where users can enter information. The most common case will be an input form where one can type some text. While each element has its own fields (for instance, input elements have placeholder colors), most Bubble elements have some shared styling properties. These properties can be used to change the background, borders, shadows, font style, etc. Most of these general properties will be modifiable in the Styles tab too. --- # Agent Instructions This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com. ## Querying This Documentation If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question. Perform an HTTP GET request on the current page URL with the \`ask\` query parameter: \`\`\` GET https://manual.bubble.io/help-guides/design/responsive-design/legacy-articles/the-basics.md?ask= \`\`\` The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation. Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections. --- # Marketplace policies | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/account-and-marketplace/marketplace-policies.md) . Last revised: July 10, 2024 When you are active on Bubble's marketplace, either as a Buyer or as a Seller, you have to abide by certain policies, in particular about the licenses for the items you can buy and our commission structure. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-bubbles-marketplace-licenses) 1\. Bubble’s marketplace licenses --------------------------------------------------------------------------------------------------------------------------------------------------- Open Source Plugin License. Buyer may access and use the plugin under the MIT License noted below in Section 2. Single Use Plugin Subscription License. Buyer may access and use the plugin in the single application it was bought for. Buyer pays a recurring subscription fee for the license, which is collected along with Buyer’s regular payments to Bubble and remitted to Seller in accordance with Bubble’s Marketplace Pricing and Payment Policies. Buyer must have an active application subscription in order to obtain this license. Single Use Plugin License. Buyer may access and use the plugin in the single application it was bought for. Buyer pays a one-time fee for the license which is remitted to Seller in accordance with Bubble’s Marketplace Pricing and Payment Policies. Open Source Template License. Buyer may access and use the template under the MIT License noted below in Section 2. Individual Commercial Template License. Buyer may access and use the template in applications used for their internal business or personal purposes (i.e., this license does not allow Buyer to incorporate the template in applications built for third parties). There is no limit on the number of applications the template can be used for. If a price is set, Buyer pays a one-time fee for the license which is remitted to Seller in accordance with Bubble’s Marketplace Pricing and Payment Policies. Templates under this license cannot be redistributed or resold, with or without modification. Developer Commercial Template License. Buyer may access and use the template in applications used for their internal business or personal purposes or applications built for third parties. There is no limit on the number of applications the template can be used for. Buyer pays a one-time fee for the license which is remitted to Seller in accordance with Bubble’s Marketplace Pricing and Payment Policies. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-available-open-source-licenses) 2\. Available Open Source licenses ------------------------------------------------------------------------------------------------------------------------------------------------------ MIT License. Seller makes plugin or template available to Buyer under the following terms: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-bubbles-marketplace-pricing-and-payment-policies) 3\. Bubble’s marketplace pricing and payment policies ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You are free to make templates or plugins available via the available open source licenses (i.e., make the template or plugin available free of charge under the terms in MIT’s open source license). All open source plugins and templates must be set as free in the marketplace. If you choose to use any of the Bubble Marketplace licenses listed above, the fee must be set within the applicable range below and will be subject to exceptions laid out in the Discounts & Promotions section that follows this one. Note that a template under the Individual Commercial Template License can be listed as free. * Single Use Plugin Subscription License: $1 - $100 per month. * Single Use Plugin License: $3 - $300. * Individual Commercial Template License: free or $3 - $500. * Developer Commercial Template License: $10 - $5,000. It is the user's responsibility to verify and confirm the ability of Stripe to process payments in their respective regions. Bubble cannot be held liable for any payment that cannot be processed by Stripe due to their system limitations. Bubble shall use its best efforts to execute payments, however, it is important to note that there is no guarantee of successful payment processing due to limitation of Stripe and Bubble shall be released from all payment obligations hereunder to the extent such payment cannot be processed by Stripe. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-4.-commission-structure) 4\. Commission structure ---------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-templates) 1\. Templates Bubble retains a 25% commission on all Template License payments. Bubble will accept payments on Seller’s behalf from Buyers and will remit the remainder to Seller during the subsequent month. ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-plugins) 2\. Plugins Bubble retains a 25% commission on all Plugin License payments. Bubble will accept payments on Seller’s behalf from Buyers in accordance with their billing period and will remit the remainder during the subsequent month. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-5.-discounts-and-promotions) 5\. Discounts and promotions ------------------------------------------------------------------------------------------------------------------------------------------ ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-discounts) 1\. Discounts As of May 1, 2023, Bubble is no longer activating new discounts on plugin subscriptions to verified Students and Non-Profits. However, users who activated their discount on a recurring Plugin License license fee before May 1, 2023 will continue to receive that discount until its 1-year expiration date. Users cannot combine the Student or Non-Profit discount with other discounts or credits, including those earned through the Referral or Affiliate program. Direct Users with Agency Accounts may access a Plugin License for free until the application is delivered to another Direct User, at which point this second Direct User will be responsible for fees associated with the Plugin License. Direct Users that are building templates for sale on the Bubble Marketplace may access a Plugin License for free until the template is delivered to another Direct User, at which point this second Direct User will be responsible for fees associated with the Plugin License. ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-promotions) 2\. Promotions There are currently no promotions. ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-coupons) 3\. Coupons Template coupons cannot be applied to Developer Licenses. Template coupons are only valid if the final price after applying the discount or coupon is greater than or equal to $3. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-6.-ratings-and-reviews) 6\. Ratings and reviews -------------------------------------------------------------------------------------------------------------------------------- The Bubble marketplace may allow a Buyer to submit or post materials such as comments, ratings and reviews (“Reviews”). You understand that any Review posted by you may be publicly viewable in the Bubble marketplace and on the internet. In posting, accessing or using any Reviews, you must comply with the Bubble [Acceptable Use Policy](https://bubble.io/acceptable-use-policy) . Furthermore, you may not: (a) post, modify, or remove a Review in exchange for any kind of compensation; (b) post a dishonest, abusive, harmful, misleading, or bad-faith rating or Review, (c) post personal, private or confidential information in any Review; or (d) post spam or unauthorized advertising or promotional materials in any Review. Buyer grants Bubble a worldwide, royalty-free, perpetual, nonexclusive license to use the Reviews you submit within the Bubble marketplace for the purposes of marketing the Bubble marketplace, Bubble products and services, as well as the Direct User Content associated with the Review. Bubble may also use the Reviews for other internal Bubble purposes. Apple may monitor and decide to remove or edit any submitted material, including via automated content filters and/or human review. Bubble reserves the right to monitor Reviews but does not have an obligation to do so. If Bubble becomes aware of any Review that violates the guidelines set forth in Section 1 above, Bubble may remove the Review. Bubble may also remove any Review at any time, for any reason or no reason, in its sole discretion, without notice or liability to you. Sellers acknowledge that at Bubble’s sole discretion, all Reviews associated with a User Component may be removed from a User Component, and the User Component’s rating will be reset when a Seller: (a) changes the price of User Component (by way of example, any modification from no fee to paid, paid to no fee, or any other change in the price for the User Component); (b) makes a material modification to the User Component (such as a new version or name change); or (c) transfers ownership of the User Component to any third party. Bubble may elect, in its sole discretion, to include Usage Statistics in the Bubble Marketplace and to make such Usage Statistics publicly available. “Usage Statistics” means information, statistics and analysis relating to the Bubble Marketplace, User Components, and Bubble Sites, including without limitation, the number of times a User Component is downloaded, the number of times a Bubble Site is viewed, etc. Bubble does not provide any warranty regarding the accuracy of any Usage Statistics, and all Usage Statistics are provided “As-Is”. Bubble may also elect to remove any or all Usage Statistics from any or all User Components at any time without liability. Sellers may use the Usage Statistics associated with an applicable User Component in marketing materials provided it accurately reflects User Component’s current Usage Statistics (for the avoidance of doubt, Usage Statistics may not be used for marketing purposes if a User Component’s Usage Statistics have been reset. Reviews may not be used in marketing materials unless permission from the reviewer is expressly granted. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-7.-important-notes) 7\. Important notes ------------------------------------------------------------------------------------------------------------------------ Bubble may change the pricing guidelines, commission structure, and discounts and promotions at any time, subject to the notice provisions in our Term and Conditions. Any such changes will be effective five (5) days after notice of such changes is provided for Templates and Plugins already available in the Marketplace. Bubble is not responsible or liable for fees that Sellers do not receive because of promotions, discounts, or changes in commission or pricing structure of the Marketplace. Note that all Bubble Marketplace licenses may be transferred in connection with a sale or change of control of Buyer. For the sake of clarity, this means that should a company using a Template or Plugin purchased on the Bubble Marketplace be acquired or IPO, the license will remain in effect for the surviving entity. Bubble has the right to moderate submissions to the plugin and template marketplaces to ensure they adhere to marketplace guidelines. [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-8.-marketplace-guidelines) 8\. Marketplace guidelines -------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-general-guidelines) 1\. General guidelines #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-marketplace-seller-profile) 1\. Marketplace seller profile Before submitting your work to the Marketplace, please make sure you have completed your Seller Profile page in your Bubble account under the Marketplace tab. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-customer-support) 2\. Customer support As a contributor on the Bubble Marketplace, it is your responsibility to offer assistance to users who have specific questions about your template or plugin. Therefore, please make sure you have added a Support email to your Seller Profile page. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-submission-name-and-logo) 3\. Submission name and logo The name and logo for your submission are the first things users will see when searching for a template or a plugin. It should help users quickly understand what to expect from your plugin or template and both the name and logo should be unique, clear, and in relevant to your submission content. When selecting a name and a logo, make sure to respect intellectual property; the logo should not resemble an existing logo, either of Bubble, another developer, or another entity. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-4.-submission-description) 4\. Submission description This description is an important factor for how potential purchasers determine whether or not this is the template or plugin for them, so it should be exhaustive and clear, with instructions, in English. It should give an overview of the features that users can expect, all of which should work as you describe. Instructions may be added as a link. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-5.-category-selection) 5\. Category selection When users filter the available templates and plugins with the category dropdown, your submission will appear for the categories you have chosen. You should select categories that are relevant to your submission so that interested users can find it. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-6.-resolving-errors) 6\. Resolving errors For your submission to be successful, it should fully function without any errors in your browser's console. If using Chrome, you can check for this by selecting "View" in your toolbar, "Developer," then "JavaScript Console." Any errors you see should be resolved prior to submitting. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-7.-respecting-intellectual-property) 7\. Respecting intellectual property As a marketplace creator, you are responsible for making sure that your submission does not violate another party's intellectual property and/or that you have the correct approval for using IP for commercial purposes if you are charging for the marketplace item. (This is especially relevant when connecting with 3rd party APIs.) If such a 3rd party later gives notice to Bubble of IP infringement, the marketplace item will be taken down immediately, pending investigation or resolution. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-8.-self-promotion-policy) 8\. Self-Promotion Policy As a Seller on the Bubble Marketplace, it is your responsibility to offer assistance to users who have specific questions about your template or plugin, and you are permitted to promote the templates and plugins you have made available via the Bubble Marketplace using your Seller account. However, Sellers are prohibited from using the Bubble Marketplace to market, promote, distribute, advertise, license, or sell any products or services other than the templates and plugins available on the Bubble Marketplace. To enforce this rule and make it easier to understand, we’ve put together the following guidelines: * No self-promotion. Don’t write a Review or use your Seller account for the purposes of (a) linking to your website, social media account, or third party website; or (b) posting advertisements, solicitations for a business, product or service, or public relations pieces designed to promote a company or individual. * No external links in Seller Profile pages. Your Seller profile is directly linked to your Bubble Seller account. Do not include links to third party sites or to your own website through your Seller profile. For clarity, you can and should include links for template-related documentation, support pages, free resources, or agency services offered through Bubble. * No templates for Self-Promotion. Don’t make a template where the purpose of the template is to promote your business or website. * Ask for feedback in dedicated spaces. There is a place for users of the Bubble Marketplace to leave Reviews. Do not re-direct users to any third party site or to your own site for the purposes of leaving a user review. If you violate this self-promotion policy, your Seller account may be suspended, and you may be banned from making templates and plugins available for posting on the Bubble Marketplace. ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-plugin-specific-guidelines) 2\. Plugin specific guidelines #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-plugin-demonstration) 1\. Plugin Demonstration When submitting your plugin, you'll be asked to include a "link for demonstration". Please note that it is required that this demonstration of the plugin is on a Bubble app that actually uses the plugin. Plugins should always be submitted with a fully functional demonstration application built on Bubble. This allows users to test the plugin's functionality. The demo application should include the following: * All features listed in the plugin's description * A clean and clear design * A button to view the demo application in the editor, for example, https://bubble.io/page?name=index&id=appname&tab=tabs-1. * This allows users to explore both sides and understand how the plugin works in order to set it up on their own. Its application rights in Settings —> General set to Everyone can view. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-api-keys) 2\. API Keys When using third-party connections in your plugin, please make sure all API Private Keys are private and not exposed. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-switching-from-unpaid-to-paid-for-an-existing-plugin) 3\. Switching from unpaid to paid for an existing plugin In order to switch a plugin from an open source (free) to a commercial license, you must: 1. Create a copy of the free plugin; 2. Mark the original free plugin as hidden; and 3. Publish the new copy of the plugin under a commercial license. The above actions will reset the installs, reviews and comments for the new plugin. All installs, reviews, and comments for the free plugin must be associated with the hidden free plugin. Installs, reviews, and comments associated with the new plugin must not include any installs, reviews or comments associated with the plugin when it was free. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-4.-data-and-user-privacy) 4\. Data and user privacy You may not include a pixel, cookie, web beacon, or other tracking tool or technology used for the purposes of collecting data or monitoring user activity (collectively “Tracking Tools”) in connection with any Bubble Site or User Components without disclosing use of the Tracking Tool on the Bubble \[plugin detail page\]. Such disclosure must clearly identify that Tracking Tools are used and include a link to your privacy policy, where such privacy policy must detail out the specific data collected by any Tracking Tools. You (and not Bubble) are responsible for ensuring that each user consents to use of the Tracking Tools if and as required by applicable Laws (defined in the paragraph below). You will not configure the Tracking Tools to capture any data that is not expressly identified in the privacy policy. You shall comply with all laws, ordinances, codes, regulations, rules, policies, regulations and procedures and the requirements of any other public or private authority (collectively “Laws”) applicable in the use and provision of Tracking Tools and the data collected from such Tracking Tools. You represent and warrant that data collected using the Tracking Tools has been lawfully collected pursuant to a prominent and publicly accessible privacy notice (accessible via the Bubble plugin detail page and at the point of collection) provided by You that satisfies the transparency, choice, and other requirements of all applicable Laws (including without limitation, those regarding collection, use and disclosure of data). You shall not use any Tracking Tools to: (a) transmit data that is unlawful or invasive of another’s privacy; (b) transmit data that contains software viruses or any other computer code, files or programs designed to interrupt, destroy or limit the functionality of any computer software or hardware or telecommunications equipment; (c) interfere with or disrupt the Platform or Services or networks connected to the Platform or Services; or (d) violate any applicable law or regulation. You are responsible for ensuring that You follow industry recommended security practices to ensure no security vulnerabilities are introduced into Bubble’s environment via the Tracking Tools. You will ensure that reasonable safeguards are in place to prevent unauthorized access to or use or disclosure of data collected by Tracking Tools. Bubble will have no liability to You or any third party as a result of any failure to adhere to such practices. You assume all risk and liability associated with Your use of any Tracking Tools. To the maximum extent allowed by law, You shall indemnify, defend and hold harmless Bubble and its directors, officers, employees, and agents from and against any and all claims, allegations, demands, losses, damages, suits, fees, judgments, costs, fines, and expenses, including attorneys’ fees and expenses resulting from, arising out of or relating to your use of Tracking Tools or your violation of any of your obligations relating to Tracking Tools. In addition to Bubble’s other remedies hereunder, Bubble reserves the right to suspend or terminate your access to any Bubble Site or User Components, or to terminate this agreement if you violate any of the provisions of this section. ### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-template-specific-guidelines) 3\. Template specific guidelines #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-unique-design) 1\. Unique design For your submission to be successful, your template should be distinct from existing templates, including but not limited to the Bubble Boilerplate template. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-log-in-and-sign-up-functionality) 2\. Log in and sign up functionality If your template has log in and sign up functionality, you should add a "demo login" button that signs potential users in as a demo user, for example, demo@demo.com. This allows users to test the template fully prior to purchasing without entering personal information. Templates that include multiple user roles, such as an admin user, should include a "demo login" button for each role. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-data-and-user-privacy) 3\. Data and user privacy If your live database has any live user data, this should be removed prior to submitting your template. This prevents the template from containing any private information. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-4.-plugin-demonstrations) 4\. Plugin demonstrations If your template demonstrates a plugin, it should significantly extend its functionality beyond the plugin itself. Otherwise, plugins and their demo applications should be submitted separately. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-5.-templates-with-plugins-or-custom-code) 5\. Templates with plugins or custom code If your template contains paid plugins, you should make this abundantly clear in the description, because users will need to purchase additional plugins for the template to work as expected. If your template contains custom code, this should be equally clear because of the nature of support required for custom code. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-6.-template-description) 6\. Template description Our team will test your template according to its description, so it's important to include key information such as whether or not the template a landing page versus a multi-page template. #### [](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-7.-responsiveness) 7\. Responsiveness You should make all reasonable efforts to make your template fully responsive, so that it looks good on all screen widths, especially mobile. Last updated 22 days ago Was this helpful? * [1\. Bubble’s marketplace licenses](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-bubbles-marketplace-licenses) * [2\. Available Open Source licenses](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-available-open-source-licenses) * [3\. Bubble’s marketplace pricing and payment policies](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-bubbles-marketplace-pricing-and-payment-policies) * [4\. Commission structure](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-4.-commission-structure) * [1\. Templates](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-templates) * [2\. Plugins](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-plugins) * [5\. Discounts and promotions](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-5.-discounts-and-promotions) * [1\. Discounts](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-discounts) * [2\. Promotions](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-promotions) * [3\. Coupons](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-coupons) * [6\. Ratings and reviews](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-6.-ratings-and-reviews) * [7\. Important notes](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-7.-important-notes) * [8\. Marketplace guidelines](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-8.-marketplace-guidelines) * [1\. General guidelines](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-1.-general-guidelines) * [2\. Plugin specific guidelines](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-2.-plugin-specific-guidelines) * [3\. Template specific guidelines](https://manual.bubble.io/account-and-marketplace/marketplace-policies#id-3.-template-specific-guidelines) Was this helpful? --- # Building Templates | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/account-and-marketplace/building-templates.md) . You can sell templates on [the Bubble marketplace](http://bubble.io/marketplace) . Templates come in a variety of categories, from clones of popular applications like Slack or Tinder to building blocks with login or multi-step form components. You can start building for others through the following steps. [](https://manual.bubble.io/account-and-marketplace/building-templates#define-your-seller-identity) Define your seller identity ------------------------------------------------------------------------------------------------------------------------------------ ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-MUk5eX6N5r33_5zfFRy%252F-MUk7Sw1fxqwhvN6E7Ug%252Fseller_profile.png%3Falt%3Dmedia%26token%3D0348ac10-7923-46e4-acd6-1b4fa3caca7b&width=768&dpr=3&quality=100&sign=9053c0db&sv=2) On your [account page](http://bubble.io/account) , under “Marketplace,” there’s a “Seller Profile” section where you can choose your information as you would like it to appear on your contributor profile. This includes your name, logo, website, location, bio, and support email. ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-MUk5eX6N5r33_5zfFRy%252F-MUk7_zFzYU4xWxkR5Za%252Ftransfer_.png%3Falt%3Dmedia%26token%3D6621ec0b-e4ad-4002-8944-f150c8da67ec&width=768&dpr=3&quality=100&sign=85cd6a57&sv=2) **Tip:** Remember to fill out the entirety of the Seller Profile in order for your template to be discoverable at bubble.io/templates. You can also set your preferences for when money from your template sales should be transferred to you, or whether or not you would like to receive emails from when one of your templates is bought. You will receive payouts automatically on the fifth of every month. If you choose to set a payout threshold, you will receive payouts for your plugin sales if they meet that threshold, and for your templates sales if they also meet that threshold. For example, if your payout threshold is $500 and you sell $600 worth of plugins and $200 worth of templates, you would receive the payout for plugins that month and the payout for template sales for the month after that total reaches $500. _Important:_ You will also see a button to register with Stripe. Payments to marketplace creators (sellers) are made via Stripe, so you must have a Stripe account in order to be paid. You will need to handle compliance aspects with Stripe directly. This can include providing identification and tax information. If your country is not supported by Stripe yet, you will not be able to sell on the Bubble Marketplace. This includes restrictions from Stripe such as [not allowing](https://support.stripe.com/questions/stripe-india-support-for-marketplaces) for transfers from non-India accounts to India-based accounts. [](https://manual.bubble.io/account-and-marketplace/building-templates#create-your-template) Create your template ---------------------------------------------------------------------------------------------------------------------- ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FWrMnsrokujOWQBDm2ITA%252Fimage.png%3Falt%3Dmedia%26token%3D346a8845-d2d2-4276-93a9-9df493e5c08f&width=768&dpr=3&quality=100&sign=1d2d2348&sv=2) At [bubble.io/my\_templates](http://bubble.io/my_templates) , select “New template” to get started. Give your template a name (you can change this later), and select whether or not you would like to create a new app for your template or base it off an existing one. If you use an existing app, it should have no data and be on the Free plan. Certify that you own all intellectual property rights: Templates' intellectual property is the propriety of the template owner. When adding a template to the library, as any other application, you have to comply with the [Acceptable Use Policy](https://bubble.io/acceptable-use-policy) you agreed to when you signed up for Bubble. In particular, you should own the design, logo and images' rights that you are using in your template. A template sold on Bubble should not be sold on another platform, including the design, logo, etc. Lastly, click “Create template.” You will now see your template under “My templates” as a thumbnail similar to how your applications appear at [bubble.io/home](http://bubble.io/home) . ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-MUk5eX6N5r33_5zfFRy%252F-MUk7vPYF-ITd6G8hJzP%252Fmy_templates_thumbnail.png%3Falt%3Dmedia%26token%3Db8653dc6-6550-49ee-8c77-0d4990874ac8&width=768&dpr=3&quality=100&sign=feaaca1c&sv=2) This will include the following icons: * **Edit:** Click this to open and continue developing your template. * **Submit:** When your template is finished, click here to submit to our team for approval to get published on the marketplace. * **Preview:** Once your template is published, click here to view the public details page where users can purchase it. * **Price:** Define the license for your template here and how much it costs. * **Delete:** Once a template is published, it can be subsequently removed from the marketplace, but the underlying app cannot be deleted (otherwise anybody who has already purchased the template would not be able to use it in the future). Click here to delete the template itself. [](https://manual.bubble.io/account-and-marketplace/building-templates#submit-your-template-for-marketplace-review) Submit your template for marketplace review -------------------------------------------------------------------------------------------------------------------------------------------------------------------- ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-MUk8-0R-xTXMqtdBNRf%252F-MUk82r_JkgdUTHVi5Si%252Fsubmit_template_popup.png%3Falt%3Dmedia%26token%3Dac1659b5-ec48-4f28-bd12-5df433d9280f&width=768&dpr=3&quality=100&sign=31f4fe5d&sv=2) Our team reviews all templates before they are published on the marketplace. Before you submit, check out our [marketplace guidelines](https://bubble.io/marketplace-policies) for more information on what we look for and how to get approved. Once you have reviewed the guidelines and are ready to submit, click the rocket icon. Name your template as you want it to appear publicly, and thoroughly describe what the template includes. This lets users know what to expect and also helps our team to know what to test during our review. Select the preferred license for your template, Open Source or Commercial. If you choose Open Source, buyers can access the template under the MIT license. If you choose Commercial, there is an Individual Commercial and Developer Commercial license. Under the individual license, buyers can access and use the template in applications used for their internal business or personal purposes, whereas under the developer license, buyers can use the template for their internal business or personal purposes or applications built for third parties. There is no limit on the number of applications templates can be used for. For a full definition of each of these licenses, visit [our terms](https://bubble.io/marketplace-policies) . Note that if your template is reviewed and approved by our team as Open Source, you can not then change it to Commercial, so make sure you are confident in your license prior to submitting. Once you choose your license, select the Category that’s most appropriate for your template. For example, a Facebook clone would select “Social.” Upload a screenshot for the thumbnail image that will appear on [bubble.io/templates](http://bubble.io/templates) . When you are happy with your details, click “Submit.” This sends your template to the Bubble team to review. You will receive an email from us once it has been reviewed with our feedback, typically after a couple of days. If after you submit your template you would like to make further changes, you will need to cancel the submission and then resubmit after you make the changes. [](https://manual.bubble.io/account-and-marketplace/building-templates#set-the-price-for-your-template) Set the price for your template -------------------------------------------------------------------------------------------------------------------------------------------- ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-legacy-files%2Fo%2Fassets%252F-M5sbzwG7CljeZdkntrL%252F-MRtcq8GsiXSWJxVtT8J%252F-MRti-crYYg15V-jdB18%252Fprice.png%3Falt%3Dmedia%26token%3D4a8cc4c2-113a-4f67-a130-4b62a6450e7f&width=768&dpr=3&quality=100&sign=60fb76ac&sv=2) While Open Source templates are free, if you select Commercial, you can now define its price. For Individual Commercial Template Licenses, you can set the price as free or $3 - $500. For Developer Commercial Template Licenses, you can set the price as $10 - $5,000. In this popup, you can also download your sales data for the past 30 days. When you sell a template, the total payout for the owner is 75% of the facing value. Note that this fee structure may change (but will not be applied retroactively on already published templates if a change occurs). [](https://manual.bubble.io/account-and-marketplace/building-templates#support-users-of-your-template) Support users of your template ------------------------------------------------------------------------------------------------------------------------------------------ As an owner of a template, you commit to fix issues that users that use the template may report. If a template is being reported as having issues and if no action is taken, Bubble reserves the right to withdraw the template from the marketplace. Users can (and are encouraged to) leave some reviews, feedback, and questions. You are responsible for handling questions and support requests. Failure to follow up with users that reach out (and report you to the Bubble Team) may lead to the cancellation of your Seller Profile. Last updated 2 years ago Was this helpful? * [Define your seller identity](https://manual.bubble.io/account-and-marketplace/building-templates#define-your-seller-identity) * [Create your template](https://manual.bubble.io/account-and-marketplace/building-templates#create-your-template) * [Submit your template for marketplace review](https://manual.bubble.io/account-and-marketplace/building-templates#submit-your-template-for-marketplace-review) * [Set the price for your template](https://manual.bubble.io/account-and-marketplace/building-templates#set-the-price-for-your-template) * [Support users of your template](https://manual.bubble.io/account-and-marketplace/building-templates#support-users-of-your-template) Was this helpful? --- # Sub-apps | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps.md) . Sub-applications are a powerful feature available in the Team plan. The feature sets up a relationship between a “main app” and one or more “sub-applications” and makes it easier to push any changes from the main app to its sub-apps, while all main and sub-apps have their own database. This is especially useful for certain ideas that involve setting up different (sub/)domains for different clients, which is common in SaaS applications. [](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#creating-new-sub-apps) Creating new sub-apps ---------------------------------------------------------------------------------------------------------------------------- The feature can be found in Settings > Sub-apps. There, you can create a sub-app using the current app as the main app. This will create a copy of the main app with the new name that you pick. The new sub-app will appear in your “My apps” dashboard (and will note which app is the parent), but from that point on, it generally functions as its own app. You cannot create a sub-app off of a sub app, but one main app can have multiple sub-apps. [](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#pushing-from-the-main-app-to-sub-apps) Pushing from the main app to sub-apps ------------------------------------------------------------------------------------------------------------------------------------------------------------ However, one of the main features of a sub-app is that at any time, you can “push” the current version of your main app to all of its sub-apps. Note that this will overwrite any changes made to a sub app individually. (This feature can take a relatively longer time for complex apps.) Certain settings on an app will **not** transfer from the main app to a sub-app upon a push: * **Custom domain** * **Favicon** * Admin's email * Setting to allow iframes * Language of the app * iOS meta tag icon and variations of startup images * OAuth client app and "redirected to" domain * Whether or not Sendgrid is used, Sendgrid verification and Sendgrid template ID * Setting for "Use field display instead of ID for key names" (Settings > API) * The app's public and private JSON web key (Settings > API) If you want a specific other setting to **not** propagate from the main app to a sub-app, please contact our Success team - we may be able to add a custom protection to that setting for your app. **Understanding page load times:** When you update your app, Bubble optimizes it in the background for faster future loads. After significant changes, the initial load might be slower while these optimizations occur. This delay, typically brief, won't recur until the next major update. This optimization happens separately for Development and Live, so infrequent deployments to live may make this more noticeable. [](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#main-app-vs-sub-app-databases) Main app vs sub-app databases -------------------------------------------------------------------------------------------------------------------------------------------- Sub-apps have separate databases from the main app, but can connect with the main app’s database through the App Connector just like any other app. In other words, the main app’s database will not transfer to sub-apps automatically. Default values, however, are stored in the app rather than directly in the database, so they will transfer to sub apps on a push. [](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#sub-app-subscriptions) Sub-app subscriptions ---------------------------------------------------------------------------------------------------------------------------- Each sub-app would be on its own Bubble subscription, but sub-apps do not need to be on the Team plan - only the main app does. If you have a subscription to a plugin on your main app, it would _not carry over_ to your sub-app(s) and your sub-app(s) would need to re-purchase that plugin. Last updated 2 years ago Was this helpful? * [Creating new sub-apps](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#creating-new-sub-apps) * [Pushing from the main app to sub-apps](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#pushing-from-the-main-app-to-sub-apps) * [Main app vs sub-app databases](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#main-app-vs-sub-app-databases) * [Sub-app subscriptions](https://manual.bubble.io/help-guides/optimizing-an-application/sub-apps#sub-app-subscriptions) Was this helpful? --- # Search | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/core-resources/data/search.md) . Experience level In-depth articles (12) Videos (4) This core reference entry is suited for **beginner-level builders** to **intermidiate level builders****.** Learn more about experience levels. To learn about this topic more in-depth, we recommend reading the suggested articles below: #### [](https://manual.bubble.io/core-resources/data/search#finding-data) Finding data * Article: [Finding data](https://manual.bubble.io/help-guides/data/the-database/finding-data) * * * **Data** * Article series: [Data](https://manual.bubble.io/help-guides/data) * Article: [The database](https://manual.bubble.io/help-guides/data/the-database) Understanding the Bubble database, and how to work with data. * Article: [Files](https://manual.bubble.io/help-guides/data/files) Uploading, downloading and securing files. * Article series: [Static data](https://manual.bubble.io/help-guides/data/static-data) * [App texts](https://manual.bubble.io/help-guides/data/static-data/app-texts-translations) Translating your app's static texts. * [Option sets](https://manual.bubble.io/help-guides/data/static-data/option-sets) * Article series: [Temporary data](https://manual.bubble.io/help-guides/data/temporary-data) * Article: [Custom states](https://manual.bubble.io/help-guides/data/temporary-data/custom-states) Saving data temporarily on a page or element. * Article: [URL parameters](https://manual.bubble.io/help-guides/data/temporary-data/url-parameters) Saving and reading data from the browser's URL bar. * * * #### [](https://manual.bubble.io/core-resources/data/search#dynamic-expressions) Dynamic expressions When you work with data in Bubble, you'll often be relying on dynamic expression to load, aggregate and manipulate it in different ways. The article below explains how dynamic expressions work. Article series: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) * * * #### [](https://manual.bubble.io/core-resources/data/search#the-data-tab) The Data tab The _Data_ tab in the Bubble editor is where you view and manage your app's data types and data, as well as other categories of data like files and option sets. Article: [The data tab](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/data-tab) * * * #### [](https://manual.bubble.io/core-resources/data/search#securing-the-database) Securing the database Database data is protected server-side by using privacy rules. These are conditions that are automatically applied every time a user tries to access a specific data type/field. Article: [Protecting data with privacy rules](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules) * Bubble Academy: [The Data Tab: Bubble Introduction Series \[7/10\]](https://www.youtube.com/watch?v=z0L8vFsCwkk) * Bubble Academy: [How to Add a Data Type as a Custom Field | Bubble Quick Tip](https://www.youtube.com/watch?v=4txlG9nwr1E) * Bubble Academy; [How to Instantly Modify Data With Autobinding | Bubble Quick Tip](https://www.youtube.com/watch?v=MamNYJmZjVY) * Bubble Academy: [How to Name Your Data Types & Fields | Bubble Quick Tip](https://www.youtube.com/watch?v=XueeVCReuI8) * Bubble Academy: [How to use the _Do a search for_ expression](https://www.youtube.com/watch?v=-2_3kuyOxkw) (finding data in the database) * Bubble Academy: [How to use search constraints](https://www.youtube.com/watch?v=gOjGDCJrXYI) * Bubble Academy: [How to use _Ignore empty constraints_](https://youtu.be/6VEavvd4TG4) These are the search options and operators to use when performing searches by using the `Do a search for` data source. ### [](https://manual.bubble.io/core-resources/data/search#ignore-empty-constraints) Ignore empty constraints Our Academy quick tip on how to ignore empty constraints * If this checkbox **is checked**, constraints using values evaluating to null will be ignored. In other words, if a constraint evaluates to null, all items will be returned. * If this box **is not checked**, the search will only return items whose field's value is actually null. Note that this does not apply to the Advanced filter. ### [](https://manual.bubble.io/core-resources/data/search#type) Type Select the type of things you looking for. ### [](https://manual.bubble.io/core-resources/data/search#constraints) Constraints Watch our Academy quick tip on how to use search constraints Enter the different constraints to apply to this search. Text matching in the database is limited to the first 256 characters for indexing purposes. If you need to match text longer than 256 characters in a search, consider appending a "[filtered:](https://manual.bubble.io/core-resources/data/operations-and-comparisons#filtered) " with an advanced constraint, saying "'s = ". The reason you have to do an advanced filter is that it forces the expression to load all the items out of the database and do the full string match, rather than just the first 256 characters. ### [](https://manual.bubble.io/core-resources/data/search#sorting-field) Sorting field Choose the field to sort the list. See also: [Additional sorting fields](https://manual.bubble.io/core-resources/data/search#adding-additional-sorting-rules) . **Note:** Re-sorting a repeating group will immediately change all "current cell" values in any display elements that were dynamically derived from the current cell. Specifically, if you have a popup that opened to display "Current Cell's Thing's Info", this information is linked to the cell's index; the Thing will change when the repeating group is resorted. If there are visible elements that rely on "current cell's thing" as a data source, these will be updated once the group is re-sorted. This can result in changes in elements such as popups, group focus, or reusable elements that conditionally display information about the current cell. ### [](https://manual.bubble.io/core-resources/data/search#change-which-field) **Change which field......** Watch our Academy quick tip to learn how to sort a list Select this option if you want the sorting field to be dynamic. When selected, another field will display and allow you to define the field. It can be dynamic and should match the name of an existing field. If it does not match, the application will show an error. ### [](https://manual.bubble.io/core-resources/data/search#random-sorting) **Random sorting** Choose this option to randomize the order results. The random value is unique for each user and page load. #### [](https://manual.bubble.io/core-resources/data/search#dynamic-data-and-random-sorting) Dynamic data and random sorting Once a random order is generated, it stays the same for the duration of the page session. It will only change if the page is refreshed or if the underlying data is modified, which triggers the search (and its sorting) to run again. **Example 1:** * A search for colors (random sorting) returns: red, yellow, green * A field on “red” is updated (_Make changes to_ action) * Re-running the search may produce a new order, e.g. yellow, green, red **Example 2:** * A search for colors (random sorting) returns: red, yellow, green * A new “blue” thing is created (_Create a new thing_ action) * Re-running the search may produce a new order, e.g. red, blue, green, yellow This principle applies to all sorting types: results remain stable as long as the underlying data does not change. Any update or addition causes the search to re-execute and the ordering to be recalculated. ### [](https://manual.bubble.io/core-resources/data/search#unsorted) Unsorted Choose this option to return results without applying any sort order. This can improve performance, especially in larger databases when using the _text contains_ operator. This is available in the editor database custom views, but not yet rolled out to all the run-mode operators. ### [](https://manual.bubble.io/core-resources/data/search#dynamic-field-name) Dynamic field name If you want the search to be sorted according to a field chosen by the user, define an expression to define which field the search should use. For instance, the expression you design here should evaluate to 'Created Date' or some other fields you have defined in your type (it should match the displayed name of the field). ### [](https://manual.bubble.io/core-resources/data/search#distance-from) Distance from When sorting on a location field, results will be sorted by distance relative to a point. This field defines which point. Current position, an address, etc. ### [](https://manual.bubble.io/core-resources/data/search#descending) Descending Choose 'yes' to sort in descending order or 'no' to sort in ascending order. This option can be dynamic and defines an expression that returns a yes/no, e.g., a checkbox element. ### [](https://manual.bubble.io/core-resources/data/search#adding-additional-sorting-rules) Adding additional sorting rules When you need more than one sorting rule, click this button and select a field and a descending/ascending order for that field. The rules will be applied in the order listed. ### [](https://manual.bubble.io/core-resources/data/search#any-field) Any field Performs a search across all the fields of the application database for a given type. For example, search for all entries with John as a first OR last name. ### [](https://manual.bubble.io/core-resources/data/search#advanced) Advanced Performs more advanced searches. For example, to find all apartments whose creators have an email hosted by yahoo.com, use 'This apartment's creator's email:extract domain is 'yahoo.com.' This operation happens after the search or list is retrieved from the server and is not as efficient as using constraints on a search. Last updated 3 months ago Was this helpful? * [Ignore empty constraints](https://manual.bubble.io/core-resources/data/search#ignore-empty-constraints) * [Type](https://manual.bubble.io/core-resources/data/search#type) * [Constraints](https://manual.bubble.io/core-resources/data/search#constraints) * [Sorting field](https://manual.bubble.io/core-resources/data/search#sorting-field) * [Change which field......](https://manual.bubble.io/core-resources/data/search#change-which-field) * [Random sorting](https://manual.bubble.io/core-resources/data/search#random-sorting) * [Unsorted](https://manual.bubble.io/core-resources/data/search#unsorted) * [Dynamic field name](https://manual.bubble.io/core-resources/data/search#dynamic-field-name) * [Distance from](https://manual.bubble.io/core-resources/data/search#distance-from) * [Descending](https://manual.bubble.io/core-resources/data/search#descending) * [Adding additional sorting rules](https://manual.bubble.io/core-resources/data/search#adding-additional-sorting-rules) * [Any field](https://manual.bubble.io/core-resources/data/search#any-field) * [Advanced](https://manual.bubble.io/core-resources/data/search#advanced) Was this helpful? --- # Native mobile apps | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/beta-features/native-mobile-apps.md) . The native mobile app builder is now in **public beta**, and its documentation has been moved into the main User Manual and Core Reference. You can explore it in the introductory article series below: Article: [Building for Native iOS and Android](https://manual.bubble.io/help-guides/getting-started/building-for.../native-ios-and-android) Last updated 1 year ago Was this helpful? Was this helpful? --- # Building Plugins | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/account-and-marketplace/building-plugins.md) . Plugins extend Bubble's functionality and add new API connections, elements and actions to Bubble. You can build plugins for the benefit of the Community, or build private plugins if you need to write custom code for your applications. This section covers the different plugin types you can build and how publishing works. System hard limits[](https://manual.bubble.io/account-and-marketplace/building-plugins#system-hard-limits) When creating plugins for Bubble, it's important to be mindful of the Bubble's hard system limits. These constraints for plugin development mirror those present in general Bubble development. The article below covers this subject: Article: [Hard limits](https://manual.bubble.io/help-guides/maintaining-an-application/performance-and-scaling/hard-limits) [The Plugin Editor](https://manual.bubble.io/account-and-marketplace/building-plugins/the-plugin-editor) [General Settings](https://manual.bubble.io/account-and-marketplace/building-plugins/general-settings) [Adding API Connections](https://manual.bubble.io/account-and-marketplace/building-plugins/adding-api-connections) [Building Elements](https://manual.bubble.io/account-and-marketplace/building-plugins/building-elements) [Building Actions](https://manual.bubble.io/account-and-marketplace/building-plugins/building-actions) [Loading Data](https://manual.bubble.io/account-and-marketplace/building-plugins/loading-data) [Publishing and versioning](https://manual.bubble.io/account-and-marketplace/building-plugins/publishing-and-versioning) [Github Integration](https://manual.bubble.io/account-and-marketplace/building-plugins/github-integration) Last updated 1 year ago Was this helpful? Was this helpful? --- # About the Beta features section | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/beta-features/about-the-beta-features-section.md) . This section highlights features that are currently in beta testing. These features are not yet released to the public and may still contain bugs. Access to beta features is limited, so not all users may have access at this time. Your feedback is valuable in helping us improve these features before their official release. Last updated 22 days ago Was this helpful? Was this helpful? --- # Privacy | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/core-resources/data/privacy.md) . Experience level In-depth articles (13) Videos (4) Books (1) This core reference entry is suited for **intermidiate level builders****.** Learn more about experience levels. To learn about this topic more in-depth, we recommend reading the suggested articles below: #### [](https://manual.bubble.io/core-resources/data/privacy#privacy-rules) Privacy rules * Article: [Protecting data with privacy rules](https://manual.bubble.io/help-guides/data/the-database/protecting-data-with-privacy-rules) * * * **Data** * Article series: [Data](https://manual.bubble.io/help-guides/data) * Article: [The database](https://manual.bubble.io/help-guides/data/the-database) Understanding the Bubble database, and how to work with data. * Article: [Files](https://manual.bubble.io/help-guides/data/files) Uploading, downloading and securing files. * Article series: [Static data](https://manual.bubble.io/help-guides/data/static-data) * [App texts](https://manual.bubble.io/help-guides/data/static-data/app-texts-translations) Translating your app's static texts. * [Option sets](https://manual.bubble.io/help-guides/data/static-data/option-sets) * Article series: [Temporary data](https://manual.bubble.io/help-guides/data/temporary-data) * Article: [Custom states](https://manual.bubble.io/help-guides/data/temporary-data/custom-states) Saving data temporarily on a page or element. * Article: [URL parameters](https://manual.bubble.io/help-guides/data/temporary-data/url-parameters) Saving and reading data from the browser's URL bar. * * * #### [](https://manual.bubble.io/core-resources/data/privacy#dynamic-expressions) Dynamic expressions When you work with data in Bubble, you'll often be relying on dynamic expression to load, aggregate and manipulate it in different ways. The article below explains how dynamic expressions work. Article series: [Dynamic expressions](https://manual.bubble.io/help-guides/logic/dynamic-expressions) * * * #### [](https://manual.bubble.io/core-resources/data/privacy#the-data-tab) The Data tab The _Data_ tab in the Bubble editor is where you view and manage your app's data types and data, as well as other categories of data like files and option sets. Article: [The data tab](https://manual.bubble.io/help-guides/getting-started/navigating-the-bubble-editor/tabs-and-sections/data-tab) * * * #### [](https://manual.bubble.io/core-resources/data/privacy#the-bubble-api-and-security) The Bubble API and security We also have an extensive article series on the **Bubble API**, which explores Bubble's API capabilities and security features in-depth: Article series: [The Bubble API](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api) * Bubble Academy: [The Data Tab: Bubble Introduction Series \[7/10\]](https://www.youtube.com/watch?v=z0L8vFsCwkk) * Bubble Academy: [How to Add a Data Type as a Custom Field | Bubble Quick Tip](https://www.youtube.com/watch?v=4txlG9nwr1E) * Bubble Academy; [How to Instantly Modify Data With Autobinding | Bubble Quick Tip](https://www.youtube.com/watch?v=MamNYJmZjVY) * Bubble Academy: [How to Name Your Data Types & Fields | Bubble Quick Tip](https://www.youtube.com/watch?v=XueeVCReuI8) * Bubble Academy: [How to use the _Do a search for_ expression](https://www.youtube.com/watch?v=-2_3kuyOxkw) (finding data in the database) * Bubble Academy: [How to use search constraints](https://www.youtube.com/watch?v=gOjGDCJrXYI) * Bubble Academy: [How to use _Ignore empty constraints_](https://youtu.be/6VEavvd4TG4) * [The Ultimate Guide to Bubble Security](https://www.amliesolutions.com/books/the-ultimate-guide-to-bubble-security/) by Petter Amlie **Security note:** Although this section is categorized for intermediate-level builders, it's crucial to emphasize that privacy rules are the primary security measure for your app. We highly recommend that all users understand how these rules work and never deploy an app containing sensitive data without implementing proper privacy rules. This section of the _Data_ tab provides security by allowing you to define rules to prevent users from seeing or modifying data they should not have access to. To do this, define rules for each of your custom types, if needed. When multiple rules apply, the user has access to an object if any one rule grants access to it. ### [](https://manual.bubble.io/core-resources/data/privacy#define-a-new-rule) Define a new rule This button creates a new rule for the selected type. Name the type with an explicit name and define conditions and permissions. The condition defines which users this rule applies to, while the permissions define what they can do with the data if they meet the conditions. ### [](https://manual.bubble.io/core-resources/data/privacy#name) Name Name the rule. Modify the name in this input. ### [](https://manual.bubble.io/core-resources/data/privacy#delete) Delete Clicking this icon deletes the rule. This action does not delete data. It only removes the rule for the selected type. ### [](https://manual.bubble.io/core-resources/data/privacy#when-condition) When (condition) Define the conditions that check whether a given user is part of the rule or not. Create a dynamic expression with the Composer, building it piece by piece. For example, if you define the condition for the type 'Event' as 'This event's creator is current user,' then only the user who created the thing of type 'event' will be part of that rule. ### [](https://manual.bubble.io/core-resources/data/privacy#permissions) Permissions This defines what users in that current rule can do with the data. ### [](https://manual.bubble.io/core-resources/data/privacy#find-this-in-searches) **Find this in searches** Uncheck this box to prevent users who are in this rule to see the search results for this type. ### [](https://manual.bubble.io/core-resources/data/privacy#view-all-fields) **View all fields** Check this box for these users to be able to see all the fields of a thing of the current type, provided they meet the conditions. If you uncheck this box, you will be able to select which fields are viewable by users in this rule. ### [](https://manual.bubble.io/core-resources/data/privacy#view-attached-files) **View attached files** If this box is unchecked, users will not be able to see the uploaded files attached to a thing of this type. For example, let's say you set up a workflow where users can create an 'Apartment,' and that apartment has pictures. Set up the picture uploader in a way that links the picture to the actual apartment in the database. Then, if you uncheck this box and if the condition is 'This apartment's creator isn't current user,' other users will not be able to see that picture, even if an image displays it or if a user has a link to the image file. ### [](https://manual.bubble.io/core-resources/data/privacy#allow-auto-binding) **Allow auto-binding** Bind the content of an input to a field of a thing. When the user modifies the content of the input, the thing gets updated automatically. See [Enable auto-binding on parent element's thing](https://manual.bubble.io/core-resources/elements/input-forms#Elements.GeneralInput.auto_binding) for input elements. You need to enable users to modify fields through a permission. Use 'Allow auto-binding.' Check this box to allow users to do this if they meet a condition. Once checked, choose from the different fields that can be modified through auto-binding. ### [](https://manual.bubble.io/core-resources/data/privacy#modify-via-api) **Modify via API** When the Data API is enabled for this type, this permission grants the user the right to modify any of the fields of this thing. For the modification to be allowed, the rule that governs this permission must be true both before and after the modification. This lets you restrict which fields may be modified. If you need more granular field restrictions, instead of granting this permission, use the Workflow API, which lets you control exactly what gets changed. ### [](https://manual.bubble.io/core-resources/data/privacy#delete-via-api) **Delete via API** When the Data API is enabled for this type, this permission grants the user the right to delete this thing via the API. ### [](https://manual.bubble.io/core-resources/data/privacy#create-via-api) **Create via API** When the Data API is enabled for this type, this permission grants the user the right to create new things via the API. If the rule that grants this permission references fields on the thing, attempts to create a thing where the rule does not apply will be rejected. ### [](https://manual.bubble.io/core-resources/data/privacy#note-modifying-data-in-the-middle-of-a-workflow) Note: Modifying data in the middle of a workflow If you have an element that displays data only to certain users, that data could be briefly displayed to a user that does not have permissions if this user triggers a workflow that you as a developer have defined to modify that piece of private data and if the modification does not need to come from the server or a remote source such as an external API. Fortunately, we have a feature for this use case. See [Scheduled Workflows](https://manual.bubble.io/help-guides/integrations/api/the-bubble-api/the-workflow-api/api-workflows/scheduling-api-workflows) . Last updated 2 years ago Was this helpful? * [Define a new rule](https://manual.bubble.io/core-resources/data/privacy#define-a-new-rule) * [Name](https://manual.bubble.io/core-resources/data/privacy#name) * [Delete](https://manual.bubble.io/core-resources/data/privacy#delete) * [When (condition)](https://manual.bubble.io/core-resources/data/privacy#when-condition) * [Permissions](https://manual.bubble.io/core-resources/data/privacy#permissions) * [Find this in searches](https://manual.bubble.io/core-resources/data/privacy#find-this-in-searches) * [View all fields](https://manual.bubble.io/core-resources/data/privacy#view-all-fields) * [View attached files](https://manual.bubble.io/core-resources/data/privacy#view-attached-files) * [Allow auto-binding](https://manual.bubble.io/core-resources/data/privacy#allow-auto-binding) * [Modify via API](https://manual.bubble.io/core-resources/data/privacy#modify-via-api) * [Delete via API](https://manual.bubble.io/core-resources/data/privacy#delete-via-api) * [Create via API](https://manual.bubble.io/core-resources/data/privacy#create-via-api) * [Note: Modifying data in the middle of a workflow](https://manual.bubble.io/core-resources/data/privacy#note-modifying-data-in-the-middle-of-a-workflow) Was this helpful? --- # Vulnerability Disclosure Policy | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/vulnerability-disclosure-policy.md) . [](https://manual.bubble.io/vulnerability-disclosure-policy#h_d31287ef19) Introduction ------------------------------------------------------------------------------------------- Bubble Group, Inc. (“**Bubble**” “**we**” or “**us**”) welcomes feedback from security researchers and the general public to help improve our security. If you believe you have discovered a vulnerability, privacy issue, exposed data, or other security issues in any of our assets, we want to hear from you. This policy outlines steps for reporting vulnerabilities to us, what we expect, and what you can expect from us. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_74553012c6) Scope ------------------------------------------------------------------------------------ This policy applies to any digital assets owned, operated, or maintained by Bubble, including: * Public-facing websites * Bubble hosting platform * Bubble-developed software The types of vulnerabilities that are in scope are those that could impact all or a substantial number of applications hosted by Bubble. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_a5d852e043) Out of Scope ------------------------------------------------------------------------------------------- All Bubble assets that are not explicitly listed within the scope of this policy should be considered out of scope. Examples of out-of-scope assets include: * 3rd-party plugins not developed by Bubble Vulnerabilities discovered or suspected in out-of-scope systems should be reported to the appropriate vendor, application owner, or applicable authority. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_ecd2628656) Prohibited Activities ---------------------------------------------------------------------------------------------------- The following activities are always prohibited and out of scope of this policy: * Social engineering (phishing, vishing, etc.) * Physical attacks * Denial of service (DoS/DDos) * Use of automated scanners/tools, or other methods that may impact system availability * Attacks that are noisy to users or admins (e.g., spamming, notifications, or forms) * Knowingly posting, transmitting, uploading, linking to, or sending malware If you discover specific Bubble applications that are being used to engage in potentially disruptive, malicious or abusive activities, please submit an [abuse report](https://bubble.io/report-abuse) . [](https://manual.bubble.io/vulnerability-disclosure-policy#h_a2175e00cf) Our Commitments ---------------------------------------------------------------------------------------------- * Respond to your report promptly, and work with you to understand and validate your report; * Strive to keep you informed about the progress of a vulnerability as it is processed; * Work to remediate discovered vulnerabilities in a timely manner, within our operational constraints and internal support SLAs; and * Extend Safe Harbor for vulnerability research that is related to this policy. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_a28d3b9d38) Official Channels ------------------------------------------------------------------------------------------------ Please use [security@bubble.io](mailto:security@bubble.io) to report security issues, providing all relevant information. The more details you provide, the easier it will be for us to triage and fix the issue. Relevant information to provide includes: * Instructions and resources to validate the vulnerability: * Specific assets in scope (e.g., URLs to specific in-scope systems) * Pre-conditions or assumptions made in order to exploit the vulnerability (e.g., an authenticated user, software version, system configuration) * Instructions for validating the vulnerability, identifying any tools and methods used * Source code, scripts, and relevant technical configurations * Proof of concept: * Video recording showing how the vulnerability was exploited and its resulting impact. When you submit a report via our official channel, you will be provided with a tool to provide a screen recording with audio. By using this feature, you consent to such recording. * Output files and screen shots **We expect that the relevant information will be uploaded via the specified Official Channels and not hosted on external sites.** If there are valid technical reasons that prevent the uploading of relevant information, we may agree to other methods. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_94774b5b05) Our Expectations ----------------------------------------------------------------------------------------------- * Play by the rules, including following this policy and any other relevant agreements. If there is any inconsistency between this policy and any other applicable terms, the terms of this policy will prevail; * Report any vulnerability you’ve discovered promptly; * System activities are solely for purposes of good-faith testing and investigation of security flaws or vulnerabilities; * Avoid violating the privacy of others, disrupting our systems, destroying data, and/or harming user experience; * Use only the Official Channels to discuss vulnerability information with us; * Provide us a reasonable amount of time to resolve the issue; * Keep the details of any discovered vulnerabilities confidential until we have confirmed that the issue has been resolved and we have agreed to public disclosure; * Perform testing only on in-scope systems, and respect systems and activities which are out-of-scope; * If a vulnerability provides unintended access to data: Limit the amount of data you access to the minimum required for effectively demonstrating a Proof of Concept; and cease testing and submit a report immediately if you encounter any user data during testing, such as Personally Identifiable Information (PII), Personal Healthcare Information (PHI), credit card data, or proprietary information; * Any user data encountered during testing must be kept strictly confidential and never publicly disclosed; * You should only interact with test accounts you own or with explicit permission from the account holder; and * Do not engage in extortion. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_6e41976852) Safe Harbor ------------------------------------------------------------------------------------------ We consider activities conducted consistent with this policy to constitute “authorized” access under applicable law. While we cannot bind law enforcement or third parties, we commit to advocating on your behalf if legal issues arise from good faith security research conducted under this policy. Please submit reports through our Official Channels before engaging in conduct that may be inconsistent with or unaddressed by this policy. If in doubt, contact us first. [](https://manual.bubble.io/vulnerability-disclosure-policy#h_f2f400b3b9) Rewards -------------------------------------------------------------------------------------- We do not currently offer a formal bug bounty or financial rewards for vulnerability disclosure. However, we offer recognition on our [Security Acknowledgement Page](https://bubble.io/security_acknowledgements) for significant findings. “Significant findings” include those that we have verified, have not already been reported to us, result in a security improvement to our product or platform, and were submitted according to this Vulnerability Disclosure Policy, as determined by us in our sole discretion. Last updated 22 days ago Was this helpful? * [Introduction](https://manual.bubble.io/vulnerability-disclosure-policy#h_d31287ef19) * [Scope](https://manual.bubble.io/vulnerability-disclosure-policy#h_74553012c6) * [Out of Scope](https://manual.bubble.io/vulnerability-disclosure-policy#h_a5d852e043) * [Prohibited Activities](https://manual.bubble.io/vulnerability-disclosure-policy#h_ecd2628656) * [Our Commitments](https://manual.bubble.io/vulnerability-disclosure-policy#h_a2175e00cf) * [Official Channels](https://manual.bubble.io/vulnerability-disclosure-policy#h_a28d3b9d38) * [Our Expectations](https://manual.bubble.io/vulnerability-disclosure-policy#h_94774b5b05) * [Safe Harbor](https://manual.bubble.io/vulnerability-disclosure-policy#h_6e41976852) * [Rewards](https://manual.bubble.io/vulnerability-disclosure-policy#h_f2f400b3b9) Was this helpful? --- # Application and data ownership | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership.md) . **Disclaimer:** This page is provided for informational purposes only. In the event of any discrepancies between the content here and the official terms of use or other legal documents found on our [legal terms page](https://bubble.io/terms) , the official terms of use and legal documents prevail. [](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership#intellectual-property-ownership) Intellectual property ownership -------------------------------------------------------------------------------------------------------------------------------------------------------- Simply put, you have ownership over your data, encompassing both your app's design and any data uploaded by your users (based on the agreement you have with them). On the other hand, Bubble retains ownership of the underlying code that powers your app. Think of it like how Microsoft owns the software Microsoft Word, but doesn't claim ownership over the documents you create with it. [](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership#exporting-your-application-and-data) Exporting your application & data -------------------------------------------------------------------------------------------------------------------------------------------------------------- We support automatically exporting user-created data in the form of CSV files. Additionally, with the Bubble API, you can craft scripts for a more automated, scalable way to access your data. Bubble apps can only be run on the Bubble platform; there's no way of exporting your application as code. If you decide to move off the Bubble platform, you'll have to rebuild the application logic, although we can help you export the design. We'll do our best to help you leave if you want to. Our goal, though, is for Bubble to grow with your app. As Bubble is built on Javascript and can be extended with code and API integrations, you'll essentially never hit a hard limit of the system. Our Enterprise plan lets you have a dedicated cluster only for your apps, maintained by us, and you can scale as your business grows independently from other Bubble applications. Your trust in Bubble is paramount. While we're committed to a lasting presence, we guarantee that, in the unlikely event of discontinuation, Bubble's source code will be made available under an open-source license. This ensures you can maintain your app on a self-hosted Bubble server. Last updated 2 years ago Was this helpful? * [Intellectual property ownership](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership#intellectual-property-ownership) * [Exporting your application & data](https://manual.bubble.io/account-and-marketplace/application-and-data-ownership#exporting-your-application-and-data) Was this helpful? --- # Bug reports | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/account-and-marketplace/bug-reports.md) . [](https://manual.bubble.io/account-and-marketplace/bug-reports#filing-a-bug-report) Filing a bug report ------------------------------------------------------------------------------------------------------------- Bubble is a powerful and flexible platform that supports millions of apps, each with its own unique setup and requirements. While we work hard to test features thoroughly—through internal reviews, beta programs, and release checks—bugs can still occur from time to time. That’s why user-reported bug reports are so important. They help us identify and resolve issues more quickly, contributing to a more stable experience for everyone. We truly appreciate the time and effort you and the community put into sharing detailed reports—they play a key role in keeping the platform reliable for all builders. [](https://manual.bubble.io/account-and-marketplace/bug-reports#before-submitting-a-bug-report) Before submitting a bug report ----------------------------------------------------------------------------------------------------------------------------------- To ensure an efficient handling of cases and to help us solve your problem as fast as we can, we encourage you to keep in mind the points below: * **Reproduce the issue:** Ensure the problem is consistent and not a one-time occurrence. * **Check the Bubble status page:** Bubble has a [status page](https://status.bubble.io/) that shows you if a server is having any known issues. You can also subscribe to issue alerts from the status page by clicking _Subscribe to updates_. Bubble's status is also visible in the AI chatbot (see [below](https://manual.bubble.io/account-and-marketplace/bug-reports#chatbot-steps) ). * **Check the docs:** Verify if the observed behavior isn't the intended one. You can also ask a question in the [forum](https://forum.bubble.io/) . * **Eliminate external factors:** If using plugins or third-party integrations, disable them temporarily to see if they are the cause. Also check your browser for ad- and or script blockers that may cause issues. [](https://manual.bubble.io/account-and-marketplace/bug-reports#what-makes-a-good-bug-report) What makes a good bug report ------------------------------------------------------------------------------------------------------------------------------- * **What you expected to happen** Describe the intended behavior. This helps us understand what should have occurred under normal conditions. * **What actually happened** Be specific about the unexpected behavior you observed. If something broke, describe exactly how. * **Step-by-step instructions to reproduce the issue** Outline the exact steps we need to take to see the bug for ourselves. Assume the person reading has no prior knowledge of your app. **User/credentials:** If the behavior depends on the app being run by a specific user, include the user’s email or the credentials we should use to log in as that user. * **A link to the relevant part of your app** If you're comfortable sharing it, include a link to the editor or run-mode version where the bug appears. Include names of pages/views/elements/workflows. * **Browser and device details** Let us know what browser and operating system you're using, including version numbers. This helps us rule out environment-specific issues. If this is related to a mobile app, please include build details. * **Any recent changes** If you’ve made changes to your app recently (e.g., new plugins, workflows, or design updates), note them. These details can sometimes point us to the source of the issue. * **Console errors:** If you know how to use the browser's console, inspect it for any related errors. * **When the error occurred:** Include when the behavior started, noting the date, time, and timezone of the first and most recent occurrences, as well as any changes made just before it first appeared. * **Mobile apps:** * Include build details in your bug report. * Specify whether the behavior occurs in Web Preview, BubbleGo, TestFlight or internal testing, and/or the published app. * If you encounter an issue in a build distributed through internal testing or after publishing, include a download link. * If the error appears in BubbleGo, confirm that you’re using the latest version. Checking console errors[](https://manual.bubble.io/account-and-marketplace/bug-reports#checking-console-errors) #### [](https://manual.bubble.io/account-and-marketplace/bug-reports#accessing-the-console) Accessing the console Most browsers include built-in developer tools that let you view console errors, which are often essential for diagnosing unexpected behavior in your app. Here’s how to open the console in the most commonly used browsers: **Chrome/Brave** Right-click anywhere on the page and select _Inspect_, then open the _Console_ tab. You can also press _Ctrl+Shift+J_ (Windows/Linux) or _Cmd+Option+J_ (Mac). **Firefox** Open the menu and choose _More Tools → Web Developer Tools_, then select the _Console_ tab. You can also press _Ctrl+Shift+K_ (Windows/Linux) or _Cmd+Option+K_ (Mac). **Safari** First enable the Develop menu by going to _Safari → Settings → Advanced_ and checking _“Show Develop menu in menu bar.”_ Then open _Develop → Show JavaScript Console_ or press _Cmd+Option+C_. **Edge** Right-click the page and choose _Inspect_, then select the _Console_ tab. You can also press _Ctrl+Shift+I_, then click _Console_, or go directly with _Ctrl+Shift+J_. #### [](https://manual.bubble.io/account-and-marketplace/bug-reports#exporting-the-log) Exporting the log **Screenshot** For most cases, a screenshot is the fastest and clearest way to share console errors. It captures the exact messages, their severity (error/warning), and any context visible in the surrounding UI. This is ideal if there are just a few errors. **Exporting or copy/pasting the log** If there are many errors or long logs, copying the text directly is more readable and easier for both you and our team to search through. * Right-click inside the console and choose **“Save as…”** or **“Copy”** (varies by browser) * Paste it into your bug report or attach it as a `.txt` file This is useful if there are multiple errors and/or you want us to search for specific information. [](https://manual.bubble.io/account-and-marketplace/bug-reports#how-to-file-a-bug-report-to-bubble) How to file a bug report to Bubble ------------------------------------------------------------------------------------------------------------------------------------------- Bug reports are submitted through the AI chatbot in the bottom right corner of your screen. Look for this symbol: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252FZ7VOrVHLL3of46zcST8E%252Fchatbot%25402x.png%3Falt%3Dmedia%26token%3D48551b42-3401-44cf-bb97-cdadfc5d485a&width=768&dpr=3&quality=100&sign=5b53824a&sv=2) ### [](https://manual.bubble.io/account-and-marketplace/bug-reports#chatbot-steps) Chatbot steps 1. Click the chatbot symbol to expand the chat window. 2. You will see a window that shows the current operational status of Bubble. 3. Use the chat input to express that you want to report a bug. 4. You will be asked to provide your app's app id. You will find this in the URL of the tab where you have the editor open, for example `id=my-app-id`. 5. You can provide a text description of the issue. We encourage you to follow the advise in the _What makes a good bug report section._ You can also attach files (such as a screenshot) to help us identify the issue. 6. The bug report is submitted. You can still add further details after this step if you need to. [](https://manual.bubble.io/account-and-marketplace/bug-reports#what-to-expect-after-submitting-a-bug-report) What to expect after submitting a bug report --------------------------------------------------------------------------------------------------------------------------------------------------------------- First, let's look at how bug reports are handled: Work hours Bubble's bug report and support team is active **24/7** Normal response time Bug reports will receive a response within **2 hours on average.** Response The response is sent back via the **chatbot**, and the **email address** associated with your Bubble account. ### [](https://manual.bubble.io/account-and-marketplace/bug-reports#when-are-bugs-fixed) When are bugs fixed? It's difficult to set an exact timeline for when a bug is fixed, for a few reasons: * **Severity and impact vary:** Some bugs affect only a small number of users, while others may have broader consequences. More critical issues are prioritized accordingly. * **Reproducibility:** Bugs that are easy to reproduce can often be addressed faster. If a bug is inconsistent or difficult to replicate, it may take longer to diagnose. * **Complexity of the underlying cause:** Some bugs can be traced to a simple fix, while others may reveal deeper issues that require more time to resolve safely. * **Need for testing:** Even after a fix is identified, it must be thoroughly tested to ensure it doesn't introduce new problems elsewhere in the platform. * **Release process:** In some cases, fixes must wait for a scheduled deployment window, especially if they involve changes to core infrastructure or systems. * **When it's not a bug:** Some issues may turn out to be expected behavior rather than actual bugs. When that happens, we’ll do our best to explain how the feature is designed to work and offer guidance or possible workarounds to help you move forward. Last updated 22 days ago Was this helpful? * [Filing a bug report](https://manual.bubble.io/account-and-marketplace/bug-reports#filing-a-bug-report) * [Before submitting a bug report](https://manual.bubble.io/account-and-marketplace/bug-reports#before-submitting-a-bug-report) * [What makes a good bug report](https://manual.bubble.io/account-and-marketplace/bug-reports#what-makes-a-good-bug-report) * [How to file a bug report to Bubble](https://manual.bubble.io/account-and-marketplace/bug-reports#how-to-file-a-bug-report-to-bubble) * [Chatbot steps](https://manual.bubble.io/account-and-marketplace/bug-reports#chatbot-steps) * [What to expect after submitting a bug report](https://manual.bubble.io/account-and-marketplace/bug-reports#what-to-expect-after-submitting-a-bug-report) * [When are bugs fixed?](https://manual.bubble.io/account-and-marketplace/bug-reports#when-are-bugs-fixed) Was this helpful? --- # Using the core reference | Bubble Docs For the complete documentation index, see [llms.txt](https://manual.bubble.io/llms.txt) . This page is also available as [Markdown](https://manual.bubble.io/core-resources/using-the-core-reference.md) . Welcome to the core reference section of the Bubble docs. The core reference is a focused, technical resource that provides information about all properties, settings, and technical details within Bubble. It's organized into feature categories, such as interface, elements, workflows and styles, and you can navigate the different sections using the panel on the left-hand side of the page. The core reference is the short-form technical documentation describing each Bubble feature. If you are looking for more in-depth and long-form articles to learn Bubble, you may be interested in checking the [Bubble Manual](https://manual.bubble.io/help-guides/getting-started) . In the Bubble docs introduction we also [list other resources](https://manual.bubble.io/#other-learning-resources) such as videos, user community and interactive tutorials. [](https://manual.bubble.io/core-resources/using-the-core-reference#help-available-in-the-bubble-editor) Help available in the Bubble editor ------------------------------------------------------------------------------------------------------------------------------------------------- ### [](https://manual.bubble.io/core-resources/using-the-core-reference#documentation-links) Documentation links In the Bubble editor, you'll see links when you hover different features that will take you directly to the right section: ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252F8CSrB10UEypWYbUyj5vt%252Fdirect-reference-link%25402x.png%3Falt%3Dmedia%26token%3Dfb817104-3ee9-483a-ac73-8936f3e78837&width=768&dpr=3&quality=100&sign=dac64ff&sv=2) Hovering a setting or property in Bubble reveals a link to the core reference entry for that setting. ### [](https://manual.bubble.io/core-resources/using-the-core-reference#in-editor-videos) In-editor videos Some features and objects also have a video tutorial available directly in the editor. You'll recognize them by the video symbol in the top-right corner. These videos are also available in our searchable [Youtube channel](https://www.youtube.com/@BubbleIO) . ![](https://manual.bubble.io/~gitbook/image?url=https%3A%2F%2F34394582-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252F-M5sbzwG7CljeZdkntrL%252Fuploads%252Fjgsn31SfW1uI5855S16j%252Fin-editor-video-bubble%25402x.png%3Falt%3Dmedia%26token%3Daddbf0e1-95d1-4b76-a8dc-d66b63df4c71&width=768&dpr=3&quality=100&sign=68aa580b&sv=2) Last updated 22 days ago Was this helpful? * [Help available in the Bubble editor](https://manual.bubble.io/core-resources/using-the-core-reference#help-available-in-the-bubble-editor) * [Documentation links](https://manual.bubble.io/core-resources/using-the-core-reference#documentation-links) * [In-editor videos](https://manual.bubble.io/core-resources/using-the-core-reference#in-editor-videos) Was this helpful? ---