An individually built React and Express e-commerce application for a fictional premium skincare brand, combining a polished storefront with customer accounts, protected carts and orders, and an administrator workspace.
Explore the static portfolio demo
| Product detail | Demo bag |
|---|---|
![]() |
![]() |
- Customer journey: searchable and filterable products, detail views, a user-scoped bag, order placement and order history.
- Server-enforced access: JWT-protected account routes, ownership-scoped cart and order operations, and role-protected administrator endpoints.
- Product operations: administrator views for customers, carts and orders plus product create, update and delete workflows.
- Interface design: a responsive editorial system with semantic structure, labelled controls, keyboard focus styles, reduced-motion support, loading states and clear empty/error feedback.
The GitHub Pages version is a deliberate frontend demonstration. It uses the same React interface with bundled synthetic product data and an in-browser demo customer, so visitors can browse, filter, inspect products, manage a bag and create an order preview without an account or database.
Real authentication, persistence and administration remain part of the local full-stack application and are not connected to the public static site. The interface labels this boundary directly.
flowchart LR
UI[React and Vite client]
API[Express JSON API]
AUTH[JWT authentication and role checks]
DB[(MongoDB through Mongoose)]
DEMO[Static demo adapter and synthetic data]
UI -->|local full-stack mode| API
API --> AUTH
AUTH --> DB
UI -->|GitHub Pages mode| DEMO
The client selects its data adapter at build time. VITE_DEMO_MODE=true uses the static adapter; otherwise the
application sends requests to the configured API base URL.
| Layer | Implementation |
|---|---|
| Client | React, Vite, JavaScript and custom CSS |
| API | Node.js and Express |
| Data | MongoDB and Mongoose |
| Authentication | bcrypt password hashing and JSON Web Tokens |
| Delivery | GitHub Actions and GitHub Pages |
Server configuration belongs in the root .env file:
PORT=5000
MONGODB_URI=mongodb://127.0.0.1:27017/lunea_store
JWT_SECRET=replace_this_with_a_long_random_secret
CLIENT_ORIGIN=http://localhost:5173Public client configuration belongs in client/.env. Vite variables are bundled into the browser and must never
contain credentials or secrets.
VITE_API_BASE_URL=/api
VITE_API_PROXY_TARGET=http://localhost:5000
VITE_BASE_PATH=/
VITE_DEMO_MODE=falseThe same-origin /api path and local proxy target remain the safe defaults, while deployments can supply different
public endpoints without changing source code.
Requirements: Node.js 20+, npm and a local MongoDB instance.
npm ciCreate .env from .env.example, then seed and start the application:
npm run seed
npm run dev- Storefront:
http://localhost:5173 - Express API:
http://localhost:5000
The seed command creates ten synthetic products plus local customer and administrator accounts for testing.
The public demonstration does not require MongoDB:
npm ci
npm run dev:demoTo produce the deployable static bundle:
npm run build:demo
npm run previewnpm run dev # client and server
npm run dev:demo # static portfolio mode
npm run lint # client lint
npm run build # standard client build
npm run build:demo # static demo build
npm run seed # reset local synthetic database data
npm run export # refresh reviewable JSON exports- Passwords are hashed before storage and password hashes are not returned by the API.
- Protected routes validate JWTs on the server; administrator routes also enforce the stored user role.
- Cart and order queries are scoped to the authenticated user.
- Secrets remain server-side and local environment files are ignored by Git.
- The static demonstration contains no live credentials, backend connection or persistent customer data.
For a production deployment, session storage, request hardening, rate limiting, atomic checkout/stock updates and operational monitoring would require further design. They are outside this university-project release.
The customer, administrator and failure-state workflows were manually exercised during development. GitHub Actions performs a clean dependency installation, lint and production build on every change; the Pages workflow independently builds and deploys the static mode.
LUNEA was completed entirely as my individual project and aligns with UTS 31748 Programming on the Internet. This repository retains that origin while presenting the implementation and its deployment boundary clearly.


