╔══════════════════════════════════════════════════════════════════╗ ║ SHOP FRONTEND ARCHITECTURE OVERVIEW ║ ║ Alpine.js + Jinja2 + Tailwind CSS + Multi-Theme ║ ╚══════════════════════════════════════════════════════════════════╝ 📦 WHAT IS THIS? ═════════════════════════════════════════════════════════════════ Customer-facing shop frontend provides visitors with a branded e-commerce experience unique to each vendor. Built with: ✅ Jinja2 Templates (server-side rendering) ✅ Alpine.js (client-side reactivity) ✅ Tailwind CSS (utility-first styling) ✅ Multi-Theme System (vendor branding) ✅ FastAPI (backend routes) 🎯 KEY PRINCIPLES ═════════════════════════════════════════════════════════════════ 1. Theme-First Design • Each vendor has unique colors, fonts, logos • CSS variables for dynamic theming • Custom CSS support per vendor • Dark mode with vendor colors 2. Progressive Enhancement • Works without JavaScript (basic HTML) • JavaScript adds cart, search, filters • Graceful degradation for older browsers 3. API-First Data Loading • All products from REST APIs • Client-side cart management • Real-time stock updates • Search and filtering 4. Responsive & Mobile-First • Mobile-first Tailwind approach • Touch-friendly interactions • Optimized images • Fast page loads 📁 FILE STRUCTURE ═════════════════════════════════════════════════════════════════ app/ ├── templates/shop/ │ ├── base.html ← ✅ Base template (layout + theme) │ ├── home.html ← ✅ Homepage / featured products │ ├── products.html ← ✅ Product catalog with filters │ ├── product.html ← Product detail page │ ├── cart.html ← Shopping cart │ ├── checkout.html ← Checkout flow │ ├── search.html ← Search results │ ├── account/ ← Customer account pages │ │ ├── login.html │ │ ├── register.html │ │ ├── dashboard.html │ │ ├── orders.html │ │ ├── profile.html │ │ └── addresses.html │ └── errors/ ← Error pages │ ├── 400.html │ ├── 404.html │ └── 500.html │ ├── static/shop/ │ ├── css/ │ │ └── shop.css ← ✅ Shop-specific styles (IMPLEMENTED) │ ├── js/ │ │ └── shop-layout.js ← ✅ Base shop functionality (IMPLEMENTED) │ └── img/ │ └── (placeholder images) │ ├── static/shared/ ← ✅ Shared across all areas (IMPLEMENTED) │ ├── js/ │ │ ├── log-config.js ← ✅ Logging setup │ │ ├── icons.js ← ✅ Icon registry │ │ ├── utils.js ← ✅ Utility functions │ │ └── api-client.js ← ✅ API wrapper │ └── css/ │ └── (shared styles if needed) │ └── routes/ └── shop_pages.py ← ✅ Route handlers (IMPLEMENTED) 🏗️ ARCHITECTURE LAYERS ═════════════════════════════════════════════════════════════════ Layer 1: Routes (FastAPI) ↓ Layer 2: Middleware (Vendor + Theme Detection) ↓ Layer 3: Templates (Jinja2) ↓ Layer 4: JavaScript (Alpine.js) ↓ Layer 5: API (REST endpoints) ↓ Layer 6: Database Layer 1: ROUTES (FastAPI) ────────────────────────────────────────────────────────────────── Purpose: Vendor Detection + Template Rendering Location: app/routes/shop_pages.py Example: @router.get("/", response_class=HTMLResponse, include_in_schema=False) @router.get("/products", response_class=HTMLResponse, include_in_schema=False) async def shop_products_page(request: Request): """ Render shop homepage / product catalog. Vendor and theme are auto-injected by middleware. """ return templates.TemplateResponse( "shop/products.html", get_shop_context(request) # Helper function ) Helper Function: def get_shop_context(request: Request, **extra_context) -> dict: """Build template context with vendor/theme from middleware""" vendor = getattr(request.state, 'vendor', None) theme = getattr(request.state, 'theme', None) clean_path = getattr(request.state, 'clean_path', request.url.path) vendor_context = getattr(request.state, 'vendor_context', None) # Get detection method (domain, subdomain, or path) access_method = vendor_context.get('detection_method', 'unknown') if vendor_context else 'unknown' # Calculate base URL for links # - Domain/subdomain: base_url = "/" # - Path-based: base_url = "/vendor/{vendor_code}/" base_url = "/" if access_method == "path" and vendor: full_prefix = vendor_context.get('full_prefix', '/vendor/') base_url = f"{full_prefix}{vendor.subdomain}/" return { "request": request, "vendor": vendor, "theme": theme, "clean_path": clean_path, "access_method": access_method, "base_url": base_url, # ⭐ Used for all links in templates **extra_context } Responsibilities: ✅ Access vendor from middleware (request.state.vendor) ✅ Access theme from middleware (request.state.theme) ✅ Calculate base_url for routing-aware links ✅ Render template with context ❌ NO database queries (data loaded client-side via API) ❌ NO business logic (handled by API endpoints) ⭐ MULTI-ACCESS ROUTING (Domain, Subdomain, Path-Based) ────────────────────────────────────────────────────────────────── The shop frontend supports THREE access methods: 1. **Custom Domain** (Production) URL: https://customdomain.com/products - Vendor has their own domain - base_url = "/" - Links: /products, /about, /contact 2. **Subdomain** (Production) URL: https://wizamart.letzshop.com/products - Vendor uses platform subdomain - base_url = "/" - Links: /products, /about, /contact 3. **Path-Based** (Development/Testing) URL: http://localhost:8000/vendor/wizamart/products - Vendor accessed via path prefix - base_url = "/vendor/wizamart/" - Links: /vendor/wizamart/products, /vendor/wizamart/about ⚠️ CRITICAL: All template links MUST use {{ base_url }} prefix Example: ❌ BAD: Products ✅ GOOD: Products ❌ BAD: Contact ✅ GOOD: Contact How It Works: 1. VendorContextMiddleware detects access method 2. Sets request.state.vendor_context with detection_method 3. get_shop_context() calculates base_url from detection_method 4. Templates use {{ base_url }} for all internal links 5. Links work correctly regardless of access method Layer 2: MIDDLEWARE ────────────────────────────────────────────────────────────────── Purpose: Vendor & Theme Identification Two middleware components work together: 1. Vendor Context Middleware (middleware/vendor_context.py) • Detects vendor from domain/subdomain/path • Sets request.state.vendor • Sets request.state.vendor_context (includes detection_method) • Sets request.state.clean_path (path without vendor prefix) • Returns 404 if vendor not found 2. Theme Context Middleware (middleware/theme_context.py) • Loads theme for detected vendor • Sets request.state.theme • Falls back to default theme Order matters: vendor_context_middleware → theme_context_middleware Detection Methods: - custom_domain: Vendor has custom domain - subdomain: Vendor uses platform subdomain - path: Vendor accessed via /vendor/{code}/ or /vendors/{code}/ Layer 3: TEMPLATES (Jinja2) ────────────────────────────────────────────────────────────────── Purpose: HTML Structure + Vendor Branding Location: app/templates/shop/ Template Hierarchy: base.html (layout + theme injection) ↓ home.html (product grid) ↓ partials/product-card.html (components) Example: {% extends "shop/base.html" %} {% block title %}{{ vendor.name }}{% endblock %} {% block alpine_data %}shopHome(){% endblock %} {% block content %}