E-commerce Platform (Full Stack)
Part of the Full Stack Developer Roadmap
In short
An online store touches every part of the stack: a catalogue, a cart that survives refresh, real payments and an order history. Recruiters know exactly how hard each part is.
A complete online store — product catalog, cart, checkout with real payments, and order history — one of the most résumé-relevant full-stack projects you can build.

Think of it like this
The mithai shop at Diwali
The counter shows sweets with prices. You pick, they pack a box, you pay at the billing desk, and only after the payment clears does the delivery boy leave. Display, cart, payment, then fulfilment, in that strict order.
Watch it happen
From cart to paid order
checkout(cart)
1/6The cart sends only product ids and quantities. No prices from the browser.
The big ideas
What you need to know
Catalogue with search
Products with images, categories and filters, paginated on the server. Use SSG or ISR for product pages so they load fast.
A cart that survives
Keep the cart in the database for logged-in users and in localStorage for guests, then merge on login.
Server-side prices
Prices, discounts and totals are always recalculated on the server from the database.
Orders as a state machine
PENDING, PAID, SHIPPED, DELIVERED, CANCELLED. Only allowed moves, each one logged.
See it in code
Walk through the code
1"use server";2import { redirect } from "next/navigation";3export async function checkout(cart: { productId: string; qty: number }[]) {4 const products = await db.product.findMany({ where: { id: { in: cart.map((c) => c.productId) } } });5 const order = await db.order.create({ data: { userId: await currentUserId(), status: "PENDING" } });6 const session = await stripe.checkout.sessions.create({7 mode: "payment",8 line_items: products.map((p) => ({9 quantity: cart.find((c) => c.productId === p.id)!.qty,10 price_data: { currency: "inr", unit_amount: p.pricePaise, product_data: { name: p.name } },11 })),12 metadata: { orderId: order.id },13 success_url: `${process.env.APP_URL}/orders/${order.id}`, cancel_url: `${process.env.APP_URL}/cart`,14 });15 redirect(session.url!);16}1/4Load products from the database. Any price the browser might send is ignored.
A Next.js server action (stripe and db are your own lib clients). The browser sends what to buy, the server decides what it costs.
Save yourself the pain
Common mistakes
Oops
Reducing stock when an item is added to the cart.
Do this instead
Reduce stock when payment is confirmed, inside a transaction, and handle the 'sold out while paying' case.
Oops
Storing prices as floats like 499.99.
Do this instead
Store money as integers in the smallest unit (paise), and format only when displaying.
Your mission
First milestone: buy one thing
Quick check
Where should the order total that you charge the customer be calculated?
Go deeper
- 1Implement the full flow: browse, cart, checkout with Stripe, order confirmation.
- 2Handle inventory correctly under concurrent orders.
- 3Add an admin view for managing products and viewing orders.
More projects at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.