RaisFastRaisFast
Full-Stack Development

E-commerce Tutorial

Build an online store with products, shopping cart, orders, and payment integration.

What You'll Build

An e-commerce store with:

  • Product catalog with categories
  • Shopping cart (guest + authenticated)
  • Checkout flow
  • Order management
  • Payment integration

Built-in E-commerce Module

RaisFast has built-in e-commerce APIs — you don't need to define content types for core commerce:

ModuleEndpointsDescription
Products/api/v1/admin/productsCRUD for products
Categories/api/v1/admin/categoriesProduct categories
Orders/api/v1/admin/ordersOrder management
Payments/api/v1/admin/paymentsPayment processing
Wallets/api/v1/admin/walletsUser wallet balances

Step 1 — Create Products

# Create a product category
curl -X POST http://localhost:9898/api/v1/admin/categories \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Electronics","slug":"electronics"}'

# Create a product
curl -X POST http://localhost:9898/api/v1/admin/products \
  -H "Authorization: Bearer TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Wireless Headphones",
    "slug": "wireless-headphones",
    "price": 99.99,
    "currency": "USD",
    "stock": 50,
    "description": "Premium wireless headphones with noise cancellation",
    "category_id": "CATEGORY_ID"
  }'

Step 2 — Product Catalog (Frontend)

import { client } from "@/lib/client";
import { useState, useEffect } from "react";

export function ProductCatalog() {
  const [products, setProducts] = useState([]);
  const [cart, setCart] = useState([]);

  useEffect(() => {
    client.setToken(localStorage.getItem("access_token")!);
    client.products.list({ page: 1, limit: 20 }).then((res) => {
      setProducts(res.data);
    });
  }, []);

  function addToCart(product) {
    setCart((prev) => {
      const existing = prev.find((item) => item.id === product.id);
      if (existing) {
        return prev.map((item) =>
          item.id === product.id
            ? { ...item, quantity: item.quantity + 1 }
            : item
        );
      }
      return [...prev, { ...product, quantity: 1 }];
    });
  }

  return (
    <div className="grid grid-cols-3 gap-6">
      {products.map((product) => (
        <div key={product.id} className="border rounded-lg p-4">
          <h3 className="font-semibold">{product.name}</h3>
          <p className="text-gray-600 text-sm mt-1">{product.description}</p>
          <div className="flex justify-between items-center mt-4">
            <span className="text-lg font-bold">${product.price}</span>
            <button
              onClick={() => addToCart(product)}
              className="px-4 py-2 bg-blue-600 text-white rounded"
            >
              Add to Cart
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

Step 3 — Checkout Flow

async function checkout(cart, shippingAddress) {
  // 1. Create an order
  const order = await client.orders.create({
    items: cart.map((item) => ({
      product_id: item.id,
      quantity: item.quantity,
      price: item.price,
    })),
    shipping_address: shippingAddress,
  });

  // 2. Initiate payment
  const payment = await client.payments.create({
    order_id: order.id,
    method: "wallet", // or "stripe", "alipay", etc.
  });

  return { order, payment };
}

Step 4 — Order Management

export function OrderHistory() {
  const [orders, setOrders] = useState([]);

  useEffect(() => {
    client.orders.list({ page: 1, limit: 20 }).then((res) => {
      setOrders(res.data);
    });
  }, []);

  return (
    <div className="space-y-4">
      {orders.map((order) => (
        <div key={order.id} className="border rounded-lg p-4">
          <div className="flex justify-between">
            <span className="font-semibold">Order #{order.id.slice(-8)}</span>
            <span className="text-sm text-gray-500">{order.status}</span>
          </div>
          <div className="mt-2 text-sm text-gray-600">
            {order.items.length} items — ${order.total}
          </div>
        </div>
      ))}
    </div>
  );
}

Custom Product Fields with Content Types

If the built-in product schema isn't enough, extend with a content type:

name = "ProductExtra"
table = "product_extras"
plural = "product_extras"

[fields.product_id]
type = "text"
required = true

[fields.specs]
type = "json"

[fields.weight]
type = "number"

[fields.dimensions]
type = "json"

Next Step

Ready to deploy? Follow the Deployment Guide.

On this page