Operate multi-store catalogs
Manage supplier truth, tenant storefront merchandising, product variants, collections, artwork rules, server-resolved carts, and provider-neutral checkout.
@absolutejs/commercev0.40.1-beta.13betaCommerce & GrowthProvider-agnostic catalogs, checkout, payments, fulfillment, and aftercare with CustomCat, EasyPost, Resend, and Stripe adapters.
Provider-agnostic commerce primitives for multi-store catalogs, storefront merchandising, trusted server-side cart resolution, payments, fulfillment, order aftercare, decoration previews, and production packets. The host package owns the domain logic and adapter contracts; CustomCat, EasyPost, Resend, and Stripe integrations live in the commerce-adapters monorepo.
bun add @absolutejs/commerceProvider-agnostic commerce primitives for AbsoluteJS apps — so every shop isn't rebuilding cart, checkout, orders, and fulfillment from scratch.
The catalog domain separates canonical supplier truth from storefront merchandising:
CatalogProduct is a branded style such as SanMar PC54.
ProductVariant is one exact purchasable supplier SKU (color/size/options).
CatalogListing exposes that product in a particular corporate store with
store-specific copy, pricing, approved artwork, and customization rules.
CatalogCollection organizes large assortments without duplicating products.
CatalogSourceProvider is the adapter contract for supplier feeds and live
inventory.
Optional provider taxonomy discovery feeds durable categories and
subcategories without hardcoded provider lists.
Supplier sync checkpoints and batch variant upserts make large feed imports
resumable and efficient; listing queries filter by search, brand, category, and product type.
That model supports one supplier product being reused across hundreds of tenant catalogs while every store remains independently merchandised.
Use an authorized, verified, and licensed photograph of the exact supplier SKU or the exact store-owned blank as the default customization truth. Retain the source, SKU match, usage rights, and review evidence with the catalog record:
ProductPhotoPreview has no Three.js dependency. It renders bounded artwork overlays against the contained source image and uses the same clampPlacementTransform() geometry as designDimensions(), so preview and operator measurements cannot disagree. Decoration zones accept a normalized previewBox tied to that evidenced product image.
The optional @absolutejs/commerce/decoration-react entrypoint provides the 3D R3F/drei surface. Load it progressively and describe it as an approximate visualization unless the model is authored for the exact supplier variant.
DecorationItemInput.identity carries brand, style, SKU, supplier SKU, catalog/listing, and variant identity into OrderProductionSpec, spec.json, and the printable work order. Operators can therefore pull the exact blank without relying on a separate admin screen.
createStorefrontAftercareService() replaces one-off return tables with a single durable order-linked case substrate for returns, exchanges, payment disputes, and customer support. Guest access reuses the secret checkout token; owner and fleet views retain assignment, internal notes, public conversation, structured resolutions, optimistic transition fencing, and stable lifecycle events. Customer requests and notification delivery are separately gated. Signed payment dispute events correlate through the provider payment identity and upsert one case without exposing raw provider payloads. Approved full returns can enqueue a distinct post-delivery refund action, so shipped-order refunds never run through fulfillment cancellation.
createStorefrontAftercareEvidenceService() owns the private attachment and payment-dispute evidence lifecycle. Uploads begin in pending_scan, use leased inspection, and remain hidden from customers unless clean. Infected bytes stay quarantined, scanner failures fail closed, and terminal-case retention cleanup deletes through a host-supplied blob boundary. Dispute evidence jobs accept only clean case-owned attachments, preserve stable provider idempotency, and quarantine ambiguous submission outcomes. A retry is prohibited until a leased provider reconciliation confirms the intended effect was not applied; applied effects converge on the retained staged/submitted record. Reconciliation also retains non-secret field/purpose mismatch diagnostics without copying customer evidence values into operational metadata. Tenant-owned deadline policies control whether alerts run, whether overdue alerts are emitted, and up to six unique warning thresholds from 1 to 720 hours. The service emits idempotent deadline events through the case event substrate and records durable, audience-routed escalations with bounded acknowledgement deadlines. createStorefrontAftercareEscalationService() adds optimistic acknowledgement and assignment, leased and retryable host-supplied incident promotion, terminal resolution, and privacy-safe SLA/outcome analytics. Evidence effectiveness counts whether a staged/submitted bundle existed; it never returns evidence values, file identifiers, or customer content. Provider adapters implement reconcileDisputeEvidence and submitDisputeEvidence; the host independently gates reconciliation, staging, final payment-network submission, notification delivery, and incident promotion.
Cross-origin provider journey evidence
Hosted checkout and invoice pages run outside the application's origin, so no browser SDK can directly capture errors rendered there. Use withProviderJourneyCorrelation() to stamp a host-owned identity into provider metadata. Providers with fixed metadata slots can pass that slot as the third argument. Retain privacy-safe ProviderJourneyEvidence from host requests, provider APIs, webhooks, reconciliation, and customer reports, then call summarizeProviderJourney().
These Commerce names are compatibility adapters over @absolutejs/handoff. New cross-domain integrations should import the neutral handoff vocabulary directly; Commerce retains payment-specific naming for existing consumers.
The summary keeps customer-reported hosted-page outcomes separate from authoritative provider evidence and flags contradictions such as a hosted page reporting failure after a webhook confirmed success. Evidence intentionally excludes raw webhook payloads, credentials, card data, and customer data; hosts keep those in their own protected stores.
The ./react export includes a reusable StorefrontRenderer and listing/card controls, while ./client includes a storefront-scoped persistent cart store. Both remain provider-neutral and can be styled by the host without replacing the cart or checkout contracts.
FulfillmentCostQuoteProvider is the read-only preflight seam for providers that can price an exact set of fulfillment lines and destination. Quotes expose normalized item, shipping, and adjustment costs, but deliberately do not claim to reserve provider inventory or pricing. Spending applications refresh the quote immediately before authorization and bind final settlement to the provider's accepted cost.
Follows the same shape as @absolutejs/voice: a host package holds the agnostic logic + adapter contracts, and provider implementations live in the commerce-adapters monorepo (Apache-2.0).
The first slice is the carrier-agnostic shipping interface. Apps program against ShippingProvider; a carrier adapter (e.g. @absolutejs/commerce-easypost) implements it, so a shop can plug in whatever carrier account it already uses.
Canonical supplier products and variants stay separate from tenant-specific listings, collections, pricing, artwork, customization rules, and publication state.
The server resolves browser cart identities against ready storefront projections, rechecks policy and availability, and calculates canonical pricing before checkout.
Tenant-fenced provider installations, idempotent checkout intents, signed and deduplicated webhooks, durable receipts, refunds, and quarantine-safe retries.
Leased fulfillment jobs, provider reconciliation, guest-safe order access, lifecycle notifications, cancellation coordination, and return or dispute cases.
Product-photo and optional 3D decoration previews share placement geometry with production specifications and printable work orders.
Commerce coordinates durable boundaries instead of treating checkout as one provider call.
Exact-product media may come from a supplier or an authorized store source when it is verified and licensed for the exact SKU. Decorative or generated imagery must not silently replace product truth.
| Option | Allowed | Required evidence | Use |
|---|---|---|---|
| Supplier photograph | Yes | Supplier + exact SKU | Default product truth |
| Store photograph | Yes | Authorization + verification + license + exact SKU | Store-owned product truth |
| Generated/styled image | Conditional | Clearly labeled; never exact-product evidence | Merchandising only |
| Mismatched variant | No | Cannot prove color/style/view | Reject |
Outcomes
Manage supplier truth, tenant storefront merchandising, product variants, collections, artwork rules, server-resolved carts, and provider-neutral checkout.
Coordinate payment, fulfillment, order access, notifications, returns, disputes, evidence, refunds, and production packets through durable boundaries.
Hardening checklist
Follow in order
Use an authorized, verified, and licensed photograph of the exact supplier SKU or the exact store-owned blank as the default customization truth. Retain the source, SKU match, usage rights, and review evidence with the catalog record:
import { ProductPhotoPreview } from "@absolutejs/commerce/decoration-preview-react";The catalog domain separates canonical supplier truth from storefront merchandising:
import {
findVariantByOptions,
listingPriceCents,
type CatalogSourceProvider,
} from "@absolutejs/commerce";
const variant = findVariantByOptions(product.variants, {
Color: "Navy",
Size: "XL",
});
const price = listingPriceCents(product.listing, variant);The first slice is the carrier-agnostic shipping interface. Apps program against ShippingProvider; a carrier adapter (e.g. @absolutejs/commerce-easypost) implements it, so a shop can plug in whatever carrier account it already uses.
import type { ShippingProvider } from "@absolutejs/commerce";
import { createEasyPostProvider } from "@absolutejs/commerce-easypost";
const shipping: ShippingProvider = createEasyPostProvider({
apiKey: process.env.EASYPOST_API_KEY!,
});
const label = await shipping.buyCheapestLabel({ from, to, parcel });
// → { trackingNumber, labelUrl, carrier, service, amount, … }Program against the ShippingProvider contract and plug in a carrier adapter — the shop code never knows which carrier account is behind it.
import type { ShippingProvider } from '@absolutejs/commerce';
import { createEasyPostProvider } from '@absolutejs/commerce-easypost';
const shipping: ShippingProvider = createEasyPostProvider({
apiKey: process.env.EASYPOST_API_KEY ?? ''
});
const label = await shipping.buyCheapestLabel({ from, to, parcel });
// → { trackingNumber, labelUrl, carrier, service, amount, … }Provider implementations live in the commerce-adapters monorepo (Apache-2.0) and implement the contracts exported by the host package.
Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.
type AnalyticsOrderLine = {
product: string;
quantity: number;
amountTotal: number;
};@absolutejs/commerceThese playbooks show where this package fits, how to verify the combined system, and what changes before production.
Current package surface
Import surface · click to copy