npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cimplify/sdk

v0.57.0

Published

Cimplify Commerce SDK for storefronts

Readme

@cimplify/sdk

The official TypeScript SDK for building storefronts with the Cimplify Commerce Engine. Typed fetch client + 90+ React components + Server-Components helpers + an in-process mock that mirrors the production API.

Where to start

| Goal | Read | |---|---| | Scaffold a storefront and ship it | Storefronts guide | | Architectural rules + agent contract | AGENTS.md | | Step-by-step task walkthroughs | RECIPES.md | | SDK ↔ backend schema contract | CONTRACTS.md | | Pricing flow internals | ./sdk-pricing-flow.md |

Installation

bun add @cimplify/sdk          # bun (recommended)
npm install @cimplify/sdk
yarn add @cimplify/sdk

Public exports

| Subpath | Use | |---|---| | @cimplify/sdk | Browser-safe typed client (createCimplifyClient), domain types, Result<T, E> | | @cimplify/sdk/react | 90+ components + 30+ hooks (useCart, useProducts, <CataloguePage>, <CartDrawer>, …) | | @cimplify/sdk/server | Server Components / Server Actions: getServerClient(), tags.*, revalidate* | | @cimplify/sdk/utils | Money helpers, formatting, slug helpers | | @cimplify/sdk/advanced | Lower-level escape hatches | | @cimplify/sdk/mock | Programmatic mock for tests / MSW | | @cimplify/sdk/mock/msw | MSW handlers wrapping the in-process mock | | @cimplify/sdk/testing | Test harness — zod schemas, createTestClient, fixtures, assertX helpers | | @cimplify/sdk/testing/suite | Pre-baked vitest suites: createBrandSuite, createCartFlowSuite, createContractSuite | | @cimplify/sdk/styles.css | Pre-compiled Tailwind utilities for the React components |

Mock storefront API

This package ships an embeddable mock storefront API used by tests and local dev:

bunx @cimplify/sdk mock --seed <default|retail|fashion|…>   # standalone HTTP server on :8787

Or import it programmatically via @cimplify/sdk/mock / @cimplify/sdk/mock/msw.

Component registry

@cimplify/sdk ships a registry of ejectable components at ./registry/*.json (60+ entries) — same shadcn-style pattern: cimplify add product-grid copies the component source into your project so you can edit it, with imports already rewritten to @cimplify/sdk / @cimplify/sdk/react.

The registry data lives here; the add / list commands live in @cimplify/cli.

CLI moved

Everything else — init, login, projects, link, deploy, env, domains, logs, etc. — lives in the dedicated CLI package:

npm i -g @cimplify/cli      # one-time install
cimplify --help             # full surface

# Or zero-install:
bunx @cimplify/cli deploy

See @cimplify/cli for the full subcommand list.

Quick start

import { createCimplifyClient } from "@cimplify/sdk";

const client = createCimplifyClient({
  publicKey: process.env.NEXT_PUBLIC_CIMPLIFY_PUBLIC_KEY,
});

// Catalogue
const products = await client.catalogue.getProducts({ limit: 24 });
if (!products.ok) throw products.error;

const single = await client.catalogue.getProductBySlug("studio-tee-natural");
const variants = await client.catalogue.getVariants("prod_xyz");

// Cart — flat add-to-cart payload (variant + add-ons go on the body, not nested)
await client.cart.addItem({
  item_id: "prod_studio-tee-natural",
  quantity: 1,
  variant_id: "var_studio-tee-natural_size_s",
  add_on_options: ["addopt_gift_wrap"],
  special_instructions: "Please ship without invoice.",
});

const cart = await client.cart.get();
await client.cart.updateQuantity("ci_…", 2);
await client.cart.removeItem("ci_…");
await client.cart.applyCoupon("WELCOME10");

// Auth — single contact arg, then `(contact, code)` to verify
await client.auth.requestOtp("+233244000000");
await client.auth.verifyOtp("+233244000000", "123456");
await client.auth.logout();

Every call returns Result<T, CimplifyError>. Always check .ok:

const r = await client.catalogue.getProducts();
if (!r.ok) {
  console.error(r.error.code, r.error.message);
  return;
}
console.log(r.value.items);

React components

"use client";
import {
  CimplifyProvider,
  CartDrawerProvider,
  CartDrawer,
  CataloguePage,
  ProductPage,
  CartPage,
  CheckoutPage,
  CimplifyAccount,
  useCart,
  useCartDrawer,
} from "@cimplify/sdk/react";

function Root({ children }) {
  return (
    <CimplifyProvider client={client}>
      <CartDrawerProvider>
        {children}
        <CartDrawer onCheckout={() => router.push("/checkout")} />
      </CartDrawerProvider>
    </CimplifyProvider>
  );
}

90+ components ship — variant-aware product cards, customizers (variant / add-on / bundle / composite / billing-plan / customer-input / scheduling), full pages (<CataloguePage>, <ProductPage>, <CartPage>, <CheckoutPage>, <SearchPage>, <CimplifyAccount>), cart drawer with free-shipping progress, primitives (<Price>, <QuantitySelector>, <DealBanner>, <DeliveryEstimate>, <ChatWidget>).

Server Components (Next.js App Router)

import { getServerClient, tags, revalidateProducts } from "@cimplify/sdk/server";
import { unstable_cacheTag as cacheTag, unstable_cacheLife as cacheLife } from "next/cache";

async function getCatalogue() {
  "use cache";
  cacheTag(tags.products());
  cacheLife("hours");
  const r = await getServerClient().catalogue.getProducts({ limit: 24 });
  if (!r.ok) throw new Error(r.error.message);
  return r.value.items;
}

// In a Server Action after a mutation:
"use server";
async function refreshProducts() {
  await revalidateProducts();
}

Testing harness

Every scaffolded storefront ships with a 30-second feedback loop:

bun run check              # typecheck + lint + brand + cart-flow + contract suites
bun run check:brand        # schema invariants on lib/brand.ts
bun run check:cart         # add → dedupe → remove against in-process mock
bun run check:contract     # validates payload + response shapes
bun run check:visual       # Playwright snapshots (fashion ref template)

Custom test cases use the extend hook on the suites:

import { createCartFlowSuite } from "@cimplify/sdk/testing/suite";
import { brand } from "../lib/brand";
import { expect } from "vitest";

createCartFlowSuite({
  seed: brand.mock.seed,
  businessId: brand.mock.businessId,
  extend: ({ getHandle, it }) => {
    it("every product priced in GHS", async () => {
      const list = await getHandle().client.catalogue.getProducts();
      if (!list.ok) throw list.error;
      for (const p of list.value.items ?? []) expect(p.currency).toBe("GHS");
    });
  },
});

The mock is the oracle. createTestClient({ seed }) boots the same Hono mock you run locally, in-process, via the SDK's first-class fetch injection — parallel-safe, no global mutation. See RECIPES.md for the full workflow.

Money

All monetary values use the branded Money type — string at runtime, distinct from plain string at compile time.

import { money, formatPrice, isOnSale, getDiscountPercentage, type Money } from "@cimplify/sdk";

const price = money("29.99");
parseFloat(price); // 29.99

formatPrice(29.99, "GHS"); // "GH₵29.99"

if (isOnSale(product)) console.log(`${getDiscountPercentage(product)}% off`);

Error handling

import { CimplifyError } from "@cimplify/sdk";

const r = await client.cart.addItem({ item_id: "invalid", quantity: 1 });
if (!r.ok && r.error instanceof CimplifyError) {
  console.error(r.error.code, r.error.message, r.error.retryable);
}

For schema-shape errors (in tests, contract validation), assertX helpers throw a typed SchemaViolationError with structured issues[] and an RFC 7807 toJSON():

import { assertCart, SchemaViolationError } from "@cimplify/sdk/testing";

try {
  assertCart(response);
} catch (e) {
  if (e instanceof SchemaViolationError) console.error(e.toJSON());
}

TypeScript

Domain types are exported from the root:

import type {
  Product, ProductWithDetails, ProductVariant,
  Category, Collection, Bundle, Composite,
  Cart, CartItem, Order, Customer,
} from "@cimplify/sdk";

// Schema-derived types from the testing entry:
import type { Brand, AddItemPayload, CheckoutResponse } from "@cimplify/sdk/testing";

License

MIT