Build an E-Commerce Platform with Next.js: Complete Starter Guide
Building an e-commerce platform is one of the most common web development projects, yet it remains one of the most complex. Between product catalogs, shopping carts, checkout flows, payment processing, order management, and inventory tracking, a production-ready e-commerce application requires dozens of interconnected features.
An e-commerce starter kit eliminates the months of setup by providing all of this infrastructure pre-built and ready to customize. This guide walks through building a complete e-commerce platform using Next.js 14, Stripe, and Supabase, with production-ready code examples at every step.
Core E-Commerce Architecture
Every e-commerce platform shares a common architecture regardless of scale:
- Product catalog with categories, search, and filtering
- Shopping cart with persistent state
- Checkout flow with payment processing
- Order management and tracking
- User accounts with order history
- Admin dashboard for inventory management
Our E-Commerce Starter template includes all of these features pre-built with Next.js 14, TypeScript, Tailwind CSS, Stripe payment processing, and Supabase for the database and authentication.
Product Catalog with Supabase
// lib/products.ts
import { supabase } from './supabase'
import { cache } from 'react'
export interface Product {
id: string
name: string
slug: string
description: string
price: number
images: string[]
category: string
inventory: number
rating: number
reviews: number
}
export const getProducts = cache(async (category?: string) => {
let query = supabase.from('products').select('*')
if (category && category !== 'all') {
query = query.eq('category', category)
}
const { data } = await query.order('created_at', { ascending: false })
return data as Product[]
})
export const getProduct = cache(async (slug: string) => {
const { data } = await supabase
.from('products')
.select('*')
.eq('slug', slug)
.single()
return data as Product | null
})Server Component Product Listing
// app/products/page.tsx
import { getProducts } from '@/lib/products'
import { ProductCard } from './ProductCard'
import { CategoryFilter } from './CategoryFilter'
export default async function ProductsPage({
searchParams,
}: {
searchParams: { category?: string }
}) {
const products = await getProducts(searchParams.category)
return (
<div className="mx-auto max-w-7xl px-4 py-8">
<h1 className="text-3xl font-bold">All Products</h1>
<CategoryFilter active={searchParams.category} />
<div className="mt-8 grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
{products.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
</div>
)
}Shopping Cart with Zustand
// store/cart.ts
import { create } from 'zustand'
import { persist } from 'zustand/middleware'
interface CartItem {
productId: string
name: string
price: number
quantity: number
image: string
}
interface CartStore {
items: CartItem[]
addItem: (item: CartItem) => void
removeItem: (productId: string) => void
updateQuantity: (productId: string, quantity: number) => void
clearCart: () => void
total: () => number
}
export const useCartStore = create<CartStore>()(
persist(
(set, get) => ({
items: [],
addItem: (item) => {
const items = get().items
const existing = items.find(i => i.productId === item.productId)
if (existing) {
set({
items: items.map(i =>
i.productId === item.productId
? { ...i, quantity: i.quantity + 1 }
: i
),
})
} else {
set({ items: [...items, item] })
}
},
removeItem: (productId) => {
set({ items: get().items.filter(i => i.productId !== productId) })
},
updateQuantity: (productId, quantity) => {
set({
items: get().items.map(i =>
i.productId === productId ? { ...i, quantity } : i
),
})
},
clearCart: () => set({ items: [] }),
total: () => get().items.reduce((sum, i) => sum + i.price * i.quantity, 0),
}),
{ name: 'cart-storage' }
)
)Stripe Checkout Integration
// app/api/checkout/route.ts
import { NextResponse } from 'next/server'
import Stripe from 'stripe'
import { auth } from '@/lib/auth'
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
export async function POST(req: Request) {
const session = await auth()
if (!session?.user) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
const { items } = await req.json()
const lineItems = items.map((item: any) => ({
price_data: {
currency: 'usd',
product_data: {
name: item.name,
images: [item.image],
},
unit_amount: Math.round(item.price * 100),
},
quantity: item.quantity,
}))
const checkout = await stripe.checkout.sessions.create({
customer_email: session.user.email!,
mode: 'payment',
line_items: lineItems,
success_url: `${process.env.NEXT_PUBLIC_APP_URL}/orders?success=true`,
cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/cart`,
metadata: { userId: session.user.id },
})
return NextResponse.json({ url: checkout.url })
}Order Management
When payment succeeds, a webhook creates the order:
// app/api/webhooks/stripe/route.ts
case 'checkout.session.completed': {
const checkoutSession = event.data.object as Stripe.Checkout.Session
const userId = checkoutSession.metadata?.userId
if (userId) {
await prisma.order.create({
data: {
userId,
email: checkoutSession.customer_email!,
total: checkoutSession.amount_total! / 100,
status: 'completed',
items: {
create: lineItems.map((item: any) => ({
productId: item.productId,
price: item.price,
quantity: item.quantity,
})),
},
},
})
}
break
}E-Commerce Templates Available
BreafIO offers over 200 templates including several e-commerce solutions. The E-Commerce Starter is our flagship e-commerce template with product management, cart, Stripe checkout, order tracking, and admin dashboard. Built with Next.js 14, TypeScript, Tailwind CSS, Supabase, and Stripe.
For multi-vendor marketplaces, the Multi-Vendor Marketplace template extends the base e-commerce platform with vendor onboarding, commission management, and Stripe Connect integration.
The Bottom Line
Building an e-commerce platform from scratch takes months. Product catalogs, cart state management, payment processing, and order management each require careful implementation. An e-commerce starter kit gives you all of this infrastructure pre-built, tested, and ready to customize. Focus on your product selection, pricing strategy, and customer experience โ not on rebuilding payment webhooks and cart logic.
Related Template
Try this production-ready starter kit to build your project faster.
Shop All Products
Wireless Headphones
Leather Backpack
Smart Watch
Sunglasses
E-Commerce Starter
Build your online store the smart way
Ready to Build?
Get started with our production-ready starter kits and ship your project faster.
Browse Starter Kits