Building a Production-Ready E-Commerce Platform with React: A Complete Walkthrough

Published: (December 20, 2025 at 05:34 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

TL;DR

I built a complete e-commerce frontend called ShopStyle using React 18, Tailwind CSS, and modern patterns. It features real‑time search, a persistent cart, dark mode, and 60 fps animations. This article breaks down the architecture, challenges, and key decisions.

Live Demo: https://shopstyle-demo.example.com
Source Code: https://github.com/yourusername/shopstyle

Goals

  • Create a realistic shopping experience with real product data.
  • Implement modern React patterns (not just another Todo app).
  • Target a 95+ Lighthouse performance score.
  • Deliver a beautiful UI with smooth animations and responsive design.
  • Keep the code maintainable with a clean architecture.

What I Built

  • Real‑time search powered by the DummyJSON API.
  • Persistent shopping cart (localStorage + cross‑tab sync).
  • Dark / light mode with system‑preference detection.
  • 60 fps animations using Framer Motion.
  • Fully responsive, mobile‑first layout.
  • Performance‑optimized (95+ Lighthouse score).

Architecture Overview

graph TB
    A[App.jsx] --> B[ThemeContext]
    A --> C[ProductContext]
    A --> D[CartContext]

    C --> E[ProductList]
    E --> F[ProductCard]

    D --> G[CartSidebar]
    D --> F

    H[SearchBar] --> I((DummyJSON API))
    I --> C

    B --> A

Each context handles a single responsibility, keeping components focused, reusable, and easy to reason about.

Technology Choices

TechnologyWhy I Chose ItAlternatives
React 18Stable ecosystem, concurrent featuresVue, Svelte
ViteLightning‑fast developer experienceCreate React App
Tailwind CSSSpeed + consistencyStyled Components
Context APIPerfect for mid‑size appsRedux, Zustand
Framer MotionDeclarative animationsReact Spring
DummyJSONRealistic fake dataMSW (Mock Service Worker)

Key Code Snippets

Search Bar (real‑time, debounced)

import { useState, useEffect } from "react";

const SearchBar = ({ onSearch }) => {
  const [query, setQuery] = useState("");
  const [debouncedQuery, setDebouncedQuery] = useState("");

  // Debounce input
  useEffect(() => {
    const timer = setTimeout(() => setDebouncedQuery(query), 300);
    return () => clearTimeout(timer);
  }, [query]);

  // Fetch results when debounced query changes
  useEffect(() => {
    if (!debouncedQuery.trim()) {
      onSearch(null);
      return;
    }

    const search = async () => {
      try {
        const res = await fetch(
          `https://dummyjson.com/products/search?q=${debouncedQuery}`
        );
        const data = await res.json();
        onSearch(data.products);
      } catch {
        onSearch([]);
      }
    };

    search();
  }, [debouncedQuery, onSearch]);

  return (
     setQuery(e.target.value)}
      placeholder="Search products..."
      className="w-full px-4 py-2 border rounded-lg"
    />
  );
};

export default SearchBar;

Persistent Cart (localStorage + cross‑tab sync)

import { useState, useEffect } from "react";

const useCart = () => {
  const [cart, setCart] = useState(() => {
    const stored = localStorage.getItem("shopstyle-cart");
    return stored ? JSON.parse(stored) : [];
  });

  // Persist to localStorage
  useEffect(() => {
    localStorage.setItem("shopstyle-cart", JSON.stringify(cart));
  }, [cart]);

  // Sync across tabs
  useEffect(() => {
    const sync = (e) => {
      if (e.key === "shopstyle-cart") {
        setCart(JSON.parse(e.newValue || "[]"));
      }
    };
    window.addEventListener("storage", sync);
    return () => window.removeEventListener("storage", sync);
  }, []);

  return [cart, setCart];
};

export default useCart;

Theme Management (dark / light)

import { useState, useEffect, useCallback } from "react";

const useTheme = () => {
  const [theme, setTheme] = useState(() => {
    const saved = localStorage.getItem("shopstyle-theme");
    if (saved) return saved;
    return window.matchMedia("(prefers-color-scheme: dark)").matches
      ? "dark"
      : "light";
  });

  // Apply theme class and persist
  useEffect(() => {
    document.documentElement.className = theme;
    localStorage.setItem("shopstyle-theme", theme);
  }, [theme]);

  const toggleTheme = useCallback(() => {
    setTheme((prev) => (prev === "light" ? "dark" : "light"));
  }, []);

  return { theme, toggleTheme };
};

export default useTheme;

Product Card (memoized)

import { memo } from "react";

const ProductCard = memo(({ product }) => {
  return {product.title};
});

export default ProductCard;

Virtualized Product List (react‑window)

import { FixedSizeList as List } from "react-window";

const VirtualProductList = ({ products }) => (
  
    {({ index, style }) => (
      
        
      
    )}
  
);

Lighthouse Scores

MetricScore
Performance96
Accessibility100
Best Practices100
SEO92

Deployment

vercel --prod

Vercel handles builds, previews, routing, and performance out of the box.

Production Tips

  • Cart sync across tabs relies on storage events.
  • Keep animations limited to transform and opacity for optimal frame rates.
  • Always plan for API failures and implement caching strategies.

Backend & Extras (future work)

  • Node + PostgreSQL API
  • Stripe integration for payments
  • PWA support
  • Internationalization

Getting Started

git clone https://github.com/yourusername/shopstyle.git
cd shopstyle
npm install
npm run dev

Closing Thoughts

Huge thanks to React, Tailwind, DummyJSON, and the DEV community ❤️

  • ⭐ Star the repository
  • Happy coding — the best project is the one you actually finish. 🚀
Back to Blog

Related posts

Read more »