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
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) => (<lionClick={() => 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) => (<lionClick={() => 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
<sectionid="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 }}<linkid="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'"><linkid="ModelViewerOverride"rel="stylesheet"href="{{ 'component-model-viewer-ui.css' | asset_url }}"media="print"onload="this.media='all'">{%- endif -%}[...Contracted]