Client Tier — User Devices
💻Desktop Browser
Chrome / Firefox / Safari / Edge
Min viewport: 1024px
Full admin dashboard access
📱Mobile Browser
Responsive layout ≤ 768px
Touch-optimized UI
Hamburger nav, stacked cards
📟Tablet
Hybrid layout 768–1024px
Side-by-side product grid
Swipe gestures supported
Presentation Tier — React SPA
🏠Home Page
Hero banner with CTA
Featured products carousel
Business story section
Footer with social links
🛍️Products Page
Grid/list toggle view
Search bar (debounced)
Category filter sidebar
Pagination / infinite scroll
📄Product Detail
Image gallery / lightbox
Description & pricing
Related products
Enquire / Order CTA
🛒Cart & Checkout
Cart Context + localStorage
Quantity stepper controls
Running total calculation
Checkout: name + email only
✉️Contact / Order
Minimal order form (no account)
Client-side validation
Stock validated server-side
Confirmation email via Resend
🔐Admin Login
Email + password form
JWT stored in httpOnly cookie
Redirect to dashboard
📊Admin Dashboard
Product & category CRUD
Order management + status flow
Analytics charts (Recharts)
Image upload, stock editing
🛡️Auth Guard
PrivateRoute wrapper
Token refresh logic
401 → redirect to login
Role-based access
React
19
TypeScript
React Router
SCSS
Modules
Cart Context
Recharts
Vite 5
Application Tier — Node.js / Express Server
📡Route Handlers
/api/products — CRUD
/api/categories — browse & manage
/api/orders — submit (public)
/api/admin/orders — manage & status
/api/auth — login, verify, logout
/api/admin/analytics — summary
⚙️Controllers
productController.ts
categoryController.ts
orderController.ts
authController.ts
analyticsController.ts
🗂️Models / ORM
Drizzle ORM (type-safe, zero overhead)
Product + Category models
Order + OrderItem models
Admin + EmailLog models
🛡️Middleware Stack
cors() — origin whitelist
helmet() — security headers
express-rate-limit
authMiddleware — JWT verify
multer — image uploads
express-validator — input
📧Email Service
Resend transactional email
Pre-built HTML templates
Order confirmation → customer
Status update → customer
All emails logged to email_logs
📁File Upload
Multer middleware
Image resize (Sharp)
Static /uploads directory
Max 5MB per file
📝Logger
Winston / Morgan
Request logging
Error tracking
Log rotation
Node.js
Express
Drizzle ORM
MySQL
JWT
bcrypt
Resend
Multer
Data Tier — MySQL Relational Database
📋 products
🔑 idINT AI
🔗 category_idINT
nameVARCHAR(255)
slugVARCHAR(255)
priceDECIMAL(10,2)
stock_quantityINT
image_urlVARCHAR(500)
is_activeBOOLEAN
📋 categories
🔑 idINT AI
nameVARCHAR(100)
slugVARCHAR(100)
sort_orderINT
📋 orders
🔑 idINT AI
customer_nameVARCHAR(255)
customer_emailVARCHAR(255)
messageTEXT
statusENUM
totalDECIMAL(10,2)
created_atTIMESTAMP
📋 order_items
🔑 idINT AI
🔗 order_idINT
🔗 product_idINT
quantityINT
priceDECIMAL(10,2)
📋 admins
🔑 idINT AI
emailVARCHAR(255)
password_hashVARCHAR(255)
nameVARCHAR(100)
📋 email_logs
🔑 idINT AI
🔗 order_idINT
typeVARCHAR(50)
to_emailVARCHAR(255)
statusENUM
Relationships:
products.category_id → categories.id (FK) ·
order_items.order_id → orders.id (FK) · order_items.product_id → products.id (FK) · email_logs.order_id → orders.id (FK)
Infrastructure Tier — Deployment
🖥️Contabo VPS
Single VPS hosting all services
Ubuntu 22.04 LTS
Nginx reverse proxy
Custom domain + Let's Encrypt SSL
⚙️Server Stack
Nginx → static frontend files
PM2 → Node.js process manager
MySQL 8.0 local instance
UFW firewall (80, 443, 22)
💾Database
MySQL 8.0 on same VPS
Local storage on VPS disk
Connection via localhost:3306
CLI / Sequelize for management
🔄Version Control
Git & GitHub repository
Manual deploy via SSH
Environment variables in .env
PM2 process management
Product Endpoints
GET/api/healthHealth check
GET/api/productsList products (paginated, filterable by category/search)
GET/api/products/:slugSingle product detail (by ID or slug)
GET/api/products/search?q=Search by name/description
GET/api/admin/products🔐 List all products (with category join)
POST/api/admin/products🔐 Create product + image upload
PUT/api/admin/products/:id🔐 Update product (incl. stock, category)
DELETE/api/admin/products/:id🔐 Delete product
Order Endpoints (Public)
POST/api/ordersCreate order (validates stock, decrements, sends confirmation email)
Order Management Endpoints (Admin)
GET/api/admin/orders🔐 List all orders
GET/api/admin/orders/:id🔐 Order detail with items
PUT/api/admin/orders/:id/status🔐 Update status (triggers customer email)
Authentication Endpoints
POST/api/auth/loginAdmin login → JWT token
POST/api/auth/logoutClear auth cookie
GET/api/auth/verifyVerify current token
POST/api/auth/refreshRefresh expired token
PUT/api/auth/password🔐 Change admin password
Analytics Endpoints
GET/api/admin/analytics/summary🔐 Total orders, revenue, popular products
Category Endpoints
GET/api/categoriesList all categories (public)
GET/api/categories/:slugCategory detail + filtered products
GET/api/admin/categories🔐 List categories (with product count)
POST/api/admin/categories🔐 Create category
PUT/api/admin/categories/:id🔐 Update category
DELETE/api/admin/categories/:id🔐 Delete category (blocked if has products)
Entity Relationship Diagram
📋 products
🔑 idINT AUTO_INCREMENT
🔗 category_idINT
nameVARCHAR(255) NOT NULL
slugVARCHAR(255) UNIQUE
descriptionTEXT
priceDECIMAL(10,2)
image_urlVARCHAR(500)
stock_quantityINT DEFAULT 0
is_activeBOOLEAN DEFAULT 1
created_atTIMESTAMP
📋
categories
🔑 idINT AUTO_INCREMENT
nameVARCHAR(100) NOT NULL
slugVARCHAR(100) UNIQUE
descriptionTEXT
image_urlVARCHAR(500)
sort_orderINT DEFAULT 0
created_atTIMESTAMP
📋
orders
🔑 idINT AUTO_INCREMENT
customer_nameVARCHAR(255) NOT NULL
customer_emailVARCHAR(255) NOT NULL
messageTEXT
statusENUM('new','confirmed','processing','shipped','delivered')
totalDECIMAL(10,2)
created_atTIMESTAMP
📋
order_items
🔑 idINT AUTO_INCREMENT
🔗 order_idINT
🔗 product_idINT
quantityINT
priceDECIMAL(10,2)
📋
admins
🔑 idINT AUTO_INCREMENT
emailVARCHAR(255) UNIQUE
password_hashVARCHAR(255) NOT NULL
nameVARCHAR(100)
created_atTIMESTAMP
📋
email_logs
🔑 idINT AUTO_INCREMENT
🔗 order_idINT
typeVARCHAR(50)
to_emailVARCHAR(255)
statusENUM('sent','failed')
sent_atTIMESTAMP
Indexes & Constraints
FK: products.category_id → categories.id ON DELETE SET
NULL
FK: order_items.order_id → orders.id ON DELETE CASCADE
FK: order_items.product_id → products.id ON DELETE SET NULL
FK: email_logs.order_id → orders.id ON DELETE CASCADE
IDX: products(slug) UNIQUE — SEO-friendly URLs
IDX: products(category_id, is_active) — product listing
queries
IDX: orders(status, created_at) — admin order filtering
IDX: orders(customer_email) — order lookup by customer
IDX: categories(slug) UNIQUE — URL-friendly category lookup
Project Structure
src/
├── components/
│ ├── common/ # Button, Input, Modal, Loader, Toast, Navbar, Footer
│ ├── products/ # ProductCard, ProductGrid, ProductFilter, SearchBar
│ ├── cart/ # CartItem, CartSummary, QuantityStepper, CartBadge
│ ├── forms/ # OrderForm, LoginForm
│ ├── admin/ # ProductTable, OrderList, AnalyticsChart, Sidebar
│ └── layout/ # PublicLayout, AdminLayout, PrivateRoute
├── pages/
│ ├── HomePage.tsx
│ ├── ProductsPage.tsx
│ ├── ProductDetailPage.tsx
│ ├── CartPage.tsx # Cart review, quantity editing, checkout form
│ ├── admin/
│ │ ├── DashboardPage.tsx
│ │ ├── ManageProductsPage.tsx
│ │ ├── OrdersPage.tsx # Order list, status management
│ │ └── AnalyticsPage.tsx
│ └── LoginPage.tsx
├── context/
│ ├── AuthContext.tsx # JWT state, login/logout actions
│ └── CartContext.tsx # Cart state, add/remove/update, localStorage sync
├── hooks/
│ ├── useProducts.ts # Fetch, filter, search products
│ ├── useCart.ts # Cart operations, total calculation
│ └── useAuth.ts # Auth state & token management
├── services/
│ ├── api.ts # Axios instance with interceptors
│ ├── productService.ts # Product API calls
│ ├── orderService.ts # Order submission API
│ └── authService.ts # Auth API calls
├── utils/
│ ├── validators.ts # Form validation rules
│ ├── formatters.ts # Date, price, text formatting
│ └── constants.ts # API URL, categories, statuses
├── styles/ # SCSS Modules, variables, animations
├── App.tsx # Router setup
└── main.tsx # Entry point
Route Map
/HomePageLanding with hero & featured
/productsProductsPageBrowse all products
/products/:slugProductDetailPageSingle product view
/cartCartPageReview cart, adjust quantities, checkout
/loginLoginPageAdmin authentication
/adminDashboardPageAUTHAnalytics overview
/admin/productsManageProductsPageAUTHProduct CRUD
/admin/ordersOrdersPageAUTHOrder management & status updates
/admin/analyticsAnalyticsPageAUTHDetailed analytics
State Management Flow
🛒CartContext
items: CartItem[] (localStorage)
addToCart(product, qty)
updateQuantity(id, qty)
removeFromCart(id)
clearCart()
cartTotal: computed decimal
cartCount: badge number
🔑AuthContext
user: object | null
token: string (httpOnly)
login(email, pass) → JWT
logout() → clear state
isAuthenticated: boolean
📦Product State (hooks)
products: array
loading / error states
filters: { category, search, sort }
pagination: { page, total }
CRUD mutations (admin)
📦Order State (admin)
orders: array
statusFilter: enum
updateStatus(id, status)
orderDetail: order + items
Status triggers customer email
Security Architecture
🔐Authentication
bcrypt (12 salt rounds) password hashing
JWT access tokens (15min TTL)
Refresh tokens (7d TTL, httpOnly cookie)
Token rotation on refresh
Brute force: 5 attempts / 15min lockout
✅Input Validation
express-validator on all inputs
XSS sanitization (DOMPurify)
SQL injection: parameterized queries
File upload: type + size checks
CSRF protection via SameSite cookies
🌐Transport Security
HTTPS enforced (HSTS header)
TLS 1.2+ minimum
CORS: whitelist frontend origin only
Helmet.js security headers
Content-Security-Policy header
📋Data Protection
No plaintext passwords stored
Sensitive data in env variables
DB credentials never in codebase
Rate limiting on public endpoints
IP logging for abuse prevention
Deployment Architecture
GitHub Repository
main branch (production)
feature/* branches
Version control & history
Code collaboration
feature/* branches
Version control & history
Code collaboration
git pull via SSH
Contabo VPS
npm install & build
Nginx → static + reverse proxy
PM2 → Node.js backend
MySQL 8.0 → local DB
Let's Encrypt → HTTPS
Nginx → static + reverse proxy
PM2 → Node.js backend
MySQL 8.0 → local DB
Let's Encrypt → HTTPS
Performance & Monitoring
⚡Performance Targets
First Contentful Paint < 1.5s
Lighthouse score > 90
API response < 200ms avg
50 concurrent users supported
Image lazy loading + WebP
📈Monitoring
Winston error logging
Uptime monitoring (UptimeRobot)
Database query performance
API response time tracking
Email delivery status logs
🔄Maintenance
apt update / upgrade schedule
PM2 auto-restart on crash
Nginx log rotation
MySQL query optimization
Let's Encrypt auto-renewal