Skip to main content
The SDK provides two ways to access the Layers API: direct API access via factory functions, and reactive methods via the app module.

Direct API Access

Create an API client using the useLayers factory function:
import { useLayers } from '@protonagency/commerce-blocks-sdk';

const api = useLayers({
  apiToken: 'your-layers-token',
  baseUrl: 'https://app.uselayers.com', // Optional
});

Available Methods

MethodDescription
browse(input)Browse and filter products within a collection
search(input)Unified search (calls prepareSearch + semanticSearch)
prepareSearch(input)Prepare search query, returns search_id (5min TTL)
semanticSearch(input)Execute search with optional search_id
similarProducts(input)Find products similar to a given product
predictiveSearch(input)Autocomplete and predictive search suggestions
searchByImage(input)Unified image search (calls imageUpload + imageSearch)
imageUpload(input)Upload image, returns imageId
imageSearch(input)Search by imageId or imageData (base64)
getSortOrders()Get available sort options
All methods return Promise<Result<T>> with either { data: T } or { error: Error }.

Browse

Browse products within a merchandised collection:
const result = await api.browse({
  collectionHandle: 'summer-shoes',
  sortOrderCode: 'best_selling',
  pagination: { page: 1, limit: 24 },
  filterGroup: {
    conditional: 'AND',
    expressions: [
      { property: 'vendor', operator: 'eq', values: ['Nike'] }
    ]
  },
  facets: ['vendor', 'color', 'size'],
  retrieveFacetCount: true,
});
Perform semantic search across your catalog:
const result = await api.search({
  query: 'blue running shoes',
  pagination: { page: 1, limit: 24 },
});

Similar Products

Find products similar to a reference product:
const result = await api.similarProducts({
  productId: '1234567890',
  limit: 8,
});
Get autocomplete suggestions:
const result = await api.predictiveSearch({
  query: 'sho',
  limit: 5,
});
Search for products using an image:
const result = await api.searchByImage({
  imageData: 'base64-encoded-image-data',
  limit: 24,
});

App Module Methods

When using the app module via initialize(), you get access to reactive methods that return Preact Signals:
import { initialize } from '@protonagency/commerce-blocks-sdk';

const app = initialize({ /* config */ });

Reactive Methods

These methods return Signal<DataState<T>> for reactive UI updates:
MethodDescription
browse(input)Browse/filter products by collection
search(input)Full-text semantic search
similarProducts(input)Find products similar to another
predictiveSearch(input)Autocomplete/predictive search
searchByImage(input)Search products by image
getSortOrders()Get available sort orders

Utility Methods

MethodDescription
getSwatch(value)Look up swatch by option value
clearCache()Clear all cached data
destroy()Destroy app instance and clean up

Properties

PropertyDescription
initializedBoolean flag if app is ready
configResolved app configuration
storeReactive Preact Signals store
layersApiDirect Layers API client (Promise-based)

DataState Type

Reactive methods return a ReadonlySignal<DataState<T>>. The DataState type represents the current state of data:
interface DataState<T> {
  data: T | null;           // The data (null if loading or error)
  error: Error | null;      // Error from the last request
  status: 'idle' | 'loading' | 'success' | 'error' | 'stale';
  timestamp: number;        // When data was last updated
}

Status Values

StatusDescription
idleInitial state, no request made yet
loadingRequest in progress
successRequest completed successfully, data available
errorRequest failed, error available
staleData restored from localStorage, may need refresh

Usage Example

const signal = app.browse({ 
  collectionHandle: 'shoes', 
  sortOrderCode: 'relevance' 
});

// In a Preact component
function ProductList() {
  const { data, error, status } = signal.value;

  if (status === 'loading') return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!data) return <div>No products</div>;

  return (
    <div>
      {data.results.map(p => <ProductCard product={p} />)}
    </div>
  );
}

Utility Functions

The SDK provides several utility functions for common operations:

Filter Builder

Build filter expressions with a functional API:
import { filter } from '@protonagency/commerce-blocks-sdk/utils';

// Simple equality filter
const vendorFilter = filter.eq('vendor', 'Nike');

// Combine filters
const combinedFilter = filter.and(
  filter.eq('vendor', 'Nike'),
  filter.gt('price', 50)
);

Throttle and Debounce

import { throttle, debounce } from '@protonagency/commerce-blocks-sdk/utils';

// Throttle: limit calls to once per wait period
const throttledSearch = throttle({
  fn: (query) => api.search({ query }),
  wait: 300,
});

// Debounce: delay until wait period of inactivity
const debouncedSearch = debounce({
  fn: (query) => api.search({ query }),
  wait: 300,
});

Shopify ID Utilities

import { 
  isShopifyProductGID,
  toShopifyProductGID,
  toShopifyVariantGID,
  fromShopifyProductGID,
} from '@protonagency/commerce-blocks-sdk/utils';

// Check if string is a Shopify product GID
isShopifyProductGID('gid://shopify/Product/123'); // true

// Convert numeric ID to Shopify GID
toShopifyProductGID(123); // 'gid://shopify/Product/123'
toShopifyVariantGID(456); // 'gid://shopify/Variant/456'

// Extract numeric ID from GID
fromShopifyProductGID('gid://shopify/Product/123'); // 123

Product Utilities

import { 
  createProduct,
  getVariant,
  getSelectedVariant,
  getImages,
  generateSrcset,
} from '@protonagency/commerce-blocks-sdk/utils';

// Create normalized Product from API data
const product = createProduct(layersData, storefrontData, 'USD');

// Get variant by selected options
const variant = getVariant(product, { color: 'Red', size: 'M' });

// Get initially selected variant
const selectedVariant = getSelectedVariant(product);

// Get images for current selection
const images = getImages(product, { color: 'Red' });

// Generate responsive srcset
const srcset = generateSrcset(imageUrl, [200, 400, 800]);

Environment Detection

import { isServer, isBrowser } from '@protonagency/commerce-blocks-sdk/utils';

if (isBrowser()) {
  // Client-side only code
}

if (isServer()) {
  // Server-side only code
}

Runtime Component Creation

The SDK provides utilities for creating Preact components at runtime without a build step:

createComponent

Compile an HTM template string into a Preact component:
import { createComponent } from '@protonagency/commerce-blocks-sdk';

const ProductCard = createComponent<{ title: string; price: string }>(`
  <div class="product-card">
    <h2>\${props.title}</h2>
    <span>\${props.price}</span>
  </div>
`);
Templates have access to:
NameDescription
htmlHTM tagged template for creating elements
propsComponent props passed at render time
useSignal(value)Create a reactive signal (hook)
useComputed(fn)Create a computed signal (hook)
useSignalEffect(fn)Run side effects on signal changes (hook)
signal(value)Create a standalone signal
computed(fn)Create a standalone computed signal

createIsland

Mount a Preact component into a DOM element:
import { createIsland } from '@protonagency/commerce-blocks-sdk';
import { signal } from '@preact/signals';

// Static props
const cleanup = createIsland(ProductCard, document.getElementById('mount'), {
  props: { title: 'Shoes', price: '$99' },
});

// Reactive props with signals
const props = signal({ title: 'Shoes', price: '$99' });
const cleanup = createIsland(ProductCard, element, { props });
props.value = { title: 'Updated', price: '$149' }; // Auto re-renders

// Cleanup when done
cleanup();