Uplift your e-commerce development experience!

Developing an e-commerce template has just become fun. Make a new theme or convert your existing React e-commerce template in hours, not days.

Why Builderoo Theme?

Developing a fully customized Builderoo theme is easy, fast and above all, fun.

You Already Know It

Builderoo themes are based on React. If you know React, you already know it.

60 Minutes Learning Curve

Know everything there's to know about Builderoo, in 60 minutes or less.

Batteries Included

All necessary React hooks to make the perfect theme, included.

Fast Refresh

Develop and preview your theme with Next.js Fast Refresh.

Built-in Preview Data

Waste no time in thinking about data to preview your theme.

Auth, Payment, Shipping

User management, payments, shipping all built-in

A Comparison with Shopify

Builderoo gives you a superior coding experience. Keep using React, No need to memorize complex structures because you get full type safety even for your custom props and blocks.

Builderoo

Just use React
import React, {useState} from 'react';
import {Button} from "../components/ui/button";
import CartCounter from "../components/ui/CartCounter";
import {useConfig, useProduct, type Config, useCartItemQuantity, useSelectedVariant, Price} from "builderoo";
import {themeConfig} from "../theme.config";
import classNames from "clsx";
function Product() {
const product = useProduct()
const config = useConfig<typeof themeConfig>()
const {variant, onSelectOption, isOptionSelected} = useSelectedVariant(product)
const {add, remove, set} = useCartItemQuantity(product, variant)
const [quantity, setQuantity] = useState(1)
return (
<div>
<section className="px-20 pt-10 grid grid-cols-2 gap-10">
<div className="">
<div>
<img src={product.image} />
</div>
<ul className="mt-4 flex gap-3 flex-wrap">
{ product.media?.map((item, index) => (
<div key={index}>
<img src={item.url} className="block object-cover cursor-pointer"/>
</div>
))}
</ul>
</div>
<div className="flex flex-col">
<h3 className="font-medium text-2xl">{product.title}</h3>
<div className="font-medium text-lg mt-2"><Price amount={parseInt(product.price)} /></div>
<ul className="space-y-3 mt-4">
{ product.options && product.options.length > 0 && product.options.map((option, i) => (
<li key={i} className="mb-4">
<div className="text-sm text-gray-600 mb-2">{option.name}</div>
{ option.type == "color" && (
<ul className="flex gap-3">
{ option.values.map((value, i) => (
<li
onClick={() => onSelectOption(option._id, value._id)}
key={i}
title={value.label}
style={{backgroundColor: value.value}}
className={classNames(
"cursor-pointer w-4 h-4 rounded-full border-spacing-4",
{"option-selected": isOptionSelected(option._id, value._id)}
)}/>
))}
</ul>
)}
{ option.type != "color" && (
<ul className="flex gap-3">
{ option.values.map((value, i) => (
<li
onClick={() => onSelectOption(option._id, value._id)}
key={i}
className={classNames(
"border border-gray-300 rounded-sm px-3 py-1 text-sm cursor-pointer",
{"option-selected": isOptionSelected(option._id, value._id)}
)}>
{value.label}
</li>
))}
</ul>
)}
</li>
))}
</ul>
<div className="mt-6 mb-10 flex items-center gap-4">
<button className="w-48" onClick={() => add(quantity)} disabled={variant == null}>Add to cart</button>
</div>
</div>
</section>
</div>
);
}
export default Product;

Shopify

Use HTML, Liquid and stuffs*
<section
id="MainProduct-{{ section.id }}"
class="section-{{ section.id }}-padding gradient color-{{ section.settings.color_scheme }}"
data-section="{{ section.id }}"
>
{{ 'section-main-product.css' | asset_url | stylesheet_tag }}
{{ 'component-accordion.css' | asset_url | stylesheet_tag }}
{{ 'component-price.css' | asset_url | stylesheet_tag }}
{{ 'component-slider.css' | asset_url | stylesheet_tag }}
{{ 'component-rating.css' | asset_url | stylesheet_tag }}
{{ 'component-deferred-media.css' | asset_url | stylesheet_tag }}
{%- if product.quantity_price_breaks_configured? -%}
{{ 'component-volume-pricing.css' | asset_url | stylesheet_tag }}
{%- endif -%}
{%- style -%}
.section-{{ section.id }}-padding {
padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;
padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;
}
@media screen and (min-width: 750px) {
.section-{{ section.id }}-padding {
padding-top: {{ section.settings.padding_top }}px;
padding-bottom: {{ section.settings.padding_bottom }}px;
}
}
{%- endstyle -%}
<script src="{{ 'product-info.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script>
{%- if product.quantity_price_breaks_configured? -%}
<script src="{{ 'show-more.js' | asset_url }}" defer="defer"></script>
<script src="{{ 'price-per-item.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{% if section.settings.image_zoom == 'hover' %}
<script id="EnableZoomOnHover-main" src="{{ 'magnify.js' | asset_url }}" defer="defer"></script>
{% endif %}
{%- if request.design_mode -%}
<script src="{{ 'theme-editor.js' | asset_url }}" defer="defer"></script>
{%- endif -%}
{%- assign first_3d_model = product.media | where: 'media_type', 'model' | first -%}
{%- if first_3d_model -%}
{{ 'component-product-model.css' | asset_url | stylesheet_tag }}
<link
id="ModelViewerStyle"
rel="stylesheet"
href="https://cdn.shopify.com/shopifycloud/model-viewer-ui/assets/v1.0/model-viewer-ui.css"
media="print"
onload="this.media='all'"
>
<link
id="ModelViewerOverride"
rel="stylesheet"
href="{{ 'component-model-viewer-ui.css' | asset_url }}"
media="print"
onload="this.media='all'"
>
{%- endif -%}
[...Contracted]

Ready to start building the coolest theme?