Universal discount language, platform adapters, and UI primitives for ecommerce.
Every ecommerce platform has its own discount API -- different field names, different data shapes, different capabilities. Building discount management across platforms means writing brittle, platform-specific code that silently drops features when translating between systems.
DiscountKit solves this with a single universal discount model that captures every platform's capabilities without lossy normalization:
- Universal discount atoms -- one type system for percentage, fixed amount, free shipping, and BXGY discounts across all platforms
- Lossless round-trip adapters -- platform-specific fields preserved in typed
extensions, zero data loss on normalize/denormalize - Capability validation before you create -- know exactly what a platform supports (and what it silently drops) before making API calls
- Headless React primitives -- hooks and compound components for building any discount UI, any platform
- Styled UI kit -- drop-in discount management with CSS custom property theming (light, dark, system)
npm install @discountkit/core @discountkit/shopifyimport { createIncentive } from "@discountkit/core";
import { ShopifyAdapter } from "@discountkit/shopify";
const incentive = createIncentive({
title: "Summer Sale 20%",
value: { type: "percentage", percentage: 0.2 },
code: { type: "static", code: "SUMMER20" },
});
const shopify = new ShopifyAdapter({
shop: "my-store.myshopify.com",
accessToken: "shpat_...",
});
const result = await shopify.create(incentive);import { BigCommerceAdapter } from "@discountkit/bigcommerce";
// Same incentive object, different adapter
const bigcommerce = new BigCommerceAdapter({
storeHash: "abc123",
accessToken: "...",
});
// Check what this platform supports before creating
const validation = bigcommerce.validateCapabilities(incentive);
if (validation.warnings.length > 0) {
validation.warnings.forEach((w) => console.warn(w.message));
}
const result = await bigcommerce.create(incentive);import { ShopifyAdapter } from "@discountkit/shopify";
import { WooCommerceAdapter } from "@discountkit/woocommerce";
const shopify = new ShopifyAdapter({ shop: "...", accessToken: "..." });
const woo = new WooCommerceAdapter({ url: "...", consumerKey: "...", consumerSecret: "..." });
// Read from Shopify, get universal format
const result = await shopify.read("gid://shopify/DiscountCodeNode/123");
if (result.success) {
const universal = shopify.toNormalized(result.data);
// Push to WooCommerce -- same data, different platform
await woo.create(universal);
}Every adapter exposes capability validation so you know exactly what works before making API calls.
| Feature | Shopify | BigCommerce | WooCommerce | Magento |
|---|---|---|---|---|
| Percentage discount | Yes | Yes | Yes | Yes |
| Fixed amount discount | Yes | Yes | Yes | Yes |
| Free shipping | Yes | Yes | Yes | Warn |
| Buy X Get Y | Yes | Error | Warn | Yes |
| Static codes | Yes | Yes | Yes | Yes |
| Dynamic codes | Yes | Warn | Warn | Yes |
| Auto-apply (no code) | Yes | Warn | Warn | Yes |
| Subscription discounts | Yes | Warn | Warn | Warn |
| Per-type combine rules | Yes | Yes | Warn | Warn |
| Country restrictions | Yes | Yes | Yes | Warn |
| Customer segments | Yes | Yes | Yes | Yes |
| Product/collection scope | Yes | Yes | Yes | Yes |
Yes = fully supported | Warn = creates with warnings (feature silently dropped or approximated) | Error = blocks creation (cannot be represented)
| Package | Description | |
|---|---|---|
@discountkit/core |
Universal types, Zod schemas, adapter interface, test utilities | |
@discountkit/shopify |
Shopify Admin GraphQL adapter | |
@discountkit/bigcommerce |
BigCommerce REST v2 adapter | |
@discountkit/woocommerce |
WooCommerce REST v3 adapter | |
@discountkit/magento |
Magento 2 REST adapter | |
@discountkit/react |
Headless React hooks + compound components | |
@discountkit/ui |
Styled UI kit with light/dark/system themes |
@discountkit/core Universal Incentive model + Zod schemas
|
+-- @discountkit/shopify Shopify Admin GraphQL
+-- @discountkit/bigcommerce BigCommerce REST v2
+-- @discountkit/woocommerce WooCommerce REST v3
+-- @discountkit/magento Magento 2 REST
|
@discountkit/react Headless hooks + compound components
|
@discountkit/ui Styled components + CSS themes
Every adapter implements PlatformAdapter<T> with a standard interface:
interface PlatformAdapter<T> {
create(incentive: Incentive): Promise<PlatformResult<T>>;
read(id: string): Promise<PlatformResult<T>>;
update(id: string, incentive: Incentive): Promise<PlatformResult<T>>;
delete(id: string): Promise<PlatformResult<boolean>>;
list(filters?: ListFilters): Promise<PlatformResult<T[]>>;
toNormalized(platformDiscount: T): Incentive;
fromNormalized(incentive: Incentive): T;
validateCapabilities(incentive: Incentive): ValidationResult;
}| Example | Description |
|---|---|
examples/nextjs-shopify |
Next.js app with Shopify adapter + styled UI |
examples/react-multi-platform |
React app showing platform switching |
examples/node-api-only |
Express server using adapters without React |
pnpm install # Install dependencies
pnpm build # Build all packages
pnpm test # Run tests
pnpm lint # Lint
pnpm typecheck # Type checkSee CONTRIBUTING.md for the full development guide.