Hydrogen’s bundles recipe adds visual indicators and data handling for Shopify product bundles across the storefront — product pages, collection listings, cart, and home page recommendations.

Prerequisites

The Shopify Bundles app must be installed in the store’s admin panel. The store must meet Shopify’s eligibility requirements, and at least one bundle must be created before the storefront changes take effect.

Bundle Detection

Bundles are detected via the requiresComponents boolean on ProductVariant. The recipe queries this through an aliased field to keep bundle logic separate from variant selection:

isBundle: selectedOrFirstAvailableVariant(
  ignoreUnknownOptions: true
  selectedOptions: { name: "", value: "" }
) {
  ...on ProductVariant {
    requiresComponents
    components(first: 100) {
      nodes {
        productVariant { ...ProductVariant }
        quantity
      }
    }
    groupedBy(first: 100) {
      nodes { id }
    }
  }
}

At runtime: const isBundle = Boolean(product.isBundle?.requiresComponents);

Components

BundleBadge

A green absolute-positioned label (“BUNDLE”) rendered on product images and cart line items. Requires a parent with position: relative.

BundledVariants

Renders the list of products contained in a bundle. Each row shows a thumbnail, product/variant title, and quantity, linking to the individual product page. Accepts variants: ProductVariantComponent[] from Hydrogen’s storefront API types.

Files Modified

FileChange
app/components/BundleBadge.tsxNew — badge component
app/components/BundledVariants.tsxNew — bundled variants list
app/routes/products.$handle.tsxQueries isBundle, renders BundledVariants, passes isBundle to ProductImage and ProductForm
app/routes/collections.$handle.tsxQueries isBundle in PRODUCT_ITEM_FRAGMENT
app/lib/fragments.tsAdds requiresComponents, components, groupedBy to cart fragments
app/components/CartLineItem.tsxShows BundleBadge for bundle line items
app/components/ProductForm.tsxButton text: “Add bundle to cart” vs “Add to cart”
app/components/ProductImage.tsxShows BundleBadge overlay when isBundle
app/components/ProductItem.tsxShows BundleBadge on product cards in listings
app/routes/_index.tsxAdds maxVariantPrice to recommended products query
app/styles/app.cssAdds position: relative to .product-image

Adapting to Non-Skeleton Projects

The recipe steps target the Hydrogen skeleton template. When adapting to a custom project:

  • File names and paths will differ — map each skeleton file to its equivalent in your project structure.
  • Steps are not strictly ordered; dependencies between steps (e.g., fragments must exist before components can query them) determine execution order.
  • Never edit generated .d.ts files directly — run npm run codegen (if available) to regenerate them after GraphQL changes.

Key Patterns

  1. requiresComponents as detection flag — single boolean on ProductVariant that identifies bundles.
  2. Aliased query field (isBundle) — keeps bundle logic isolated from primary variant selection.
  3. components connection — provides ProductVariantComponent nodes with variant data and quantity for rendering bundled items.
  4. Badge overlayBundleBadge uses absolute positioning; parent containers must set position: relative.
  5. Conditional button textProductForm adjusts CTA copy based on isBundle prop.

Troubleshooting

IssueSolution
No bundles visible on storefrontInstall Shopify Bundles app and create bundles in admin
No badges on product pagesVerify PRODUCT_FRAGMENT includes the isBundle alias and BundledVariants is rendered
No badges in cartVerify CART_QUERY_FRAGMENT includes requiresComponents and components

See Also