Skip to content

Universal discount language, platform adapters, and UI primitives for ecommerce. Shopify, BigCommerce, WooCommerce, Magento.

License

Notifications You must be signed in to change notification settings

coreyepstein/discountkit

DiscountKit

Universal discount language, platform adapters, and UI primitives for ecommerce.

npm @discountkit/core CI Coverage License: MIT


Why DiscountKit?

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)

Quick Start

npm install @discountkit/core @discountkit/shopify

Create a discount and push to Shopify

import { 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);

Same discount, different platform -- zero changes

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);

Read from one platform, write to another

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);
}

Platform Comparison

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)

Packages

Package Description
@discountkit/core Universal types, Zod schemas, adapter interface, test utilities npm
@discountkit/shopify Shopify Admin GraphQL adapter npm
@discountkit/bigcommerce BigCommerce REST v2 adapter npm
@discountkit/woocommerce WooCommerce REST v3 adapter npm
@discountkit/magento Magento 2 REST adapter npm
@discountkit/react Headless React hooks + compound components npm
@discountkit/ui Styled UI kit with light/dark/system themes npm

Architecture

@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;
}

Examples

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

Development

pnpm install      # Install dependencies
pnpm build        # Build all packages
pnpm test         # Run tests
pnpm lint         # Lint
pnpm typecheck    # Type check

See CONTRIBUTING.md for the full development guide.

License

MIT

About

Universal discount language, platform adapters, and UI primitives for ecommerce. Shopify, BigCommerce, WooCommerce, Magento.

Topics

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors