An e-commerce application is not really a shopping cart project. It is a state-management, authentication, database, API and business-logic project disguised as a shopping website.
When I started building PrinceStore, I initially thought about the interface. Product cards. Navbar. Hero section. Cart. Checkout.
But once the application started behaving like a real product, the difficult questions appeared.
What happens when a user logs out? What happens to the cart? What happens when a product is removed? What happens when an order is created?
Building the interface is only one part of building an application. The real complexity appears when features interact.
It started as a normal e-commerce website.
The goal was simple: create a complete shopping experience where users could browse products, authenticate, manage a cart, maintain a wishlist and place orders.
But I didn't want another static shopping page.
I wanted the application to behave like an actual product.
User
↓
Register / Login
↓
Browse Products
↓
Product Details
↓
Cart
↓
Wishlist
↓
Checkout
↓
Order
↓
Order Success
The UI was only the beginning.
The application needed multiple layers.
The frontend handled the user experience. The backend handled business logic and API requests. MySQL handled persistent application data.
Keeping those responsibilities separated made the application easier to reason about.
React
↓
Axios
↓
Express Route
↓
Controller / Logic
↓
MySQL
↓
JSON Response
↓
React State
↓
UI Update
Login is not just a form.
A login screen looks simple. Email. Password. Button.
But authentication creates application state.
Login Form
↓
POST /api/auth/login
↓
Backend Validation
↓
Database Check
↓
Authentication Result
↓
Frontend State
↓
Authenticated User
Once authentication exists, almost every other feature needs to understand who the current user is.
Cart. Wishlist. Orders. Profile. Logout.
That is why authentication is an application-wide concern, not just a login-page feature.
Products are the center of the shopping experience.
The product system needed to support more than displaying a name and price.
products
──────────────
id
name
description
price
image
category
stock
created_at
The frontend could then request the products through an API.
GET /api/products
That separation meant the UI didn't need to know how the database stored the products.
The cart exposed the real state-management problem.
A cart seems simple until multiple pages need access to it.
Product page adds an item. Navbar shows cart count. Cart page changes quantity. Checkout reads cart contents.
Suddenly several components need access to the same state.
CartContext
│
├── Navbar
│
├── ProductCard
│
├── ProductDetails
│
├── Cart
│
└── Checkout
This is where a shared context became useful.
Instead of passing cart data through multiple levels of components, the application could expose cart operations through a common context.
Then another state system appeared.
Wishlist functionality looked similar to the cart, but it represented a different concept.
A cart means: "I intend to purchase this."
A wishlist means: "I want to remember this."
Application
│
├── AuthContext
│
├── CartContext
│
├── WishlistContext
│
└── OrderContext
Separating these responsibilities kept the application logic easier to understand.
Checkout is where everything finally meets.
Checkout was one of the most important parts of the application because it connected several systems.
Authenticated User
↓
Cart
↓
Address
↓
Order Data
↓
POST /api/orders
↓
Backend
↓
Database
↓
Order Created
↓
Success Page
This taught me something important: features should not be designed independently when they ultimately participate in the same business flow.
Someone has to control the catalog.
A real store cannot depend on manually editing database rows every time a product changes.
That introduced an admin side.
Create Product
↓
Read Products
↓
Update Product
↓
Delete Product
This was also a useful lesson in authorization.
Authentication answers: "Who are you?"
Authorization answers: "What are you allowed to do?"
The bugs were more educational than the features.
The database contained product information but image references were not always being stored or resolved correctly.
Production required changing API configuration, environment variables and deployment settings.
Cart, authentication, wishlist and orders all needed consistent state management.
Connecting the UI to reliable backend and database behavior was where most of the engineering work appeared.
The biggest lesson was architecture.
Before this project, it was easy to think of features as isolated screens.
Login. Cart. Products. Checkout.
Building the entire flow changed that.
UI
↓
State
↓
API
↓
Business Logic
↓
Database
↓
Persistent Data
Every layer has a responsibility. Every layer can fail. And every layer needs to communicate clearly with the next one.
That is much closer to real software engineering than simply building pages.
The project became bigger than the shopping website.
I started with the idea of building an e-commerce website.
I ended up learning about:
React
State Management
Authentication
REST APIs
Express
MySQL
Database Design
CRUD
Authorization
Deployment
Debugging
Production Problems
The most valuable part wasn't the final UI.
It was understanding how all the pieces communicate.
A real application is not a collection of pages. It is a system.
another project.
Build something
that teaches you.