Ecommerce storefront
A product catalog with category filters and search, product detail view, and a cart kept in local state.
Catalog, product detail and cart screens driven by a typed in-memory product list. The cart is persisted to localStorage through a small hook, quantities can be adjusted inline, and the checkout form is explicitly a placeholder: it records the order locally and tells you where to plug in Stripe or Razorpay on the server.
- react
- ecommerce
- cart
- catalog
- tailwind
This preview is the template's actual file tree and source code — exactly what is copied into a new project. Codexa does not publish screenshots or mock-ups of templates; run the project to see it rendered.
Files13 files
import { useState, type FormEvent } from "react";
import { formatPrice } from "./products";
import type { useCart } from "./cart";
export function Cart({ cart, onBack }: { cart: ReturnType<typeof useCart>; onBack: () => void }) {
const [placed, setPlaced] = useState(false);
function checkout(e: FormEvent) {
e.preventDefault();
// PLACEHOLDER: send the cart to your server, create a Stripe/Razorpay order there, then redirect to the hosted checkout.
setPlaced(true);
cart.clear();
}
if (placed) {
return (
<div className="mx-auto max-w-md text-center">
<h1 className="text-2xl font-semibold">Order recorded locally</h1>
<p className="mt-2 text-slate-600">No payment was taken. Wire the checkout form to a payment provider on your server.</p>
<button type="button" onClick={onBack} className="mt-6 rounded-md bg-slate-900 px-4 py-2 text-sm text-white">
Continue shopping
</button>
</div>
);
}
return (
<div className="grid gap-8 lg:grid-cols-[1fr_360px]">
<section>
<h1 className="text-2xl font-semibold tracking-tight">Your cart</h1>
{cart.items.length === 0 ? (
<p className="mt-6 text-slate-500">
Your cart is empty.{" "}
<button type="button" onClick={onBack} className="text-blue-600">
Browse products
</button>
</p>
) : (
<ul className="mt-6 divide-y divide-slate-200">
{cart.items.map((l) => (
<li key={l.productId} className="flex items-center justify-between gap-4 py-4">
<div>
<p className="font-medium">{l.product.name}</p>
<p className="text-sm text-slate-500">{formatPrice(l.product.price)} each</p>
</div>
<div className="flex items-center gap-2">
<button type="button" onClick={() => cart.setQty(l.productId, l.qty - 1)} className="size-8 rounded-md border border-slate-300" aria-label={"Decrease quantity of " + l.product.name}>
−
</button>
<span className="w-6 text-center text-sm" aria-live="polite">
{l.qty}
</span>
<button type="button" onClick={() => cart.setQty(l.productId, l.qty + 1)} className="size-8 rounded-md border border-slate-300" aria-label={"Increase quantity of " + l.product.name}>
+
</button>
</div>
</li>
))}
</ul>
)}
</section>
<form onSubmit={checkout} className="h-fit space-y-3 rounded-xl border border-slate-200 p-5">
<h2 className="font-medium">Checkout (placeholder)</h2>
<label className="block text-sm">
<span>Email</span>
<input type="email" required className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2" />
</label>
<label className="block text-sm">
<span>Shipping address</span>
<textarea required className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2" rows={3} />
</label>
<div className="flex justify-between border-t border-slate-200 pt-3 text-sm">
<span>Total</span>
<span className="font-semibold">{formatPrice(cart.total)}</span>
</div>
<button type="submit" disabled={cart.items.length === 0} className="w-full rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white disabled:opacity-50">
Place order
</button>
<p className="text-xs text-slate-500">No payment provider is connected in this template.</p>
</form>
</div>
);
}
Dependencies
Documented from the template's package.json. The runtime has a prebuilt dependency set for Vite + React + TypeScript, so installs are fast.
| Package | Version |
|---|---|
| react | ^19.1.0 |
| react-dom | ^19.1.0 |
| vite | ^6.3.0 |
| @vitejs/plugin-react | ^4.4.0 |
| tailwindcss | ^4.1.0 |
| @tailwindcss/vite | ^4.1.0 |
| typescript | ^5.8.0 |
How it runs
- Framework
- Vite + React + TypeScript
- Dev command
- npm run dev
- Build command
- npm run build
- Output directory
- dist
- Port
- 5173
- Opens at
- /
- Difficulty
- intermediate
Projects run in an isolated sandbox with a live preview. Read the projects documentation for details on settings, snapshots and deployment.
Need the raw data? GET /api/v1/templates/vite-react-storefront returns this template with its files.
Build on Ecommerce storefront
Create a free account, start from this template, and ask the AI agent to turn it into your app.