Catalog & Search
Listing and looking up products, and live typeahead search over WebSocket.
Products
storefront.products — list/filter the catalog and look up individual products.
storefront.products.get({ q: 'shoes', page: 2 }, function(err, data) {
if (err) return console.error(err)
console.log(data.products, data.total_pages)
})
storefront.products.getForCart('aurora-runner', function(err, product) {
if (err) return console.error(err)
// product.variant_options / product.variant_list — the color/size matrix,
// same shape product-variant-selector (see Components) expects
})
get(params?, fn)— List products, optionally filtered (q,collections,product_types,vendors,tags,price_gte,price_lte,page,facets). Callsfn(err, data)withdata: { products, page, per_page, total_items, total_pages, facets }. Each product is in basic mode — no variant data.related(productSlug, fn)— Products related to the given one (by tag or collection), for cross-sell widgets. Items already in the cart are excluded automatically. Callsfn(err, products).getForCart(productSlug, fn)— A single product in cart-ready shape: the fullvariant_options/variant_listmatrix (for multi-axis variant selection),bundle_config,modifiers,subscription_fees. This is the only way to get variant data headlessly —get()’s list endpoint never includes it, even in full mode. Callsfn(err, product).
Search
storefront.search gives you live, typeahead-style product search over a WebSocket
connection to Bolder’s hosted search service — the same backend that powers hosted
themes’ search boxes.
bindTo(input, opts?) — the common case
Wires an <input> element up end to end: connects on focus (so the connection is warm
before the first keystroke), debounces input, and emits results. Returns an
Emitter — call .destroy() to unbind.
const handle = storefront.search.bindTo(document.querySelector('#search-input'), {
minChars: 3, // default: 3
debounce: 150, // ms, default: 150
})
handle.on('results', (evt, results, query) => {
renderResults(results.products, results.groups)
})
handle.on('cleared', () => clearResults())
handle.on('error', (evt, err) => console.error('Search failed', err))
// later, e.g. on component unmount:
handle.destroy()
You don’t need to manage the connection yourself — bindTo reuses one socket per
storefront instance and lets it disconnect on inactivity automatically.
search(query, opts?, fn) — build your own UI
Lower-level: runs a single query without binding to an input. Auto-connects if needed.
storefront.search.search('running shoes', { minChars: 3 }, (err, results) => {
if (err) return console.error(err)
console.log(results.products, results.groups)
})
connect(fn?) — pre-warm the connection
Rarely needed directly — both search() and bindTo() connect automatically. Useful if
you want to open the connection earlier than the first query (e.g. as soon as a search
UI becomes visible, before the user has typed anything) to shave connection latency off
the first result.
storefront.search.connect((err, socket) => {
if (err) return console.error('Could not connect to search', err)
})
Results shape
{
products: [
{ id, name, slug, url, type, vendor, price, image, vars, skus }
],
groups: [
{ type, name, slug } // Collection, ProductType, Vendor, ProductSet, or Tag matches
]
}
Which fields are present depends on config passed to createStorefront() — image and
price require withImages/withPrices (both on by default for headless).