Specialized skill for the Payload CMS Ecommerce plugin. Use this for configuring the plugin, working with ecommerce collections (products, carts, orders), and implementing frontend checkout flows.
This skill covers the official @payloadcms/plugin-ecommerce. It adds comprehensive ecommerce capabilities to Payload, including products, carts, orders, and payment processing.
pnpm add @payloadcms/plugin-ecommerce
payload.config.ts)import { ecommercePlugin } from "@payloadcms/plugin-ecommerce";
import { stripeAdapter } from "@payloadcms/plugin-ecommerce/payments/stripe";
export default buildConfig({
plugins: [
ecommercePlugin({
// active: true, // defaults to true
payments: {
paymentMethods: [
stripeAdapter({
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
}),
],
},
// Optional: Override default collections
// products: { slug: 'merch' },
}),
],
});
The plugin provides a React provider and hooks for interacting with the ecommerce API from your frontend (Next.js).
Wrap your application (or specific routes) with EcommerceProvider.
// src/components/providers/EcommerceProvider.tsx
"use client";
import { EcommerceProvider as PayloadEcommerceProvider } from "@payloadcms/plugin-ecommerce/client/react";
import { stripeAdapterClient } from "@payloadcms/plugin-ecommerce/payments/stripe";
export const EcommerceProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
return (
<PayloadEcommerceProvider
paymentMethods={[
stripeAdapterClient({
publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
}),
]}
>
{children}
</PayloadEcommerceProvider>
);
};
Import these from @payloadcms/plugin-ecommerce/client/react.
| Hook | Purpose | Returns |
|---|---|---|
useCart() | Manage shopping cart | cart, addItem, removeItem, updateItem, clearCart, isLoading |
usePayments() | Handle checkout | initiatePayment, confirmOrder, paymentMethods, activePaymentMethod |
useAddresses() | Manage shipping/billing | addresses, createAddress, updateAddress, deleteAddress |
useCurrency() | Currency formatting | currency, setCurrency, formatCurrency |
import { useCart } from "@payloadcms/plugin-ecommerce/client/react";
export const AddToCart = ({ productId }) => {
const { addItem, isLoading } = useCart();
return (
<button
onClick={() => addItem({ product: productId, quantity: 1 })}
disabled={isLoading}
>
Add to Cart
</button>
);
};
import { usePayments } from "@payloadcms/plugin-ecommerce/client/react";
export const CheckoutButton = () => {
const { initiatePayment, confirmOrder } = usePayments();
const handleCheckout = async () => {
// 1. Initiate (creates PaymentIntent on Stripe)
await initiatePayment("stripe", {
additionalData: {
/* ... */
},
});
// 2. Confirm (finalizes order)
await confirmOrder("stripe", {
additionalData: {
/* ... */
},
});
};
};
The plugin automatically registers several collections. You can override their slugs/configs in ecommercePlugin options.
productsThe core catalog item.
title, slug, price (JSON), images, stock (if inventory enabled), relatedProducts.variants collection and relationship.cartsStores temporary user selections.
items (array of product + quantity), total, user (relationship).ordersCompleted purchases.
orderedBy, items (snapshot of cart), total, status, paymentIntent.pending, succeeded, failed.transactionsLogs payment attempts/history.
order, amount, status, paymentMethod, externalId (e.g. Stripe ID).customersExtension of the auth collection (usually users).
stripeCustomerID, addresses (array).By default, the plugin applies secure defaults:
Use these types for type safety in your code:
import type { Product, Cart, Order } from "@/payload-types"; // Generated types
import type { EcommerceConfig } from "@payloadcms/plugin-ecommerce/types";