E-Commerce Development

•
1
•

Implements robust shopping cart logic, secure payment processing, and scalable inventory management systems for online stores.

This skill provides Claude with advanced patterns for building end-to-end e-commerce applications. It includes standardized implementations for Zustand-based cart state management, comprehensive Stripe API integration (including Checkout and Payment Intents), and React-based payment forms. Developers can leverage these patterns to handle complex inventory operations using optimistic locking via Prisma, manage multi-step order fulfillment workflows, and implement efficient product catalog search systems. It is ideal for building high-performance storefronts where data integrity and transaction security are paramount.

Características Principales

01Inventory management system with optimistic locking to prevent overselling
02Searchable product catalog patterns with filtering and pagination
03Stripe integration for checkout sessions, payment intents, and webhooks
04Order fulfillment workflows and status tracking logic
051 GitHub stars
06Persistent shopping cart state management using Zustand and middleware

Casos de Uso

01Building a custom headless e-commerce storefront with Next.js and Stripe
02Developing automated payment confirmation and order processing webhooks
03Implementing high-concurrency inventory reservation and release systems
name description domain version tags triggers
e-commerce
E-commerce platforms, payment processing, and shopping cart patterns
domain-applications
1.0.0
e-commerce
payments
stripe
cart
checkout
inventory
keywords context_boost context_penalty priority
primary secondary
e-commerce
ecommerce
shopping cart
checkout
payment
stripe
inventory
order
product catalog
discount
coupon
shipping
shop
store
buy
sell
transaction
game
mobile
desktop
high

E-Commerce Development

Overview

Building e-commerce applications with shopping carts, payment processing, inventory management, and order fulfillment.


Shopping Cart

Cart State Management

interface CartItem {
  productId: string;
  variantId?: string;
  quantity: number;
  price: number;
  name: string;
  image: string;
}

interface Cart {
  id: string;
  items: CartItem[];
  subtotal: number;
  tax: number;
  shipping: number;
  total: number;
  discountCode?: string;
  discountAmount: number;
}

// Zustand cart store
import { create } from 'zustand';
import { persist } from 'zustand/middleware';

interface CartStore {
  cart: Cart;
  addItem: (item: Omit<CartItem, 'quantity'>, quantity?: number) => void;
  updateQuantity: (productId: string, quantity: number) => void;
  removeItem: (productId: string) => void;
  clearCart: () => void;
  applyDiscount: (code: string) => Promise<void>;
}

const useCartStore = create<CartStore>()(
  persist(
    (set, get) => ({
      cart: createEmptyCart(),

      addItem: (item, quantity = 1) => {
        set((state) => {
          const existingIndex = state.cart.items.findIndex(
            (i) => i.productId === item.productId && i.variantId === item.variantId
          );

          const newItems = [...state.cart.items];
          if (existingIndex >= 0) {
            newItems[existingIndex].quantity += quantity;
          } else {
            newItems.push({ ...item, quantity });
          }

          return { cart: recalculateCart({ ...state.cart, items: newItems }) };
        });
      },

      updateQuantity: (productId, quantity) => {
        set((state) => {
          if (quantity <= 0) {
            return {
              cart: recalculateCart({
                ...state.cart,
                items: state.cart.items.filter((i) => i.productId !== productId),
              }),
            };
          }

          const newItems = state.cart.items.map((item) =>
            item.productId === productId ? { ...item, quantity } : item
          );

          return { cart: recalculateCart({ ...state.cart, items: newItems }) };
        });
      },

      removeItem: (productId) => {
        set((state) => ({
          cart: recalculateCart({
            ...state.cart,
            items: state.cart.items.filter((i) => i.productId !== productId),
          }),
        }));
      },

      clearCart: () => set({ cart: createEmptyCart() }),

      applyDiscount: async (code) => {
        const discount = await validateDiscountCode(code);
        set((state) => ({
          cart: recalculateCart({
            ...state.cart,
            discountCode: code,
            discountAmount: discount.amount,
          }),
        }));
      },
    }),
    { name: 'cart-storage' }
  )
);

function recalculateCart(cart: Cart): Cart {
  const subtotal = cart.items.reduce(
    (sum, item) => sum + item.price * item.quantity,
    0
  );
  const tax = subtotal * 0.1; // 10% tax
  const shipping = subtotal > 100 ? 0 : 9.99;
  const total = subtotal + tax + shipping - cart.discountAmount;

  return { ...cart, subtotal, tax, shipping, total };
}

Payment Processing

Stripe Integration

import Stripe from 'stripe';

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2023-10-16',
});

// Create checkout session
async function createCheckoutSession(cart: Cart, customerId?: string) {
  const session = await stripe.checkout.sessions.create({
    mode: 'payment',
    customer: customerId,
    line_items: cart.items.map((item) => ({
      price_data: {
        currency: 'usd',
        product_data: {
          name: item.name,
          images: [item.image],
        },
        unit_amount: Math.round(item.price * 100),
      },
      quantity: item.quantity,
    })),
    discounts: cart.discountCode
      ? [{ coupon: cart.discountCode }]
      : undefined,
    shipping_address_collection: {
      allowed_countries: ['US', 'CA', 'GB'],
    },
    success_url: `${process.env.APP_URL}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.APP_URL}/cart`,
    metadata: {
      cartId: cart.id,
    },
  });

  return session;
}

// Create payment intent (for custom checkout)
async function createPaymentIntent(amount: number, customerId?: string) {
  const paymentIntent = await stripe.paymentIntents.create({
    amount: Math.round(amount * 100),
    currency: 'usd',
    customer: customerId,
    automatic_payment_methods: { enabled: true },
  });

  return {
    clientSecret: paymentIntent.client_secret,
    paymentIntentId: paymentIntent.id,
  };
}

// Webhook handler
async function handleStripeWebhook(body: string, signature: string) {
  const event = stripe.webhooks.constructEvent(
    body,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET!
  );

  switch (event.type) {
    case 'checkout.session.completed': {
      const session = event.data.object as Stripe.Checkout.Session;
      await fulfillOrder(session);
      break;
    }

    case 'payment_intent.succeeded': {
      const paymentIntent = event.data.object as Stripe.PaymentIntent;
      await handlePaymentSuccess(paymentIntent);
      break;
    }

    case 'payment_intent.payment_failed': {
      const paymentIntent = event.data.object as Stripe.PaymentIntent;
      await handlePaymentFailure(paymentIntent);
      break;
    }
  }
}

React Stripe Elements

import { loadStripe } from '@stripe/stripe-js';
import {
  Elements,
  PaymentElement,
  useStripe,
  useElements,
} from '@stripe/react-stripe-js';

const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_KEY!);

function CheckoutForm({ clientSecret }: { clientSecret: string }) {
  const stripe = useStripe();
  const elements = useElements();
  const [error, setError] = useState<string | null>(null);
  const [processing, setProcessing] = useState(false);

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    if (!stripe || !elements) return;

    setProcessing(true);
    setError(null);

    const { error: submitError } = await stripe.confirmPayment({
      elements,
      confirmParams: {
        return_url: `${window.location.origin}/checkout/success`,
      },
    });

    if (submitError) {
      setError(submitError.message || 'Payment failed');
      setProcessing(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <PaymentElement />
      {error && <div className="error">{error}</div>}
      <button type="submit" disabled={!stripe || processing}>
        {processing ? 'Processing...' : 'Pay Now'}
      </button>
    </form>
  );
}

function CheckoutPage() {
  const [clientSecret, setClientSecret] = useState('');

  useEffect(() => {
    fetch('/api/create-payment-intent', {
      method: 'POST',
      body: JSON.stringify({ amount: cart.total }),
    })
      .then((res) => res.json())
      .then((data) => setClientSecret(data.clientSecret));
  }, []);

  if (!clientSecret) return <Loading />;

  return (
    <Elements
      stripe={stripePromise}
      options={{ clientSecret, appearance: { theme: 'stripe' } }}
    >
      <CheckoutForm clientSecret={clientSecret} />
    </Elements>
  );
}

Inventory Management

interface Product {
  id: string;
  name: string;
  sku: string;
  price: number;
  inventory: number;
  lowStockThreshold: number;
  variants: ProductVariant[];
}

interface ProductVariant {
  id: string;
  name: string;
  sku: string;
  price: number;
  inventory: number;
  attributes: Record<string, string>;
}

// Inventory operations with optimistic locking
async function reserveInventory(items: CartItem[]): Promise<boolean> {
  return prisma.$transaction(async (tx) => {
    for (const item of items) {
      const product = await tx.product.findUnique({
        where: { id: item.productId },
        select: { inventory: true, version: true },
      });

      if (!product || product.inventory < item.quantity) {
        throw new Error(`Insufficient inventory for ${item.name}`);
      }

      // Optimistic locking with version check
      const updated = await tx.product.updateMany({
        where: {
          id: item.productId,
          version: product.version,
          inventory: { gte: item.quantity },
        },
        data: {
          inventory: { decrement: item.quantity },
          version: { increment: 1 },
        },
      });

      if (updated.count === 0) {
        throw new Error(`Concurrent modification for ${item.name}`);
      }
    }

    return true;
  });
}

// Release inventory (on order cancellation)
async function releaseInventory(orderId: string) {
  const order = await prisma.order.findUnique({
    where: { id: orderId },
    include: { items: true },
  });

  await prisma.$transaction(
    order.items.map((item) =>
      prisma.product.update({
        where: { id: item.productId },
        data: { inventory: { increment: item.quantity } },
      })
    )
  );
}

// Low stock alerts
async function checkLowStock() {
  const lowStockProducts = await prisma.product.findMany({
    where: {
      inventory: { lte: prisma.product.fields.lowStockThreshold },
    },
  });

  for (const product of lowStockProducts) {
    await sendLowStockAlert(product);
  }
}

Order Management

enum OrderStatus {
  PENDING = 'pending',
  PAID = 'paid',
  PROCESSING = 'processing',
  SHIPPED = 'shipped',
  DELIVERED = 'delivered',
  CANCELLED = 'cancelled',
  REFUNDED = 'refunded',
}

interface Order {
  id: string;
  userId: string;
  status: OrderStatus;
  items: OrderItem[];
  subtotal: number;
  tax: number;
  shipping: number;
  total: number;
  shippingAddress: Address;
  billingAddress: Address;
  paymentIntentId: string;
  trackingNumber?: string;
  createdAt: Date;
  updatedAt: Date;
}

// Create order from checkout session
async function fulfillOrder(session: Stripe.Checkout.Session) {
  const order = await prisma.order.create({
    data: {
      userId: session.client_reference_id!,
      status: OrderStatus.PAID,
      paymentIntentId: session.payment_intent as string,
      subtotal: session.amount_subtotal! / 100,
      total: session.amount_total! / 100,
      shippingAddress: JSON.parse(session.metadata!.shippingAddress),
      items: {
        create: JSON.parse(session.metadata!.items),
      },
    },
  });

  // Reserve inventory
  await reserveInventory(order.items);

  // Send confirmation email
  await sendOrderConfirmation(order);

  // Notify fulfillment system
  await notifyFulfillment(order);

  return order;
}

// Order status updates
async function updateOrderStatus(orderId: string, status: OrderStatus) {
  const order = await prisma.order.update({
    where: { id: orderId },
    data: { status },
  });

  // Send notification
  await sendOrderStatusUpdate(order);

  return order;
}

Product Catalog

// Product search with filters
async function searchProducts(params: {
  query?: string;
  category?: string;
  minPrice?: number;
  maxPrice?: number;
  sortBy?: 'price' | 'name' | 'createdAt';
  sortOrder?: 'asc' | 'desc';
  page?: number;
  limit?: number;
}) {
  const {
    query,
    category,
    minPrice,
    maxPrice,
    sortBy = 'createdAt',
    sortOrder = 'desc',
    page = 1,
    limit = 20,
  } = params;

  const where: Prisma.ProductWhereInput = {
    status: 'active',
    ...(query && {
      OR: [
        { name: { contains: query, mode: 'insensitive' } },
        { description: { contains: query, mode: 'insensitive' } },
      ],
    }),
    ...(category && { categoryId: category }),
    ...(minPrice && { price: { gte: minPrice } }),
    ...(maxPrice && { price: { lte: maxPrice } }),
  };

  const [products, total] = await Promise.all([
    prisma.product.findMany({
      where,
      orderBy: { [sortBy]: sortOrder },
      skip: (page - 1) * limit,
      take: limit,
      include: {
        category: true,
        images: true,
        variants: true,
      },
    }),
    prisma.product.count({ where }),
  ]);

  return {
    products,
    pagination: {
      page,
      limit,
      total,
      totalPages: Math.ceil(total / limit),
    },
  };
}

Related Skills

  • [[payment-processing]] - Payment systems
  • [[backend]] - API development
  • [[database]] - Data modeling