🦄 Unicorn UI - 300+ full stack components for Bubble, made entirely with Buildprint

That’s awesome thanks @georgecollier for the approach - this is great for components.

I would argue that the plugin approach + code is simpler and easier to maintain - but the whole release/collaborator setup is holding it back, especially when only used in a single app.

Yes, when a human was writing them, and even then, only when you own it

But the whole testing loop and setup is such a pain

In a plugin, for styling for example you’re limited to what the plugin exposes. If you want more customisability you’re out of luck

Good points @georgecollier - excited to dig into these components more. Great contribution to the ecosystem!

So true, and hard to get different plugins to look the same styling or match bubble native elements. Another issue is the saved styles, if available, not easy to use across different apps.

Thanks @georgecollier for this amazing library! :folded_hands:

I will LOVE to see a resource calendar as well… I have a room booking system, and I need to see the rooms at the top, with the time slots displayed along the side. This is hard to find (at least something as nice as you have built)…

We have some calendars already; once those components are published officially, just ask Buildprint to build you one based on the Unicorn UI calendars!

The library is designed as a boilerplate the agent takes and adapts

FWIW I think Bubble will solve the custom code problem in Bubble more comprehensively so this component library is kind of a sneak peek of what people will be able to achieve in a prompt in future!

Excellent contribution to the community George! Bravo. Out of interest, what did you use for the demo video?

You can ask AI to make this as a plugin for you. That’s what I did and turned out pretty good

opus 5.5

I took a look at the latest components, @georgecollier , really interesting approach.

I know a few Bubble users who already put code inside HTML elements for different use cases, sometimes even for pretty large parts of a page. I’ve done that myself too, not only for CSS styling, but for complete components.

So I think sharing these as ready-made components is a pretty interesting idea.

To me, the main difference of these HTML-based components compared with plugins is basically where the code lives and who is responsible for maintain and update it, also styling and autobind.

So, these are some of my thoughts about…


UPDATES

With BP components (HTML-based), the code is copied into the given app. That means you can grab an initial version from the original Unicorn UI lib, then open it, change it, extend it and adapt it to something the original component was never designed to do.

With plugins, the internal code stays inside the plugin. You work with the properties, actions, events and states that the plugin exposes. You have less freedom to change it beyond what the plugin allows you to do, but you also don’t have to maintain them yourself.

Updates are also a bit different. A plugin developer can fix something or release a new feature once and publish a new version that can be reflected to all users. The trade-off is that you become dependent on the plugin author for maintenance and future fixes. So the reputation of the author, the plugin’s history, and the level of support behind it become important.

This is especially relevant with free plugins, where ongoing maintenance and support can sometimes be limited simply because the author has less incentive or time to keep investing in them.

And then… with a BP component that lives inside the app, you have your own copy, which is great for customization, but different apps can end up with slightly different versions over time. Specially because you can modify the original version to accommodate your needs, and these changes can be done manually, if you know the basics about code (with a risk to break something silently or lose styles consistency between componentes in the same family) or using AI, that I supposed would be more practical in these days. Or maybe even using Bubble’s AI agent… or your own agent if you trained one to do this (I did it for some of my apps and it is working well).

Also, I believe that if you use BP components with multiple apps, and if at some point the original one receives a fix/update that you also want that in your app, or if you did some update by yourself and want that in all those other apps already using it, you will need to replicate the changes (specially if they are critical) to all those apps. In this case, I think, to no be so much time consuming, you will also need to use AI and be confident that the results will be stable and not introduced small differences between apps.


STYLING

Another practical difference is styling. If a plugin is built properly around Bubble’s native style system, you can have multiple predefined styles for the same component and switch between them very quickly across the app.

For example, you could have two or three versions of the same dropdown, input or toggle already defined as Bubble styles and reuse them anywhere without changing the component itself.

With an HTML-based component, you can achieve the same result, but you would normally need either separate versions of the component or additional parameters to control those visual variations.

So plugins can fit (if made in a correct way) quite naturally into Bubble’s existing global styling workflow (with some exceptions), while HTML-based components usually need to recreate that layer themselves.

But yeah, the vast majority of plugins don’t do this the way, like @boston85719 pointed above.

There are some input plugins where the author didn’t even select the “Input element” type, which already limits the plugin in many ways.


DYNAMIC DATA SOURCE

Another difference is data flexibility.

Reusable elements are still limited by the datatype they are built around, maybe Bubble will change this in the future, what would be really useful. Because, right now, if a component expects a specific Thing, datatype or option set, reusing the exact same component with a completely different data structure can require extra parameters, duplicated versions or some additional abstraction.

Plugins can be a bit more flexible here because they can expose more generic inputs and states without being tied as closely to a specific reusable element datatype.

So for components that need to work with many different kinds of dynamic data, plugins can sometimes provide a cleaner interface.

LIMITATIONS

One thing I do agree with is that Bubble’s native components still have a lot of limitations, and some common components simply don’t even exist natively.

Plugins can fill those gaps, but if you rely on many different plugin authors, you can eventually end up with some visual and technical debt. Different components may follow different UI patterns, expose different features, use different naming conventions, and behave differently even when they solve similar problems.

That’s actually one of the reasons I’ve always preferred building many of my own components around the same design system. I also use my own React component library as a reference, so I try to keep the same patterns, behavior and visual language across everything I build.

From that perspective, I can definitely see the appeal of having a large component library where everything follows a more consistent approach.

So I don’t really see one as replacing the other. I think it depends much more on the type of user, the project, and how much control you actually want over the component.

Some developers will prefer having access to the implementation and being able to change anything they want. Others will prefer a more contained component where the internal code is maintained for them.

So… I think, in the end, they solve similar problems in different ways.

BP HTML-based components are AI-editable, giving you more control over the implementation.

Plugins are mostly AI-configurable (if well documented), giving you less control due the abstraction layer, but less responsibility for maintaining them too.


Well… you know, these are just some of my thoughts at the moment… So let me know your perspective about these points, and correct me if I am wrong in some way…

Anyway, great contribution, man.

Also, one question, are these components handling with autobind in some way?

That looks very nice @gf_wolfer :clap:! Thanks for sharing your experience!

file browser go brrrrrr

(and it only loads the files it actually needs from the db, not the entire nested folder subtrees)

fully integrated with workflow editor etc

This are now all available in the components tab in Buildprint.

If using CLI, just ask Buildprint to use the component.

One limitation I ran into back in 2019 using HTML elements and JavaScript to create charts was dynamic data expressions were a nightmare to manage. The bugginess of Bubble HTML elements when changing basic text (it jumps around so you end of typing somewhere else than where clicked, or delete something you didn’t intend to) made it frustrating to try and manage the code, but dynamic expressions trying to click to correct location to add them or edit them.

If trying to copy everything out of the html element to give to a LLM chat it will be difficult if dynamic expressions exist as you can only copy the static text, but I suppose you could take screen shots of it all.

The use of HTML elements has some advantages and drawbacks as you’ve pointed out. I think overall they are pretty decent for simple apps or quick MVPs that mostly need some visuals, and maybe not all the functionality plugins could deliver more easily.

Loving the functional components like the calendars and date pickers! My calendar and date picker components were a pain to build and implement.

I still am not using Buildprint for my current projects but can’t wait to start with my next one on Buildprint.

The implementation of HTML elements in Unicorn components are very well done. The script expects a JSON shape so all one needs to do is fit datatype fields to the key values.

image

For example we can break this script into:

{
  "base": "Arbitrary date/time :extract UNIX",
  "selected": "Unicorn Calendar's Selected event's unique id",
  "resources": "Search for Calendar Resources :format as text",
  "events": "Search for Calendar Events :format as text"
}

Resources and Events are just arrays of JSON objects.

"resources": [
  {
    "id": "This Calendar Resource's unique id",
    "name": "This Calendar Resource's name",
    "role": "This Calendar Resource's role",
    "color": "This Calendar Resource's color"
  }
]
"events": [
  {
    "id": "This Calendar Event's unique id",
    "title": "This Calendar Event's title",
    "start": "This Calendar Event's start :extract UNIX",
    "end": "This Calendar Event's end :extract UNIX",
    "allDay": "This Calendar Event's all day",
    "resource": "This Calendar Event's resource's unique id",
    "color": "This Calendar Event's resource's color"
  }
]

This method of implementation makes it very easy to debug in the Bubble editor.

Even the boolean for events.allDay uses Bubble’s yes/no format instead of a true JSON Boolean. Very easy to fit!

Yep, and even for the calendar component for example - you don’t need to pass the HTML ALL the possible events so it can filter client side. The logic is designed so that if the user changes view to month or week or moves through the calendar, the HTML element requests the data from Bubble, avoiding loading more records than necessary.

In reality, you’ll be using Buildprint to edit these, but it means it’s still easy to understand and maintain with any AI agent (well, maybe Bubble agent will need some time, but eventually :wink: )

You’re gonna kick yourself when you realise what you’ve been missing

Just use it! Buildprint can run with dev db access only, which is useful for any compliance concerns.

@georgecollier I was looking through the script for the Date Range Picker component and it’s really cool that Buildprint uses a workaround to trigger Bubble element workflow events by calling Bubble methods.

Question about the Bubble Date Picker elements that the script refers to with IDs unicorn-date-start and unicorn-date-end. I can’t find the IDs being dynamically set in the script so I assume it’s set in the Bubble Editor but I don’t see it set

Could be because I’m previewing the editor but I don’t see the IDs being set in the Bubble editor.

HTML ID attributes are in property editor → Interaction → Advanced

And yes you (or the agent) just set statically