Build a Complete E-Commerce App with Auth, Cart, CRUD, Zustand, Server Actions & Deployment
To solidify your skills, youโll now build a fully working E-Commerce Web App. This project will include:
- Product listing and detail pages
- Add to Cart (Zustand)
- Auth with
next-auth
- Admin-only product management (CRUD)
- Form handling via Server Actions
- Responsive layout + Tailwind styling
- Deployment to Vercel
๐งฑ Folder Structure Overview
src/
โโโ app/
โ โโโ page.tsx โ Home (Product Grid)
โ โโโ product/[id]/page.tsx โ Product Detail Page
โ โโโ admin/ โ Admin Dashboard (Protected)
โ โโโ cart/page.tsx โ Cart Page
โ โโโ api/products/route.ts โ CRUD API (GET, POST, etc.)
โโโ components/
โโโ lib/ โ DB (Prisma) and utils
โโโ store/ โ Zustand cart store
โโโ server/ โ Server Actions
๐ 1. Product Listing Page (Home)
๐น src/app/page.tsx
import { getAllProducts } from "@/server/actions/product";
import ProductCard from "@/components/ProductCard";
export default async function HomePage() {
const products = await getAllProducts();
return (
<main className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 p-6">
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</main>
);
}
๐ฆ 2. Cart Functionality with Zustand
๐น src/store/cart.ts
import { create } from "zustand";
type CartItem = { id: number; name: string; price: number; qty: number };
type Store = {
items: CartItem[];
add: (item: CartItem) => void;
remove: (id: number) => void;
};
export const useCart = create<Store>((set) => ({
items: [],
add: (item) =>
set((state) => {
const exists = state.items.find((i) => i.id === item.id);
if (exists) {
return {
items: state.items.map((i) =>
i.id === item.id ? { ...i, qty: i.qty + item.qty } : i
),
};
}
return { items: [...state.items, item] };
}),
remove: (id) => set((state) => ({ items: state.items.filter((i) => i.id !== id) })),
}));
๐น Add to Cart in Product Page
"use client";
import { useCart } from "@/store/cart";
export default function AddToCart({ product }) {
const { add } = useCart();
return (
<button
onClick={() => add({ ...product, qty: 1 })}
className="bg-green-600 text-white px-4 py-2 rounded"
>
Add to Cart
</button>
);
}
๐ 3. Authentication with next-auth
- Already covered in Module 9
- Used to restrict access to
/admin
routes - Only allow admins to add/edit/delete products
๐งฐ 4. Admin Panel (CRUD with Server Actions)
๐น Add Product Form
'use client';
import { addProduct } from '@/server/actions/product';
export default function AddProductForm() {
return (
<form action={addProduct} className="space-y-4">
<input name="name" required placeholder="Name" className="border p-2" />
<input name="price" type="number" required placeholder="Price" className="border p-2" />
<button className="bg-blue-600 text-white px-4 py-2">Add Product</button>
</form>
);
}
๐น Server Action (DB Insert)
// src/server/actions/product.ts
'use server';
import { prisma } from '@/lib/prisma';
export async function addProduct(formData: FormData) {
const name = formData.get('name') as string;
const price = Number(formData.get('price'));
await prisma.product.create({ data: { name, price } });
}
export async function getAllProducts() {
return prisma.product.findMany();
}
๐ฐ 5. Checkout Summary Page
๐น src/app/cart/page.tsx
'use client';
import { useCart } from '@/store/cart';
export default function CartPage() {
const { items, remove } = useCart();
const total = items.reduce((sum, item) => sum + item.price * item.qty, 0);
return (
<div className="p-6 space-y-4">
<h2 className="text-xl font-bold">Cart</h2>
{items.map((item) => (
<div key={item.id} className="flex justify-between">
<p>{item.name} x {item.qty}</p>
<button onClick={() => remove(item.id)} className="text-red-600">Remove</button>
</div>
))}
<hr />
<p className="text-lg">Total: โน{total.toFixed(2)}</p>
</div>
);
}
๐ 6. Deploy the Project on Vercel
- Connect GitHub repo โ Deploy on Vercel
- Set
.env.local
for database andNEXTAUTH_SECRET
- Set up a domain (optional)
- Enjoy your live full-stack app!
โ Summary
Feature | Implemented With |
---|---|
Routing & Layout | App Router , layout.tsx |
Reusable UI | Tailwind + Components |
Auth | next-auth |
Cart State | Zustand |
Server CRUD | Server Actions + Prisma + PostgreSQL |
Admin Panel | Protected route + role-based access |
Deployment | Vercel + GitHub + Env Vars |
๐ Congratulations! Youโve Built a Full-Stack App in Next.js 14 ๐
You now have the skills to build and deploy real-world projects using:
- App Router
- Server Components
- Server Actions
- State Management (Zustand + Redux)
- Auth, APIs, CMS, SEO, and more
๐ฆ Bonus Modules (Optional)
- ๐งช Testing with Playwright/Vitest
- ๐ฌ Live Chat with WebSockets (e.g., Pusher)
- ๐ i18n (Multi-language Setup)
- ๐ฑ Build a PWA (Progressive Web App)