
Make a Shop App with JS
DATE POSTED:4/14/2026
Build a responsive website using:
- Next.js — frontend
- Firebase — database + auth
- Vercel — hosting
- Stripe — later for payments
This gives you:
- a normal website
- works on phones
- easy deployment
- no app store needed
Simplest version to build first
Start with a very basic store:
Pages
- Home page with products
- Product details page
- Cart page
- Login/signup page
- Checkout page
Features
- View products
- Add to cart
- Remove from cart
- Save orders
- Responsive design
Easiest stack
Frontend
- Next.js
- Tailwind CSS for styling
Backend
- Firebase Firestore
Hosting
- Vercel
Why this is easiest
- Next.js is beginner-friendly
- Tailwind makes styling fast
- Firebase avoids building your own backend
- Vercel makes deployment very easy
Recommended folder structure
bashshopping-site/ app/
page.js
product/[id]/page.js cart/page.js
login/page.js
checkout/page.js
components/
ProductCard.js
Navbar.js
lib/
firebase.js
cartStore.js
public/How to create it
Step 1: Create project
bashnpx create-next-app@latest shopping-site cd shopping-siteChoose:
- JavaScript or TypeScript
- App Router = yes
- Tailwind = yes
Then install Firebase and Zustand:
bashnpm install firebase zustand
Step 2: Set up Firebase
Create a Firebase project and enable:
- Firestore
- Authentication
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";
const firebaseConfig = {
apiKey: "YOUR_KEY",
authDomain: "YOUR_DOMAIN",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_BUCKET",
messagingSenderId: "YOUR_ID",
appId: "YOUR_APP_ID"
};
const app = initializeApp(firebaseConfig);
export const db = getFirestore(app);
export const auth = getAuth(app);Step 3: Add products in Firebase
Create a products collection.
Example product:
{
"name": "T-Shirt",
"price": 25,
"image": "https://via.placeholder.com/300",
"description": "Comfortable cotton T-shirt",
"category": "Clothing"
}Step 4: Create product list homepage
"use client";
import { useEffect, useState } from "react";
import { collection, getDocs } from "firebase/firestore";
import { db } from "../lib/firebase";
import Link from "next/link";
export default function HomePage() {
const [products, setProducts] = useState([]);
useEffect(() => {
async function fetchProducts() {
const querySnapshot = await getDocs(collection(db, "products"));
const items = querySnapshot.docs.map(doc => ({
id: doc.id,
...doc.data()
}));
setProducts(items);
}
fetchProducts();
}, []);
return (
<main className="p-6">
<h1 className="text-3xl font-bold mb-6">Shop</h1>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
{products.map(product => (
<Link key={product.id} href={`/product/${product.id}`}>
<div className="border rounded-xl p-4 shadow hover:shadow-lg">
<img
src={product.image}
alt={product.name}
className="w-full h-48 object-cover rounded"
/>
<h2 className="text-xl font-semibold mt-3">{product.name}</h2>
<p className="text-gray-600">${product.price}</p>
</div>
</Link>
))}
</div>
</main>
);
}Step 5: Add cart state
import { create } from "zustand";
export const useCartStore = create((set) => ({
cart: [],
addToCart: (product) =>
set((state) => {
const found = state.cart.find((item) => item.id === product.id);
if (found) {
return {
cart: state.cart.map((item) =>
item.id === product.id
? { ...item, qty: item.qty + 1 }
: item
)
};
}
return {
cart: [...state.cart, { ...product, qty: 1 }]
};
}),
removeFromCart: (id) =>
set((state) => ({
cart: state.cart.filter((item) => item.id !== id)
}))
}));Step 6: Product page
"use client";
import { doc, getDoc } from "firebase/firestore";
import { db } from "../../../lib/firebase";
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { useCartStore } from "../../../lib/cartStore";
export default function ProductPage() {
const params = useParams();
const [product, setProduct] = useState(null);
const addToCart = useCartStore((state) => state.addToCart);
useEffect(() => {
async function fetchProduct() {
const docRef = doc(db, "products", params.id);
const docSnap = await getDoc(docRef);
if (docSnap.exists()) {
setProduct({ id: docSnap.id, ...docSnap.data() });
}
}
fetchProduct();
}, [params.id]);
if (!product) return <p className="p-6">Loading...</p>;
return (
<main className="p-6 max-w-4xl mx-auto">
<img
src={product.image}
alt={product.name}
className="w-full max-w-md rounded mb-4"
/>
<h1 className="text-3xl font-bold">{product.name}</h1>
<p className="text-xl text-gray-600 mb-2">${product.price}</p>
<p className="mb-4">{product.description}</p>
<button
onClick={() => addToCart(product)}
className="bg-black text-white px-4 py-2 rounded"
>
Add to Cart
</button>
</main>
);
}Step 7: Cart page
"use client";
import { useCartStore } from "../../lib/cartStore";
export default function CartPage() {
const cart = useCartStore((state) => state.cart);
const removeFromCart = useCartStore((state) => state.removeFromCart);
const total = cart.reduce((sum, item) => sum + item.price * item.qty, 0);
return (
<main className="p-6">
<h1 className="text-3xl font-bold mb-6">Your Cart</h1>
{cart.length === 0 ? (
<p>Your cart is empty.</p>
) : (
<>
<div className="space-y-4">
{cart.map((item) => (
<div key={item.id} className="border p-4 rounded flex justify-between">
<div>
<h2 className="font-semibold">{item.name}</h2>
<p>${item.price} x {item.qty}</p>
</div>
<button
onClick={() => removeFromCart(item.id)}
className="text-red-500"
>
Remove
</button>
</div>
))}
</div>
<h2 className="text-2xl font-bold mt-6">Total: ${total.toFixed(2)}</h2>
<button className="mt-4 bg-black text-white px-4 py-2 rounded">
Checkout
</button>
</>
)}
</main>
);
}Step 8: Make it mobile-friendly
Tailwind already helps with this.
Important things:
- use responsive grid classes like grid-cols-1 sm:grid-cols-2 md:grid-cols-3
- keep buttons large enough to tap
- use max-w-* containers
- avoid tiny text
That makes it work well on phones in a browser.
Step 9: Deploy it
Push to GitHub, then deploy on Vercel.
bashgit init git add . git commit -m "initial shop site"Then:
- upload to GitHub
- import into Vercel
- add Firebase env vars if needed
- deploy
If you want the absolute easiest possible route
If you don’t care about coding much, use:
Shopify
Best if your goal is just to sell products.
Squarespace / Wix
Easier than coding, but less custom.
Medusa / Saleor
More advanced, not easiest.
My recommendation for you
If you want easy + flexible + modern, do this:
Build:
- Next.js
- Tailwind
- Firebase
- Vercel
This is the easiest coded solution.
Part 2: Coming soon
I can now give you either:
- A full working starter project
- A super simple one-page shopping site
- A version with fake data first, no Firebase yet
- Firebase auth + cart + checkout structure