Create Box Builder or Mix and Match

Hello everyone, i wanna ask how to custom a box builder or kinda like mix & match product which we can set the conditions like minimum and maximum, also multiple per one page, i found many apps but the free plan is not giving this.

Hey @veluxe1 I don’t know how much could this be of help or to what extent t it matches your requirements but did a feature similar to this.

Site: shadabs-online-store.myshopify.com

Password: reafur

Please search for bundled discounted collection or just see the second section on the home page.

What this does is let you mix and match products from different collections and you have the option from the customizer to choose how many products to include. This is kind of a fixed price bundle implementation.

Hope this helps in a way.

Best

Hi @veluxe1,

Goto Online store> edit code > goto section folder > create a file named custom-box-builder.liquid and paste the code

<style>

  .box-builder {

    padding: 50px 20px;

    max-width: 1200px;

    margin: 0 auto;

    z-index: 1;

    position: relative;

  }

  .box-grid {

    display: grid;

    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));

    gap: 30px;

    margin-top: 40px;

  }

  .product-card {

    border: 1px solid #e1e1e1;

    padding: 15px;

    border-radius: 8px;

    transition: transform 0.3s ease;

    text-align: center;

  }

  .product-card:hover {

    transform: translateY(-5px);

    box-shadow: 0 5px 15px rgba(0,0,0,0.1);

  }

  .add-to-box-btn {

    width: 100%;

    background: #000;

    color: #fff;

    border: none;

    padding: 10px;

    margin-top: 10px;

    font-weight: bold;

    cursor: pointer;

  }

  .item-count-display {

    margin-top: 10px;

    font-weight: bold;

  }

</style>




<section class="box-builder" data-min="{{ section.settings.min_items }}" data-max="{{ section.settings.max_items }}">

  <h2>{{ section.settings.title }}</h2>

  <p>Select between {{ section.settings.min_items }} and {{ section.settings.max_items }} items.</p>




  <div class="box-grid">

    {% for product in collections[section.settings.collection].products %}

      

 

    
      <div class="product-card" data-variant-id="{{ product.selected_or_first_available_variant.id }}">

        <img src="{{ product.featured_image | img_url: '300x300' }}" alt="{{ product.title }}" style="max-width: 100%;">

        <h3>{{ product.title }}</h3>

        <p>{{ product.price | money }}</p>

        <button type="button" class="add-to-box-btn">Add to Box</button>

        <div class="item-count-display">Count: <span class="item-count">0</span></div>

      </div>

    {% endfor %}

  </div>




  <div class="box-summary" style="margin-top: 30px; padding: 20px; border: 2px solid #000; text-align: center;">

    <h3>Your Box (<span id="total-selected">0</span> items)</h3>

    <button id="submit-box" disabled style="padding: 15px 30px; background: #000; color: #fff; cursor: not-allowed;">Add Box to Cart</button>

  </div>

</section>




<script>

document.addEventListener('DOMContentLoaded', function() {

  const boxContainer = document.querySelector('.box-builder');

  if (!boxContainer) return;




  const min = parseInt(boxContainer.dataset.min);

  const max = parseInt(boxContainer.dataset.max);

  const submitBtn = document.getElementById('submit-box');

  const totalDisplay = document.getElementById('total-selected');

  

  let selectedItems = {}; 

  document.querySelectorAll('.add-to-box-btn').forEach(btn => {

    btn.addEventListener('click', function() {

      const card = this.closest('.product-card');

      const vId = card.dataset.variantId;

      const countSpan = card.querySelector('.item-count');




      let currentTotal = Object.values(selectedItems).reduce((a, b) => a + b, 0);




      if (currentTotal < max) {

        selectedItems[vId] = (selectedItems[vId] || 0) + 1;

        countSpan.innerText = selectedItems[vId];

        updateSummary();

      } else {

        alert("Maximum limit of " + max + " reached.");

      }

    });

  });




  function updateSummary() {

    let currentTotal = Object.values(selectedItems).reduce((a, b) => a + b, 0);

    totalDisplay.innerText = currentTotal;

    

    if (currentTotal >= min) {

      submitBtn.disabled = false;

      submitBtn.style.cursor = "pointer";

      submitBtn.style.backgroundColor = "#008000";

    } else {

      submitBtn.disabled = true;

      submitBtn.style.cursor = "not-allowed";

      submitBtn.style.backgroundColor = "#000";

    }

  }

  submitBtn.addEventListener('click', function() {

    let itemsArray = [];

    for (const [id, qty] of Object.entries(selectedItems)) {

      if(qty > 0) {

        itemsArray.push({

          id: parseInt(id),

          quantity: parseInt(qty)

        });

      }

    }

    fetch(window.Shopify.routes.root + 'cart/add.js', {

      method: 'POST',

      headers: { 'Content-Type': 'application/json' },

      body: JSON.stringify({ items: itemsArray })

    })

    .then(response => {

      if (!response.ok) {


        return response.json().then(err => { throw new Error(err.description || err.message) });

      }

      return response.json();

    })

    .then(data => {


      window.location.href = window.Shopify.routes.root + 'cart'; 

    })

    .catch(error => {

      console.error('Cart Error:', error);

      alert("Error: " + error.message);

    });

  });

});

</script>




{% schema %}

{

  "name": "Box Builder",

  "settings": [

    { "type": "text", "id": "title", "label": "Heading", "default": "Mix & Match Box" },

    { "type": "collection", "id": "collection", "label": "Select Collection" },

    { "type": "number", "id": "min_items", "label": "Minimum Items", "default": 3 },

    { "type": "number", "id": "max_items", "label": "Maximum Items", "default": 6 }

  ],

  "presets": [{ "name": "Box Builder" }]

}

{% endschema %}

Next Steps:

  1. Save the File
    2.Go to Theme Eedit
    3.Click add section and search Box Builder
    4.Choose yor collection

Hi @veluxe1 :raising_hands:

Sorry for the delayed response — I hope everything’s been going well on your end :blush:

A setup like this can actually be created quite nicely with Easify Box Bundle Builder BYOB, especially if you’re looking to build a Mix & Match or Box Builder experience with minimum and maximum quantity requirements.

To give you a clearer idea of how the setup could work in practice, I’ve also prepared a similar demo that you can use as a reference:

  • This is the result:

To begin with, inside the app you just need to create a new box and choose the Regular Box type :blush: This box type is designed for Mix & Match setups, allowing customers to freely combine different products within the same bundle-building experience.

After that, you can add the collections or specific products you’d like customers to choose from :blush: As customers make their selections, the chosen items will automatically appear in the box summary, making it easy for them to review everything before adding the bundle to the cart.

For the minimum and maximum quantity conditions, for example if you’d like customers to select at least 3 products and no more than 6 products, you can simply click on Add Conditions and configure the quantity rules there :blush:

Once everything is set up, the app will automatically validate the customer’s selections and only allow them to proceed when the required quantity conditions are satisfied.

The overall setup is also very beginner-friendly and can usually be configured directly inside the app without needing coding knowledge or complicated customizations. :heart:

Hey @veluxe1

This is exactly what a mix-and-match box builder does — you can try NeatBundles (full disclosure: I’m the founder :slightly_smiling_face:). You set up a builder where customers pick their own products to fill the box, with min/max quantity rules (and allow/disallow duplicates) per step, and you can put multiple selection steps in one flow — so it sounds like a direct match for what you’re describing.

There are also other apps which do the similar thing like Easy Bundle Builder, Easify Box Bundle Builder, Kitenzo - Bundle Builder, BYOB ‑ Build Your Own Bundles.

On the pricing point: NeatBundles has a free plan for development stores, so you can build and test the whole thing (min/max conditions included) at no cost before going live.

Feel free to reach out if you have any questions.

Best,
Jure