Modularity in Bubble

For the sake of modularity, what if I drop ALL of my workflows in a Reusable group or push them to Backend Workflows.

Would this be smart? :eyes:

Hey @bestbubbledev,

Mostly replying to not miss the comments …

I started moving my workflows to the backend because of the mobile editor (having the same workflows for web and mobile). I guess if you have a web AND mobile app this becomes necessary to ensure being synced between both - plus, no double work.

I also realized I have a lot of actions that run stand-alone as well as part of larger workflows. I decided to break them down in small modular workflows that trigger each other if necessary. That way I can ensure everything is just built once and I can easily reuse workflows when I build something new.

Does that make sense?

*I am still in the process and can’t tell yet if it’s a good idea or not

2 Likes

in traditional development, you don’t keep any CRUD operations or any heavy computation in FE ( where is user’s browser )

When u do in BE u use cluster instance CPU and MEM so I/O is more reliable and fast ofc.

For one of our modules ( app ), we use bubble as FE only, all logic sits in NodeJS + AWS

but ofc it would be smart, you can make a lot WFs as utils and reuse them for others logics, keeping dry ur app.

Some considerations on this:

  • You need to keep some rationale on grouping workflows together in a reusable element. Otherwise they’ll turn into a jumble.
  • If workflows are only used in one place, moving them to a RE will slow down your navigation in Bubble editor.
  • If moved to backend, you’ll have to deal with possible delays on whatever workflow result you are expecting the frontend to show.
  • Most important, moving workflows to backend implies, at least some, increase on WU usage.
1 Like

What I do is put the workflows inside existing reusables.

For example:
If I have a popup for editing/adding a new contact, I’ll build a reusable popup and put all the workflows related to the contact inside it.
Most of the time, I’m using the popup on a page or another reusable anyway, and for the rare times it’s not used, it just sits there hidden — no issue.

This keeps everything very DRY (Do Not Repeat Yourself).


Saving Steps with Embedded Workflows

I use workflows in reusables a lot — even for small things.

For example, most people show a popup with:

  1. Set data
  2. Show popup

Instead, I put that inside a single workflow inside the popup and then just run that workflow.
2 steps might not seem like a lot, but it really helps later — like if you add a tab element inside the popup and want it to reset to Tab 1 on open. You just update the popup’s workflow once and it updates across all 20 places it’s called.
No chasing bugs across the app.


Generic Reusables Over Hard-Coded Ones

Another approach I use is building generic reusable elements.

For example, in a contact search popup, instead of passing tons of different fields into the popup to handle every situation, I:

  • Build a version where the list of selected contacts is passed back out of the popup.
  • The page or parent handles what to do with the list.

Setup:

  • Create two custom states inside the popup:
    • contact_selected
    • trigger_boolean
  • When contacts are selected:
    • Set the list to contact_selected
    • Set trigger_boolean to yes
    • Then schedule a custom event to reset trigger_boolean to no immediately (so it can be retriggered again).

On the page side, I just listen for trigger_boolean = yes and then save the contacts however needed.
This lets you drop the popup onto any page without modifying it.


Data Ownership Trick: Single Field for Linking Data

I often add one field to a data type called for_data.

  • It stores the unique_id of whatever thing the child data belongs to.
  • Then, whenever needed, I search for all things where for_data = this thing's unique_id.

This keeps your database super clean, especially when items like files might belong to dozens of different things.


Additional Tricks I Use

:small_blue_diamond: Dummy Groups for Common Data

  • I create invisible “dummy” groups on the page that prefetch or hold common data (like a search for Current User’s teams, settings, etc.).
  • I also use these groups to store numbers so that if I need to change the number source I don’t have to redo the 5 clicks to format the number again
  • This way, I don’t have to write the same search arguments 20 times in different workflows — just reference the dummy group (be careful with this though as you don’t want to download 1000 full objects when you could have just fetched the count)
  • In the backend I’ll use custom events often just as an easy way to hold and process common functions and data. Like I have a couple of math custom events for rounding to nearest 15 mins and storing lists/data so I don’t have to redo the search multiple times in each step.

:small_blue_diamond: Popup Close Events Always Reset State

  • Every popup has a “Reset Data” workflow inside it that’s triggered on close.
  • Clears inputs, resets tabs, empties custom states — keeps everything ready for the next open.

:small_blue_diamond: Settings Data for App-Wide Config

  • I create a Settings data type where I keep global things like app name, logo, company address, phone etc or for storing things like email html templates
  • The app pulls from Settings instead of hardcoding stuff — makes it easier to update later.

:small_blue_diamond: Using Data Instead of Option Sets (When Needed)

  • While Option Sets are awesome for lightweight stuff, sometimes it’s better to use an actual Data Type instead.
  • Especially if you want multiple fields (like description, icon, image), or the ability to easily add/edit options later without touching the editor. (ie admin user wants to change the options themself)
  • Just set the slug to make the options fairly easy to filter to for backend logic (I also hide the ability to delete the option if it has a slug since it’s used in logic somewhere)

:small_blue_diamond: Compartmentalizing Data Into Small Tables

  • I keep my database organized into smaller tables instead of giant master tables.
  • Keeps searches fast, keeps fields organized, and lets me expand specific parts of the app without bloating everything else. It does complicate filtering occasionally but the benefits outweigh the downsides.

If you build this way, your app stays light, scalable, and easy to maintain — even if it grows into hundreds of pages and thousands of workflows which some of my apps have.

2 Likes

Thank you all for chiming in! :heart_hands:

My main concern was WU usage as @ademiguel has pointed out. I guess pushing everything to BWs is smart but expensive. Not sure if it’s worth it.

@bestbubbledev check out the video below for an approach that considers modularity, WU, and flexibility.

You can get this functionality with this plugin

Data Jedi