A complete e-commerce web application built using the MERN-like stack (MySQL instead of MongoDB) with separate frontend and backend services, designed for free-tier deployment. Features include product browsing, searching, shopping cart, user authentication, role-based access, basic admin dashboard functionalities, and Stripe payment integration (Test Mode).
π View Live Demo π
(Note: Backend might take ~30s to wake up on the first visit due to Railway's free tier sleeping policy.)
Page | Screenshot |
---|---|
Homepage | ![]() |
Product Listing | ![]() |
Product Detail | ![]() |
Search Results | ![]() |
Shopping Cart | ![]() |
Login Page | ![]() |
Register Page | ![]() |
User Profile | ![]() |
Checkout Page | ![]() |
- Frontend (Next.js):
- Server-Side Rendering (SSR) for product listing and details.
- Responsive design for Desktop, Tablet, and Mobile.
- Modern UI built with Tailwind CSS.
- Client-side state management with Zustand.
- Form handling with React Hook Form.
- Backend (Node.js/Express):
- RESTful API endpoints for managing resources.
- MySQL database interaction using
mysql2
.
- Core E-commerce:
- Product listing and detailed view pages.
- Product search functionality (by name/description).
- Shopping cart functionality (add, update quantity, remove, clear).
- Basic checkout flow structure.
- Authentication & Authorization:
- User registration and login.
- JWT (JSON Web Token) based authentication.
- Password hashing using
bcrypt
. - Role-based access control (user vs. admin).
- Protected routes for authenticated users and admins (
withAuth
,withAdminAuth
HOCs).
- Admin Panel (Basic):
- Dashboard overview (placeholder stats).
- View all users, orders (basic list).
- Manage products (Add, Edit, Delete - requires UI implementation).
- Admin-only API endpoints protected.
- Payments:
- Stripe Payment Intents integration (Test Mode).
- Secure payment form using Stripe Elements (
PaymentElement
). - Backend endpoint to create Payment Intents.
- Order confirmation page displaying payment status.
- Basic Stripe Webhook endpoint structure for verifying payments.
- Frontend:
- Next.js (v15+) - React Framework (Pages Router)
- React (v19+) - UI Library
- Tailwind CSS (v4+) - Utility-First CSS Framework
- Zustand - State Management
- Axios - HTTP Client
- React Hook Form - Form Validation
- @stripe/react-stripe-js & @stripe/stripe-js - Stripe Frontend Libraries
- @heroicons/react - Icons
- Backend:
- Node.js - JavaScript Runtime
- Express.js - Web Framework
- mysql2 - MySQL Client
- jsonwebtoken - JWT Implementation
- bcrypt - Password Hashing
- cors - Cross-Origin Resource Sharing Middleware
- dotenv - Environment Variable Loading
- stripe - Stripe Node.js Library
- Database:
- Deployment:
Follow these instructions to get a copy of the project up and running on your local machine for development and testing purposes.
- Node.js (LTS version recommended, e.g., v18+)
- npm (usually comes with Node.js) or yarn
- Git
- A Railway account (for hosting the database during local development - free tier available)
- A Stripe account (for payment testing - free test mode available)
-
Clone the repository:
git clone https://github.com/Garbii1/ecommerce-platform.git cd ecommerce-platform
-
Backend Setup:
- Navigate to the backend directory:
cd backend
- Install dependencies:
npm install
- Create a Railway MySQL database service in your Railway project dashboard.
- Create a
.env
file in thebackend
directory and add the following environment variables (get values from Railway, Stripe, and generate your own JWT secret):# Get from Railway MySQL service -> Variables tab (use the PUBLIC host/port for local dev) DATABASE_URL=mysql://USER:PASSWORD@PUBLIC_HOST:PORT/DATABASE_NAME # Generate a strong random string (e.g., using Node crypto or openssl rand -hex 32) JWT_SECRET=YOUR_REALLY_STRONG_JWT_SECRET_KEY # Optional: JWT Expiration (defaults can be set in code) JWT_EXPIRES_IN=1d # Your LOCAL frontend URL for CORS FRONTEND_URL=http://localhost:3000 # Get from Stripe Dashboard (Test Mode -> Developers -> API Keys) STRIPE_SECRET_KEY=sk_test_YOUR_STRIPE_SECRET_KEY # Get from running `stripe listen --forward-to ...` locally (see Stripe Setup) STRIPE_WEBHOOK_SECRET=whsec_YOUR_LOCAL_STRIPE_CLI_WEBHOOK_SECRET
- Set up the database tables: Connect to your Railway database using an SQL client (like TablePlus, DBeaver) and run the SQL
CREATE TABLE
statements found earlier in the project setup guide (or in a dedicatedschema.sql
file if you create one). - Start the backend development server:
The backend should be running on
npm run dev
http://localhost:5001
(or the port specified in.env
).
- Navigate to the backend directory:
-
Frontend Setup:
- Open a new terminal and navigate to the frontend directory:
(If you are inside the
cd frontend
backend
directory, usecd ../frontend
) - Install dependencies:
npm install
- Create a
.env.local
file in thefrontend
directory and add the following environment variables:# Your LOCAL backend API endpoint NEXT_PUBLIC_API_URL=http://localhost:5001/api # Get from Stripe Dashboard (Test Mode -> Developers -> API Keys) NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_YOUR_STRIPE_PUBLISHABLE_KEY
- Start the frontend development server:
The frontend should be running on
npm run dev
http://localhost:3000
.
- Open a new terminal and navigate to the frontend directory:
-
Access the Application: Open your browser and go to
http://localhost:3000
.
(Note: Base URL is assumed to be /api
)
- Auth:
POST /auth/register
: Register a new user.POST /auth/login
: Log in a user, returns JWT.GET /auth/profile
: Get logged-in user's profile (Requires Auth).
- Products:
GET /products
: Get all products.GET /products/search?q={term}
: Search products by name/description.GET /products/{id}
: Get a single product by ID.POST /products
: Create a new product (Admin only).PUT /products/{id}
: Update a product (Admin only).DELETE /products/{id}
: Delete a product (Admin only).
- Orders:
POST /orders
: Create a new order (Requires Auth).GET /orders/mine
: Get orders for the logged-in user (Requires Auth).GET /orders/{id}
: Get a specific order by ID (Owner or Admin).GET /orders
: Get all orders (Admin only).PUT /orders/{id}/status
: Update order status (Admin only).
- Payments:
POST /payments/create-payment-intent
: Create a Stripe Payment Intent (Requires Auth).
- Admin:
GET /admin/users
: Get all users (Admin only).GET /admin/users/{id}
: Get a specific user (Admin only).DELETE /admin/users/{id}
: Delete a user (Admin only).PUT /admin/users/{id}/role
: Update a user's role (Admin only).
- Webhooks:
POST /webhooks/stripe
: Listens for events from Stripe (e.g., payment success/failure).
- Backend: Deployed on Railway. Requires environment variables (
DATABASE_URL
[usually injected],JWT_SECRET
,NODE_ENV=production
,FRONTEND_URL_PROD
,STRIPE_SECRET_KEY
,STRIPE_WEBHOOK_SECRET
) set in the Railway service settings. Root directory set to/backend
. - Frontend: Deployed on Vercel. Requires environment variables (
NEXT_PUBLIC_API_URL
,NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
) set in the Vercel project settings. Root directory set to/frontend
. - CORS: Ensure the
FRONTEND_URL_PROD
on Railway matches the Vercel deployment URL. - Database: MySQL hosted on Railway (Free tier limitations apply).
- Stripe Webhook: A production webhook endpoint needs to be configured in Stripe pointing to the deployed backend URL, and the corresponding production
whsec_...
key used in the Railway environment variables.
- CORS Errors: Encountered CORS blocking between the deployed Vercel frontend and Railway backend. Solved by ensuring the correct Vercel URL was added to the
FRONTEND_URL_PROD
environment variable on Railway and restarting the backend service. - Build Failures (ESLint): Vercel builds initially failed due to strict ESLint rules (
react/no-unescaped-entities
). Solved by escaping special characters (like"
and'
) in JSX text content using HTML entities ("
,'
). - Build Failures (Module Parsing): Faced "Unexpected token" errors during the build, often pointing to JSX. Typically resolved by ensuring correct file extensions (
.js
/.jsx
) and fixing any subtle syntax errors preceding the problematic JSX. - Tailwind CSS Class Issues: Encountered errors where custom or even default Tailwind classes ("Cannot apply unknown utility class") were not recognized. Resolved by ensuring correct Tailwind/PostCSS configuration (
tailwind.config.js
,postcss.config.mjs
), verifying compatible package versions (especially with Tailwind v4), and clearing the Next.js cache (.next
folder) before restarting the development server. - Database Connection Errors (
ENOTFOUND
,ECONNRESET
):ENOTFOUND
: Occurred when trying to connect from local machine/Node.js to the database using the internal Railway hostname. Solved by finding and using the public database connection URL/host/port provided by Railway in the local.env
file.ECONNRESET
: Connection reset by the database server, often due to idle timeouts on free tiers. Mitigated by implementing a basic retry mechanism (queryWithRetry
) in the backend controllers for read operations.
- React Hydration Errors: Faced "Hydration failed" and "Maximum update depth exceeded" errors.
- Caused by discrepancies between server-rendered HTML and initial client render, often due to nested invalid HTML (like
<a>
inside<a>
,<form>
inside<form>
) or accessinglocalStorage
/Zustand state too early on the client. - Solved by fixing invalid HTML nesting (updating Next.js
<Link>
usage, removing nested forms) and implementing anisMounted
state check in_app.js
to delay rendering until the client is ready, allowing state hydration to stabilize.
- Caused by discrepancies between server-rendered HTML and initial client render, often due to nested invalid HTML (like
- Stripe Image/SVG Errors:
next/image
failed withENOTFOUND
when trying to optimize images fromvia.placeholder.com
(Node.js DNS issue) anddangerouslyAllowSVG
errors withplacehold.co
(returned SVGs). Solved by switching placeholder service topicsum.photos
(which Node.js could resolve and returns raster images) and updatingnext.config.mjs
remotePatterns
accordingly.
- Implement robust pagination for product lists and order history.
- Add advanced search filters (category, price range, sorting).
- Implement user reviews and ratings for products.
- Detailed order history page for users.
- Replace placeholder images with actual image hosting/upload (e.g., Cloudinary, AWS S3).
- Add comprehensive unit and integration tests (Jest, React Testing Library, Supertest).
- Add end-to-end tests (Cypress, Playwright).
- Implement password reset functionality.
- Allow users to update their profile information.
- Enhance admin dashboard with more features (analytics, user editing).
- Add more payment methods via Stripe.
- Improve accessibility (ARIA attributes, keyboard navigation).
- Consider PWA (Progressive Web App) features.
- Refactor state management if complexity increases.
- Switch to live Stripe keys and webhook secret for production.
- Author: Muhammed Babatunde Garuba
- GitHub: Garbii1