@wix/headless-ecom
v0.0.45
Published
E-commerce headless components for building cart, checkout, and commerce functionality in Wix-powered applications.
Maintainers
Keywords
Readme
@wix/headless-ecom
E-commerce headless components for building cart, checkout, and commerce functionality in Wix-powered applications.
💡 Motivation
Traditional Wix components are tightly coupled with Wix's editor and rendering engine. Headless components break free from this constraint, enabling developers to build completely custom frontends while still leveraging Wix's powerful backend services.
This package connects your standalone React application (Next.js, Astro, Remix, etc.) directly to Wix's e-commerce APIs through the Wix SDK.
In simple words - the developer brings the UI, Wix provides the e-commerce engine. The headless components are the bridge that connects them, giving the developer the best of both worlds—Wix's robust backend with his frontend creativity.
📦 Package Overview
This package provides unstyled, composable React components for e-commerce functionality, following a service-oriented architecture where business logic is separated from presentation.
For detailed API specifications, see ECOM_INTERFACE.md.
🚀 Installation
npm install @wix/headless-ecom @wix/headless-components
# or
yarn add @wix/headless-ecom @wix/headless-components📚 What's Included
✅ Current Components
- Cart - Main cart component with primitive layer and AsChild support
- LineItem - Individual cart item component
- CartCoupon - Coupon management functionality
- SelectedOption - Product options displayed in cart
- CurrentCart - Cart state wrapper component
- Commerce - Commerce functionality wrapper
🔧 Services
- CurrentCartService - Cart state management
- CheckoutService - Checkout flow logic
- SelectedOptionService - Product option handling
🎯 Usage
Basic Cart Implementation
import { Cart } from '@wix/headless-ecom/react';
import { LineItem } from '@wix/headless-ecom/react';
function ShoppingCart() {
return (
<Cart.Root>
<Cart.LineItemsList>
{({ lineItems, isLoading }) =>
isLoading ? (
<div>Loading cart...</div>
) : (
lineItems.map((item) => (
<LineItem.Root key={item.id} lineItem={item}>
<LineItem.Image />
<LineItem.Title />
<LineItem.SelectedOptions>
<LineItem.SelectedOptionRepeater>
<SelectedOption.Text />
<SelectedOption.Color />
</LineItem.SelectedOptionRepeater>
</LineItem.SelectedOptions>
</LineItem.Root>
))
)
}
</Cart.LineItemsList>
<Cart.Summary>
{({ subtotal, total, tax }) => (
<div>
<p>Subtotal: {subtotal}</p>
<p>Tax: {tax}</p>
<p>Total: {total}</p>
</div>
)}
</Cart.Summary>
<Cart.Checkout>
{({ checkout, isLoading }) => (
<button onClick={checkout} disabled={isLoading}>
{isLoading ? 'Processing...' : 'Checkout'}
</button>
)}
</Cart.Checkout>
</Cart.Root>
);
}Using Services Directly
import {
CurrentCartService,
loadCurrentCartServiceConfig,
} from '@wix/headless-ecom/services';
// Load cart configuration
const config = await loadCurrentCartServiceConfig();
// Use in your service manager
const services = createServiceManager({
services: [CurrentCartService],
config: { currentCart: config },
});🏗️ Architecture
This package follows a three-layer architecture:
1. Services Layer (/services)
Business logic, state management, and API integrations:
current-cart-service.ts- Cart state and operationscheckout-service.ts- Checkout flow managementselected-option-service.ts- Product option handlingcommon-types.ts- Shared TypeScript types
2. React Components (/react)
Headless UI primitives with render props:
- Core Components (
/react/core) - Plain render functions connecting directly to the SDK. These use the old render-props pattern and provide the foundational logic for interacting with Wix services. - Public API Components (
/react) - Primitive components inspired by Radix UI. These wrap the core components to provide a more modern, composable API withasChildsupport and follow the documented patterns.
Key Principle: Headless components include no styling and preferably minimal DOM elements. They are designed to be building blocks for composing the UI of your e-commerce app, giving the developer complete control over the visual presentation while handling all the business logic, state management, and API interactions.
3. Mappers (/mappers)
Data transformation utilities:
line-item-to-selected-options.ts- Convert line items to selected options
📋 File Structure
ecom/
├── package.json
├── README.md (this file)
├── tsconfig.*.json
├── vitest.config.ts
├── src/
│ ├── react/
│ │ ├── Cart.tsx (1,246 lines - main component)
│ │ ├── Cart.test.tsx
│ │ ├── LineItem.tsx
│ │ ├── LineItem.test.tsx
│ │ ├── SelectedOption.tsx
│ │ ├── SelectedOption.test.tsx
│ │ ├── CartCoupon.tsx
│ │ ├── CartCoupon.test.tsx
│ │ ├── CurrentCart.tsx
│ │ ├── Commerce.tsx
│ │ ├── Commerce.test.tsx
│ │ ├── index.tsx
│ │ └── core/
│ │ ├── CurrentCart.tsx (old render-props)
│ │ └── Checkout.tsx
│ ├── services/
│ │ ├── current-cart-service.ts
│ │ ├── checkout-service.ts
│ │ ├── selected-option-service.ts
│ │ ├── common-types.ts
│ │ └── index.ts
│ ├── mappers/
│ │ └── line-item-to-selected-options.ts
│ └── data-component-tags.ts
├── dist/ (built ESM output)
└── cjs/ (built CommonJS output)🛠️ Development
Setup
# Install dependencies (from monorepo root)
yarn install
# Build this package
cd packages/headless-components/ecom
yarn buildTesting
⚠️ Important: Always use --run flag to avoid interactive watch mode.
# Run tests (non-interactive)
yarn test --run
# Run tests with verbose output
yarn test --run --reporter=verbose
# Run tests with coverage
yarn test --run --coverageBuild
# Build both ESM and CommonJS
yarn build
# Build ESM only
yarn build:esm
# Build CommonJS only
yarn build:cjsLinting
# Lint and fix
yarn lint:fix
# Lint check (no changes)
yarn lint:check📐 Design Patterns
List, Options, and Repeater Pattern
This package follows the standard three-level architecture for list-based components:
// Level 1: Container - provides context, conditional rendering
<Cart.LineItems>
// Level 2: List container - handles empty state
<Cart.LineItemsList emptyState={<div>Your cart is empty</div>}>
// Level 3: Repeater - maps to LineItem.Root
<Cart.LineItemRepeater>
<LineItem.Title />
<LineItem.Image />
</Cart.LineItemRepeater>
</Cart.LineItemsList>
</Cart.LineItems>AsChild Pattern
Components support the asChild prop for custom DOM structure:
// Default rendering
<LineItem.Title>Product Name</LineItem.Title>
// Renders: <div>Product Name</div>
// With asChild - merges with child element
<LineItem.Title asChild>
<h3 className="text-2xl font-bold">Product Name</h3>
</LineItem.Title>
// Renders: <h3 className="text-2xl font-bold">Product Name</h3>TestIds Pattern
All components use centralized TestIds enums:
enum TestIds {
cartRoot = 'cart-root',
cartLineItems = 'cart-line-items',
cartItem = 'cart-item',
cartSummary = 'cart-summary',
}
// Usage in tests
screen.getByTestId('cart-root');🚀 Deployment
This section describes how to roll out changes from the headless components package into the full Wix ecosystem (stores extension, kitchensink, Vibe plugins, and production extensions).
ℹ️ Note: These steps are internal to Wix and assume access to the relevant private repositories and Falcon publishing.
1. Publish the package via Falcon
- Add your code changes to the headless components monorepo:
@wix/headless-ecom/@wix/storesin
https://github.com/wix-private/headless-components/tree/master/packages/headless-components/stores - Open a PR, get it reviewed, and merge into
master. - Wait for Falcon to build and publish the new package version to the internal registry.
2. Update the Stores extension to re-export the new version
Update the Stores extension to re-export the newly published version of @wix/stores:
- Bump the consumed version to the newly published one.
3. Update Kitchensink
Update the kitchensink demo app to use the new version of @wix/stores:
- In https://github.com/wix-incubator/kitchensink, bump the
@wix/storesversion. - Modify wrapper components or examples if API changes affect them.
- Open a PR and merge it into
masteronce tests pass.
4. Update vibe-stores-plugin via kitchen-sync
- In
vibe-stores-plugin-files, run the kitchen-sync script to pull the updated files from kitchensink. - Open a PR containing the generated updates.
- In the same PR, bump the plugin version in:
https://github.com/wix-private/vibe-plugins/blob/master/plugins/stores/vibe-stores-plugin/package.json#L3
5. Update the Dynamic Extension
When the updated @wix/vibe-stores-plugin version is published:
- Go to the extension in your app in dev center:
- Update the Store plugin version in the extension to the newly published one.
- Publish the extension.
🔗 Dependencies
Core Dependencies
{
"@wix/auto_sdk_ecom_checkout": "^1.0.61",
"@wix/auto_sdk_ecom_current-cart": "^1.0.56",
"@wix/headless-media": "workspace:*",
"@wix/sdk": "^1.15.24",
"@wix/services-manager-react": "^0.1.26",
"@radix-ui/react-slot": "^1.1.0"
}Peer Dependencies
{
"@wix/headless-components": "^0.0.0"
}📊 Package Exports
This package exports both ESM and CommonJS formats:
{
"exports": {
"./react": {
"types": "./dist/react/index.d.ts",
"import": "./dist/react/index.js",
"require": "./cjs/dist/react/index.js"
},
"./services": {
"types": "./dist/services/index.d.ts",
"import": "./dist/services/index.js",
"require": "./cjs/dist/services/index.js"
}
}
}📖 Related Documentation
- Main README:
/packages/headless-components/README.md- Architecture guidelines - Implementation Status:
/docs/IMPLEMENTATION_STATUS.md- Complete component checklist - API Documentation:
/docs/api/ECOM_INTERFACE.md- E-commerce API specifications - Contributing:
/CONTRIBUTING.md- Contribution guidelines
🔍 Examples
Check out these example projects using this package:
examples/astro-stores-demo/- Complete store implementationexamples/astro-restaurants-olo-demo/- Online ordering with cart
