@cartflare/button-sdk
v0.1.1
Published
JAMstack commerce platform SDK for Cloudflare infrastructure
Maintainers
Readme
CartFlare Button SDK
A modern, TypeScript-first e-commerce SDK for building customizable buy buttons and shopping cart experiences. Optimized for Cloudflare infrastructure and JAMstack architectures.
Features
Core Functionality
- Product Display: Render products with customizable layouts (vertical/horizontal)
- Shopping Cart: Full-featured cart with add, update, remove, and clear operations
- Checkout Integration: Seamless checkout flow with multiple payment providers
- Real-time Updates: Live cart state synchronization across components
- Persistent Storage: LocalStorage integration for cart persistence
- Event System: Comprehensive event hooks for customization
React Integration
- React Provider: Context-based state management for React applications
- Custom Hooks: Easy-to-use hooks for cart operations
- TypeScript Support: Full type safety with React components
- Server-Side Rendering: Compatible with Next.js and other SSR frameworks
Customization Options
- Flexible Layouts: Multiple product and cart layout options
- Style Customization: Extensive CSS styling configuration
- Text Localization: Customizable text for all UI elements
- Component Ordering: Control the display order of product elements
- DOM Event Handling: Custom event handlers for advanced interactions
Performance & Architecture
- Bundle Size Optimized: Tree-shakable modules with minimal footprint
- Multiple Formats: ESM, CJS, UMD, and minified builds available
- Type Declarations: Complete TypeScript definitions included
- Cloudflare Ready: Optimized for Workers and Pages deployment
Installation
Package Managers
# Using Bun (recommended)
bun install cartflare-button-sdk
# Using npm
npm install cartflare-button-sdk
# Using yarn
yarn add cartflare-button-sdk
# Using pnpm
pnpm add cartflare-button-sdkCDN Usage
<!-- UMD Build -->
<script src="https://unpkg.com/cartflare-button-sdk@latest/dist/cartflare.min.js"></script>
<!-- ESM Build -->
<script type="module">
import { createCartFlare } from 'https://unpkg.com/cartflare-button-sdk@latest/dist/index.esm.js';
</script>Quick Start
Basic Setup
import { createCartFlare } from 'cartflare-button-sdk';
// Initialize CartFlare
const cartflare = createCartFlare({
merchantId: 'your-merchant-id',
apiUrl: 'https://api.cartflare.com', // Optional
storefrontToken: 'your-storefront-token' // Optional
});
// Initialize the SDK
await cartflare.init();
// Add a product to cart
await cartflare.addToCart('variant-id', 1);
// Proceed to checkout
await cartflare.checkout();React Integration
import { CartFlareProvider, useCartFlare } from 'cartflare-button-sdk/react';
function App() {
return (
<CartFlareProvider config={{
merchantId: 'your-merchant-id',
ui: {
components: {
product: {
layout: 'vertical',
buttonDestination: 'cart'
}
}
}
}}>
<ProductComponent />
<CartComponent />
</CartFlareProvider>
);
}
function ProductComponent() {
const { addToCart, cart } = useCartFlare();
const handleAddToCart = async () => {
await addToCart('variant-id', 1);
};
return (
<div>
<button onClick={handleAddToCart}>
Add to Cart ({cart?.lineItems.length || 0} items)
</button>
</div>
);
}Configuration
Core Configuration
interface CartFlareConfig {
// Required
merchantId: string;
// Optional API settings
apiUrl?: string;
storefrontToken?: string;
// Cart behavior
cart?: {
startOpen?: boolean;
popup?: boolean;
sticky?: boolean;
contents?: {
note?: boolean;
noteDescription?: string;
};
templates?: {
footer?: string;
};
};
// UI customization
ui?: {
components?: {
product?: ProductComponentConfig;
cart?: CartComponentConfig;
};
styles?: StyleConfig;
};
// Event handlers
events?: {
afterInit?: (component: unknown) => void;
afterRender?: (component: unknown) => void;
beforeDestroy?: (component: unknown) => void;
};
}Product Component Configuration
interface ProductComponentConfig {
layout?: 'vertical' | 'horizontal';
buttonDestination?: 'cart' | 'checkout' | 'modal';
contents?: {
img?: boolean;
imgWithCarousel?: boolean;
title?: boolean;
description?: boolean;
price?: boolean;
button?: boolean;
buttonWithQuantity?: boolean;
quantity?: boolean;
};
text?: {
button?: string;
outOfStock?: string;
unavailable?: string;
};
order?: string[];
DOMEvents?: {
[key: string]: (event: Event, target: HTMLElement) => void;
};
}Cart Component Configuration
interface CartComponentConfig {
contents?: {
title?: boolean;
note?: boolean;
discountForm?: boolean;
};
text?: {
title?: string;
total?: string;
button?: string;
empty?: string;
noteDescription?: string;
notice?: string;
};
popup?: boolean;
startOpen?: boolean;
sticky?: boolean;
}Implementation Guide
Step 1: Basic Setup
Install the SDK
bun install cartflare-button-sdkCreate a CartFlare instance
import { createCartFlare } from 'cartflare-button-sdk'; const cartflare = createCartFlare({ merchantId: 'your-merchant-id' });Initialize the SDK
await cartflare.init();
Step 2: Product Display
Vanilla JavaScript
<div id="product-container"></div>
<script>
const productComponent = cartflare.createComponent('product', {
productId: 'product-id'
});
productComponent.render('#product-container');
</script>React Integration
import { ProductComponent } from 'cartflare-button-sdk/react';
function MyProduct() {
return (
<ProductComponent
productId="product-id"
config={{
layout: 'vertical',
contents: {
img: true,
title: true,
price: true,
button: true
}
}}
/>
);
}Step 3: Cart Management
Programmatic Cart Operations
// Add to cart
await cartflare.addToCart('variant-id', 2, {
customField: 'custom-value'
});
// Update line item
await cartflare.updateLineItem('line-item-id', 3);
// Remove line item
await cartflare.removeLineItem('line-item-id');
// Clear entire cart
await cartflare.clearCart();
// Get current cart state
const currentCart = cartflare.cart;
// Subscribe to cart changes
const unsubscribe = cartflare.subscribeToCart((cart) => {
console.log('Cart updated:', cart);
});
// Cleanup subscription
unsubscribe();React Hooks
import { useCartFlare } from 'cartflare-button-sdk/react';
function CartManager() {
const { cart, addToCart, updateLineItem, removeLineItem, clearCart, checkout } = useCartFlare();
return (
<div>
<h2>Shopping Cart ({cart?.lineItems.length || 0} items)</h2>
{cart?.lineItems.map((item) => (
<div key={item.id}>
<span>{item.title}</span>
<span>${item.price}</span>
<input
type="number"
value={item.quantity}
onChange={(e) => updateLineItem(item.id, parseInt(e.target.value))}
/>
<button onClick={() => removeLineItem(item.id)}>Remove</button>
</div>
))}
<button onClick={() => clearCart()}>Clear Cart</button>
<button onClick={() => checkout()}>Checkout</button>
</div>
);
}Step 4: Styling Customization
CSS Variables
:root {
--cartflare-product-max-width: 500px;
--cartflare-product-title-color: #333;
--cartflare-product-price-color: #666;
--cartflare-button-background: #007bff;
--cartflare-button-color: white;
}Configuration-based Styling
const cartflare = createCartFlare({
merchantId: 'your-merchant-id',
ui: {
styles: {
product: {
'@media (min-width: 601px)': {
'max-width': '400px'
},
title: {
'font-size': '18px',
'font-weight': '600',
'color': '#333'
},
price: {
'font-size': '16px',
'color': '#007bff'
},
button: {
'background-color': '#007bff',
'color': '#ffffff',
'padding': '12px 24px',
':hover': {
'background-color': '#0056b3'
}
}
}
}
}
});Step 5: Event Handling
Global Events
// Listen to cart events
document.addEventListener('cartflare:item:added', (event) => {
console.log('Item added:', event.detail);
});
document.addEventListener('cartflare:item:removed', (event) => {
console.log('Item removed:', event.detail);
});
document.addEventListener('cartflare:checkout:initiated', (event) => {
console.log('Checkout started:', event.detail);
});Component Events
const cartflare = createCartFlare({
merchantId: 'your-merchant-id',
events: {
afterInit: (component) => {
console.log('CartFlare initialized');
},
afterRender: (component) => {
console.log('Component rendered');
},
beforeDestroy: (component) => {
console.log('Component about to be destroyed');
}
}
});Custom DOM Events
const productComponent = cartflare.createComponent('product', {
productId: 'product-id'
});
// Add custom DOM event handlers
productComponent.config.ui.components.product.DOMEvents = {
click: (event, target) => {
console.log('Product clicked:', target);
},
mouseover: (event, target) => {
console.log('Product hovered:', target);
}
};Advanced Usage
Multiple Product Display
// Display multiple products
const productIds = ['product-1', 'product-2', 'product-3'];
productIds.forEach((productId, index) => {
const container = document.getElementById(`product-${index}`);
const component = cartflare.createComponent('product', { productId });
component.render(container);
});Custom Product Templates
const cartflare = createCartFlare({
merchantId: 'your-merchant-id',
ui: {
components: {
product: {
order: ['img', 'title', 'description', 'price', 'quantity', 'button'],
contents: {
imgWithCarousel: true,
description: true,
buttonWithQuantity: true
}
}
}
}
});Cart Popup Configuration
const cartflare = createCartFlare({
merchantId: 'your-merchant-id',
cart: {
startOpen: false,
popup: true,
sticky: true
},
ui: {
components: {
cart: {
popup: true,
startOpen: false,
sticky: true,
contents: {
title: true,
note: true,
discountForm: true
}
}
}
}
});API Reference
CartFlare Class
Methods
init(): Promise<void>- Initialize the SDKaddToCart(variantId: string, quantity?: number, properties?: Record<string, unknown>): Promise<Cart>- Add item to cartupdateLineItem(lineItemId: string, quantity: number): Promise<Cart>- Update item quantityremoveLineItem(lineItemId: string): Promise<Cart>- Remove item from cartclearCart(): Promise<void>- Clear entire cartcheckout(): Promise<void>- Initiate checkoutsubscribeToCart(callback: (cart: Cart | null) => void): () => void- Subscribe to cart changescreateComponent(type: 'product' | 'cart', options?: any): Component- Create UI componentdestroyComponent(component: Component): void- Destroy UI component
Properties
cart: Cart | null- Current cart state (readonly)
Data Types
Cart
interface Cart {
id: string;
lineItems: LineItem[];
subtotal: number;
total: number;
discount: number;
note?: string;
createdAt: string;
updatedAt: string;
}LineItem
interface LineItem {
id: string;
variantId: string;
title: string;
price: number;
quantity: number;
properties?: Record<string, unknown>;
}Product
interface Product {
id: string;
title: string;
description?: string;
price: number;
compareAtPrice?: number;
currency?: string;
images: ProductImage[];
variants: ProductVariant[];
}Development
Building from Source
# Clone the repository
git clone https://github.com/cartflare/cartflare-button-sdk.git
cd cartflare-button-sdk
# Install dependencies
bun install
# Development mode
bun run dev
# Build for production
bun run build
# Run tests
bun run test
# Type checking
bun run typecheck
# Linting
bun run lintProject Structure
src/
├── core/ # Core SDK implementation
│ └── cartflare.ts
├── components/ # UI components
│ ├── cartflare.ts # Vanilla JS components
│ └── react/ # React components
│ └── cartflare.tsx
├── types/ # TypeScript definitions
│ └── cart-types.ts
├── styles/ # Default CSS styles
│ └── cartflare.css
└── index.ts # Main entry pointBuild Outputs
dist/index.esm.js- ES Module builddist/index.js- CommonJS builddist/cartflare.js- UMD builddist/cartflare.min.js- Minified UMD builddist/index.d.ts- TypeScript declarations
Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
License
MIT License - see LICENSE file for details.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Submit a pull request
Support
- Documentation: https://docs.cartflare.com
- Issues: GitHub Issues
- Community: Discord Server
