Make a Shop App with JS

Make a Shop App with JS

DATE POSTED:4/14/2026

Build a responsive website using:

This gives you:

Simplest version to build first

Start with a very basic store:

Pages

Features

Easiest stack

Frontend

Backend

Hosting

Why this is easiest

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-site

Choose:

Then install Firebase and Zustand:

bashnpm install firebase zustand

Step 2: Set up Firebase

Create a Firebase project and enable:

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:

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:

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:

This is the easiest coded solution.

Part 2: Coming soon

I can now give you either:

  1. A full working starter project
  2. A super simple one-page shopping site
  3. A version with fake data first, no Firebase yet
  4. Firebase auth + cart + checkout structure