docs: add consolidated dev URL reference and migrate /shop to /storefront
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled

- Add Development URL Quick Reference section to url-routing overview
  with all login URLs, entry points, and full examples
- Replace /shop/ path segments with /storefront/ across 50 docs files
- Update file references: shop_pages.py → storefront_pages.py,
  templates/shop/ → templates/storefront/, api/v1/shop/ → api/v1/storefront/
- Preserve domain references (orion.shop) and /store/ staff dashboard paths
- Archive docs left unchanged (historical)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 13:23:44 +01:00
parent 3df75e2e78
commit d648c921b7
50 changed files with 1104 additions and 1049 deletions

View File

@@ -189,7 +189,7 @@ app/templates/shared/
### Shop Frontend
**Template:** `app/templates/shop/base.html`
**Template:** `app/templates/storefront/base.html`
```html
{# Lines 41-42: Tailwind CSS fallback #}

View File

@@ -148,39 +148,39 @@ function myPageComponent() {
return {
...data(),
currentPage: 'my-page',
items: [],
loading: false,
async init() {
pageLog.info('Initializing page');
// Prevent double init
if (window._myPageInitialized) return;
window._myPageInitialized = true;
const start = performance.now();
try {
pageLog.group('Loading Data');
await this.loadData();
pageLog.groupEnd();
const duration = performance.now() - start;
window.LogConfig.logPerformance('Page Init', duration);
pageLog.info('Page initialized successfully');
} catch (error) {
window.LogConfig.logError(error, 'Page Init');
}
},
async loadData() {
const url = '/api/my-data';
window.LogConfig.logApiCall('GET', url, null, 'request');
const data = await apiClient.get(url);
window.LogConfig.logApiCall('GET', url, data, 'response');
this.items = data;
}
@@ -300,7 +300,7 @@ The system automatically detects which frontend based on URL:
|----------|----------|--------|
| `/admin/*` | admin | `ADMIN:` |
| `/store/*` | store | `STORE:` |
| `/shop/*` | shop | `SHOP:` |
| `/storefront/*` | storefront | `SHOP:` |
---
@@ -338,21 +338,21 @@ const DEFAULT_LOG_LEVELS = {
window.LogConfig = {
// Log levels
LOG_LEVELS: { ERROR: 1, WARN: 2, INFO: 3, DEBUG: 4 },
// Current config
frontend: 'admin' | 'store' | 'shop',
environment: 'development' | 'production',
logLevel: 1 | 2 | 3 | 4,
// Default logger
log: { error(), warn(), info(), debug(), group(), groupEnd(), table(), time(), timeEnd() },
// Pre-configured loggers
loggers: { stores, products, orders, ... },
// Create custom logger
createLogger(prefix, level?),
// Utility functions
logApiCall(method, url, data?, status),
logError(error, context),

View File

@@ -327,13 +327,13 @@ Tab navigation components for switching between content sections.
---
## E-commerce Components (Shop Frontend)
## E-commerce Components (Storefront Frontend)
Reusable macros for shop/storefront functionality. Located in `app/templates/shared/macros/shop/`.
Reusable macros for storefront functionality. Located in `app/templates/shared/macros/storefront/`.
### 🛍️ Product Card
```html
{% from 'shared/macros/shop/product-card.html' import product_card %}
{% from 'shared/macros/storefront/product-card.html' import product_card %}
{# Basic product card #}
{{ product_card(product_var='product') }}
@@ -360,7 +360,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🛍️ Product Grid
```html
{% from 'shared/macros/shop/product-grid.html' import product_grid %}
{% from 'shared/macros/storefront/product-grid.html' import product_grid %}
{# Basic grid #}
{{ product_grid(products_var='products', loading_var='loading') }}
@@ -381,7 +381,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🛒 Add to Cart
```html
{% from 'shared/macros/shop/add-to-cart.html' import add_to_cart_button, add_to_cart_form, buy_now_button %}
{% from 'shared/macros/storefront/add-to-cart.html' import add_to_cart_button, add_to_cart_form, buy_now_button %}
{# Simple button #}
{{ add_to_cart_button(action='addToCart()') }}
@@ -397,11 +397,11 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
- `add_to_cart_button()` - Simple button with loading state
- `add_to_cart_form()` - Form with quantity selector + button
- `buy_now_button()` - Direct checkout button
- `shop_quantity_selector()` - Stock-aware quantity input
- `storefront_quantity_selector()` - Stock-aware quantity input
### 🛒 Mini Cart (Header)
```html
{% from 'shared/macros/shop/mini-cart.html' import mini_cart, mini_cart_icon %}
{% from 'shared/macros/storefront/mini-cart.html' import mini_cart, mini_cart_icon %}
{# Complete mini cart with dropdown #}
{{ mini_cart(cart_var='cart', show_var='showCart') }}
@@ -419,7 +419,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🖼️ Product Gallery (Priority 3)
```html
{% from 'shared/macros/shop/product-gallery.html' import product_gallery %}
{% from 'shared/macros/storefront/product-gallery.html' import product_gallery %}
{# Full gallery with thumbnails, zoom, and lightbox #}
{{ product_gallery(images_var='product.images', enable_zoom=true, enable_lightbox=true) }}
@@ -436,7 +436,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🎨 Variant Selector (Priority 3)
```html
{% from 'shared/macros/shop/variant-selector.html' import size_selector, color_swatches %}
{% from 'shared/macros/storefront/variant-selector.html' import size_selector, color_swatches %}
{# Size buttons with size guide link #}
{{ size_selector(sizes_var='product.sizes', show_guide=true) }}
@@ -453,7 +453,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 📄 Product Info (Priority 3)
```html
{% from 'shared/macros/shop/product-info.html' import product_info, product_price %}
{% from 'shared/macros/storefront/product-info.html' import product_info, product_price %}
{# Complete info block #}
{{ product_info(product_var='product', show_store=true, show_rating=true) }}
@@ -473,7 +473,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 📑 Product Tabs (Priority 3)
```html
{% from 'shared/macros/shop/product-tabs.html' import product_tabs %}
{% from 'shared/macros/storefront/product-tabs.html' import product_tabs %}
{# Tabbed product information #}
{{ product_tabs(
@@ -486,7 +486,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 📂 Category Navigation (Priority 4)
```html
{% from 'shared/macros/shop/category-nav.html' import category_nav, category_tree, category_menu %}
{% from 'shared/macros/storefront/category-nav.html' import category_nav, category_tree, category_menu %}
{# Sidebar with nested categories #}
{{ category_nav(categories_var='categories', current_var='currentCategory', show_count=true) }}
@@ -502,10 +502,10 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🍞 Breadcrumbs (Priority 4)
```html
{% from 'shared/macros/shop/breadcrumbs.html' import shop_breadcrumbs, compact_breadcrumbs %}
{% from 'shared/macros/storefront/breadcrumbs.html' import storefront_breadcrumbs, compact_breadcrumbs %}
{# Static breadcrumbs #}
{{ shop_breadcrumbs(items=[
{{ storefront_breadcrumbs(items=[
{'label': 'Electronics', 'url': '/electronics'},
{'label': 'Audio', 'url': '/audio'},
{'label': 'Headphones'}
@@ -515,11 +515,11 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
{{ compact_breadcrumbs(parent={'label': 'Audio', 'url': '/audio'}, current='Headphones') }}
```
**Macros:** `shop_breadcrumbs()`, `auto_breadcrumbs()`, `compact_breadcrumbs()`
**Macros:** `storefront_breadcrumbs()`, `auto_breadcrumbs()`, `compact_breadcrumbs()`
### 🔍 Search Bar (Priority 4)
```html
{% from 'shared/macros/shop/search-bar.html' import search_bar, search_autocomplete %}
{% from 'shared/macros/storefront/search-bar.html' import search_bar, search_autocomplete %}
{# Basic search #}
{{ search_bar(placeholder='Search products...') }}
@@ -535,7 +535,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🎛️ Filter Sidebar (Priority 4)
```html
{% from 'shared/macros/shop/filter-sidebar.html' import filter_sidebar, price_filter, sort_dropdown %}
{% from 'shared/macros/storefront/filter-sidebar.html' import filter_sidebar, price_filter, sort_dropdown %}
{# Complete filter panel #}
{{ filter_sidebar(filters_var='filters', active_filters_var='activeFilters', on_change='filterProducts()') }}
@@ -551,7 +551,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### ⭐ Star Rating (Priority 5)
```html
{% from 'shared/macros/shop/star-rating.html' import star_rating, rating_input, rating_summary, compact_rating %}
{% from 'shared/macros/storefront/star-rating.html' import star_rating, rating_input, rating_summary, compact_rating %}
{# Static star rating with half-star support #}
{{ star_rating(rating=4.5, show_value=true, show_count=true, count=127) }}
@@ -573,7 +573,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 💬 Reviews (Priority 5)
```html
{% from 'shared/macros/shop/reviews.html' import review_card, review_list, review_form, review_summary_section %}
{% from 'shared/macros/storefront/reviews.html' import review_card, review_list, review_form, review_summary_section %}
{# Single review card with helpful buttons #}
{{ review_card(review_var='review', on_helpful='markHelpful(review.id)') }}
@@ -592,7 +592,7 @@ Reusable macros for shop/storefront functionality. Located in `app/templates/sha
### 🛡️ Trust Badges (Priority 5)
```html
{% from 'shared/macros/shop/trust-badges.html' import trust_badges, trust_banner, payment_icons, guarantee_badge, security_seals, checkout_trust_section %}
{% from 'shared/macros/storefront/trust-badges.html' import trust_badges, trust_banner, payment_icons, guarantee_badge, security_seals, checkout_trust_section %}
{# Trust badges grid #}
{{ trust_badges(badges=['secure_payment', 'free_shipping', 'easy_returns', 'support_24_7'], layout='grid') }}

View File

@@ -1,12 +1,12 @@
╔══════════════════════════════════════════════════════════════════╗
║ SHOP FRONTEND ARCHITECTURE OVERVIEW ║
║ STOREFRONT FRONTEND ARCHITECTURE OVERVIEW ║
║ Alpine.js + Jinja2 + Tailwind CSS + Multi-Theme ║
╚══════════════════════════════════════════════════════════════════╝
📦 WHAT IS THIS?
═════════════════════════════════════════════════════════════════
Customer-facing shop frontend provides visitors with a branded
Customer-facing storefront frontend provides visitors with a branded
e-commerce experience unique to each store. Built with:
✅ Jinja2 Templates (server-side rendering)
✅ Alpine.js (client-side reactivity)
@@ -46,7 +46,7 @@ e-commerce experience unique to each store. Built with:
═════════════════════════════════════════════════════════════════
app/
├── templates/shop/
├── templates/storefront/
│ ├── base.html ← ✅ Base template (layout + theme)
│ ├── home.html ← ✅ Homepage / featured products
│ ├── products.html ← ✅ Product catalog with filters
@@ -67,11 +67,11 @@ app/
│ ├── 404.html
│ └── 500.html
├── static/shop/
├── static/storefront/
│ ├── css/
│ │ └── shop.css ← ✅ Shop-specific styles (IMPLEMENTED)
│ │ └── storefront.css ← ✅ Storefront-specific styles (IMPLEMENTED)
│ ├── js/
│ │ └── shop-layout.js ← ✅ Base shop functionality (IMPLEMENTED)
│ │ └── storefront-layout.js ← ✅ Base storefront functionality (IMPLEMENTED)
│ └── img/
│ └── (placeholder images)
@@ -85,7 +85,7 @@ app/
│ └── (shared styles if needed)
└── routes/
└── shop_pages.py ← ✅ Route handlers (IMPLEMENTED)
└── storefront_pages.py ← ✅ Route handlers (IMPLEMENTED)
🏗️ ARCHITECTURE LAYERS
@@ -107,37 +107,37 @@ Layer 6: Database
Layer 1: ROUTES (FastAPI)
──────────────────────────────────────────────────────────────────
Purpose: Store Detection + Template Rendering
Location: app/routes/shop_pages.py
Location: app/routes/storefront_pages.py
⚠️ ROUTE REGISTRATION (main.py):
The shop router is mounted at TWO prefixes to support both access methods:
The storefront router is mounted at TWO prefixes to support both access methods:
# main.py
app.include_router(shop_pages.router, prefix="/shop", ...) # Domain/subdomain
app.include_router(shop_pages.router, prefix="/stores/{store_code}/shop", ...) # Path-based
app.include_router(storefront_pages.router, prefix="/storefront", ...) # Domain/subdomain
app.include_router(storefront_pages.router, prefix="/storefront/{store_code}", ...) # Path-based
This means routes defined WITHOUT /shop prefix in shop_pages.py:
@router.get("/products") → /shop/products OR /stores/{code}/shop/products
This means routes defined WITHOUT /storefront prefix in storefront_pages.py:
@router.get("/products") → /storefront/products OR /storefront/{code}/products
❌ COMMON MISTAKE: Don't add /shop prefix in route definitions!
@router.get("/shop/products") ❌ WRONG - creates /shop/shop/products
@router.get("/products") ✅ CORRECT - creates /shop/products
❌ COMMON MISTAKE: Don't add /storefront prefix in route definitions!
@router.get("/storefront/products") ❌ WRONG - creates /storefront/storefront/products
@router.get("/products") ✅ CORRECT - creates /storefront/products
Example Route Handler:
@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):
async def storefront_products_page(request: Request):
"""
Render shop homepage / product catalog.
Render storefront homepage / product catalog.
Store and theme are auto-injected by middleware.
"""
return templates.TemplateResponse(
"shop/products.html",
get_shop_context(request) # Helper function
"storefront/products.html",
get_storefront_context(request) # Helper function
)
Helper Function:
def get_shop_context(request: Request, **extra_context) -> dict:
def get_storefront_context(request: Request, **extra_context) -> dict:
"""Build template context with store/theme from middleware"""
store = getattr(request.state, 'store', None)
theme = getattr(request.state, 'theme', None)
@@ -176,39 +176,39 @@ Responsibilities:
⭐ MULTI-ACCESS ROUTING (Domain, Subdomain, Path-Based)
──────────────────────────────────────────────────────────────────
The shop frontend supports THREE access methods:
The storefront frontend supports THREE access methods:
1. **Custom Domain** (Production)
URL: https://customdomain.com/shop/products
URL: https://customdomain.com/storefront/products
- Store has their own domain
- base_url = "/"
- Links: /shop/products, /shop/about, /shop/contact
- Links: /storefront/products, /storefront/about, /storefront/contact
2. **Subdomain** (Production)
URL: https://orion.letzshop.com/shop/products
URL: https://orion.letzshop.com/storefront/products
- Store uses platform subdomain
- base_url = "/"
- Links: /shop/products, /shop/about, /shop/contact
- Links: /storefront/products, /storefront/about, /storefront/contact
3. **Path-Based** (Development/Testing)
URL: http://localhost:8000/stores/orion/shop/products
URL: http://localhost:8000/storefront/orion/products
- Store accessed via path prefix
- base_url = "/stores/orion/"
- Links: /stores/orion/shop/products, /stores/orion/shop/about
- base_url = "/storefront/orion/"
- Links: /storefront/orion/products, /storefront/orion/about
⚠️ CRITICAL: All template links MUST use {{ base_url }}shop/ prefix
⚠️ CRITICAL: All template links MUST use {{ base_url }}storefront/ prefix
Example:
❌ BAD: <a href="/products">Products</a>
❌ BAD: <a href="{{ base_url }}products">Products</a>
✅ GOOD: <a href="{{ base_url }}shop/products">Products</a>
✅ GOOD: <a href="{{ base_url }}storefront/products">Products</a>
Note: The router is mounted at /shop prefix in main.py, so all links need shop/ after base_url
Note: The router is mounted at /storefront prefix in main.py, so all links need storefront/ after base_url
How It Works:
1. StoreContextMiddleware detects access method
2. Sets request.state.store_context with detection_method
3. get_shop_context() calculates base_url from detection_method
3. get_storefront_context() calculates base_url from detection_method
4. Templates use {{ base_url }} for all internal links
5. Links work correctly regardless of access method
@@ -243,7 +243,7 @@ Detection Methods:
Layer 3: TEMPLATES (Jinja2)
──────────────────────────────────────────────────────────────────
Purpose: HTML Structure + Store Branding
Location: app/templates/shop/
Location: app/templates/storefront/
Template Hierarchy:
base.html (layout + theme injection)
@@ -253,7 +253,7 @@ Template Hierarchy:
partials/product-card.html (components)
Example:
{% extends "shop/base.html" %}
{% extends "storefront/base.html" %}
{% block title %}{{ store.name }}{% endblock %}
{% block alpine_data %}shopHome(){% endblock %}
{% block content %}
@@ -276,7 +276,7 @@ Key Features:
Layer 4: JAVASCRIPT (Alpine.js)
──────────────────────────────────────────────────────────────────
Purpose: Client-Side Interactivity + Cart + Search
Location: app/static/shop/js/
Location: app/static/storefront/js/
⚠️ CRITICAL: JavaScript Loading Order
──────────────────────────────────────────────────────────────────
@@ -284,14 +284,14 @@ Scripts MUST load in this exact order (see base.html):
1. log-config.js ← Logging system (loads first)
2. icons.js ← Icon registry
3. shop-layout.js ← Alpine component (before Alpine!)
3. storefront-layout.js ← Alpine component (before Alpine!)
4. utils.js ← Utility functions
5. api-client.js ← API wrapper
6. Alpine.js (deferred) ← Loads last
7. Page-specific JS ← Optional page scripts
Why This Order Matters:
• shop-layout.js defines storefrontLayoutData() BEFORE Alpine initializes
• storefront-layout.js defines storefrontLayoutData() BEFORE Alpine initializes
• Alpine.js defers to ensure DOM is ready
• Shared utilities available to all scripts
• Icons and logging available immediately
@@ -299,7 +299,7 @@ Why This Order Matters:
Example from base.html:
<script src="{{ url_for('static', path='shared/js/log-config.js') }}"></script>
<script src="{{ url_for('static', path='shared/js/icons.js') }}"></script>
<script src="{{ url_for('static', path='shop/js/shop-layout.js') }}"></script>
<script src="{{ url_for('static', path='storefront/js/storefront-layout.js') }}"></script>
<script src="{{ url_for('static', path='shared/js/utils.js') }}"></script>
<script src="{{ url_for('static', path='shared/js/api-client.js') }}"></script>
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
@@ -307,14 +307,14 @@ Example from base.html:
Alpine.js Component Architecture:
──────────────────────────────────────────────────────────────────
⭐ BASE COMPONENT (shop-layout.js):
⭐ BASE COMPONENT (storefront-layout.js):
Provides shared functionality for all shop pages:
Provides shared functionality for all storefront pages:
function storefrontLayoutData() {
return {
// Theme state
dark: localStorage.getItem('shop-theme') === 'dark',
dark: localStorage.getItem('storefront-theme') === 'dark',
// UI state
mobileMenuOpen: false,
@@ -325,12 +325,12 @@ Provides shared functionality for all shop pages:
cart: [],
init() {
shopLog.info('Shop layout initializing...');
shopLog.info('Storefront layout initializing...');
this.loadCart();
window.addEventListener('cart-updated', () => {
this.loadCart();
});
shopLog.info('Shop layout initialized');
shopLog.info('Storefront layout initialized');
},
addToCart(product, quantity = 1) {
@@ -356,7 +356,7 @@ Provides shared functionality for all shop pages:
toggleTheme() {
this.dark = !this.dark;
localStorage.setItem('shop-theme',
localStorage.setItem('storefront-theme',
this.dark ? 'dark' : 'light');
shopLog.debug('Theme toggled:', this.dark ? 'dark' : 'light');
},
@@ -393,7 +393,7 @@ Each page extends storefrontLayoutData() for page-specific functionality:
// Page-specific methods
async loadProducts() {
const response = await fetch('/api/v1/shop/products');
const response = await fetch('/api/v1/storefront/products');
const data = await response.json();
this.products = data.products;
this.loading = false;
@@ -454,30 +454,30 @@ Responsibilities:
Layer 5: API (REST)
──────────────────────────────────────────────────────────────────
Purpose: Product Data + Cart + Orders
Location: app/api/v1/shop/*.py
Location: app/api/v1/storefront/*.py
⭐ NEW API STRUCTURE (as of 2025-11-22):
All shop endpoints use middleware-based store context.
All storefront endpoints use middleware-based store context.
NO store_id or store_code in URLs!
Example Endpoints:
GET /api/v1/shop/products ← Product catalog
GET /api/v1/shop/products/{id} ← Product details
GET /api/v1/shop/products?search=... ← Search products
GET /api/v1/shop/cart/{session_id} ← Get cart
POST /api/v1/shop/cart/{session_id}/items ← Add to cart
PUT /api/v1/shop/cart/{session_id}/items/{product_id} ← Update item
DELETE /api/v1/shop/cart/{session_id}/items/{product_id} ← Remove item
POST /api/v1/shop/orders ← Place order (auth required)
GET /api/v1/shop/orders ← Order history (auth required)
POST /api/v1/shop/auth/login ← Customer login
POST /api/v1/shop/auth/register ← Customer registration
GET /api/v1/shop/content-pages/navigation ← CMS navigation
GET /api/v1/shop/content-pages/{slug} ← CMS page content
GET /api/v1/storefront/products ← Product catalog
GET /api/v1/storefront/products/{id} ← Product details
GET /api/v1/storefront/products?search=... ← Search products
GET /api/v1/storefront/cart/{session_id} ← Get cart
POST /api/v1/storefront/cart/{session_id}/items ← Add to cart
PUT /api/v1/storefront/cart/{session_id}/items/{product_id} ← Update item
DELETE /api/v1/storefront/cart/{session_id}/items/{product_id} ← Remove item
POST /api/v1/storefront/orders ← Place order (auth required)
GET /api/v1/storefront/orders ← Order history (auth required)
POST /api/v1/storefront/auth/login ← Customer login
POST /api/v1/storefront/auth/register ← Customer registration
GET /api/v1/storefront/content-pages/navigation ← CMS navigation
GET /api/v1/storefront/content-pages/{slug} ← CMS page content
How Store Context Works:
1. Browser makes API call from shop page (e.g., /stores/orion/shop/products)
2. Browser automatically sends Referer header: http://localhost:8000/stores/orion/shop/products
1. Browser makes API call from storefront page (e.g., /storefront/orion/products)
2. Browser automatically sends Referer header: http://localhost:8000/storefront/orion/products
3. StoreContextMiddleware extracts store from Referer header
4. Middleware sets request.state.store = <Store: orion>
5. API endpoint accesses store: store = request.state.store
@@ -489,13 +489,13 @@ How Store Context Works:
Page Load Flow:
──────────────────────────────────────────────────────────────────
1. Customer → visits acme-shop.com (or /stores/acme/shop/products)
1. Customer → visits acme-shop.com (or /storefront/acme/products)
2. Store Middleware → Identifies "ACME" store from domain/path
3. Theme Middleware → Loads ACME's theme config
4. FastAPI → Renders shop/products.html
4. FastAPI → Renders storefront/products.html
5. Browser → Receives HTML with theme CSS variables
6. Alpine.js → init() executes
7. JavaScript → GET /api/v1/shop/products (with Referer header)
7. JavaScript → GET /api/v1/storefront/products (with Referer header)
8. Middleware → Extracts store from Referer, injects into request.state
9. API → Returns product list JSON for ACME store
10. Alpine.js → Updates products array
@@ -516,7 +516,7 @@ Checkout Flow:
1. Customer → Goes to /cart
2. Page → Loads cart from localStorage
3. Customer → Fills checkout form
4. Alpine.js → POST /api/v1/shop/orders (with Referer header)
4. Alpine.js → POST /api/v1/storefront/orders (with Referer header)
5. Middleware → Extracts store from Referer
6. API → Creates order + payment intent for store
7. Alpine.js → Redirects to payment
@@ -621,7 +621,7 @@ Key Functions:
Cart Persistence:
• Survives page refresh
• Shared across shop pages
• Shared across storefront pages
• Cleared on checkout completion
• Synced across tabs (optional)
@@ -637,7 +637,7 @@ Search System:
• Keyboard shortcuts (Cmd+K)
2. Search API
POST /api/v1/shop/{store_code}/search
POST /api/v1/storefront/{store_code}/search
{
"query": "laptop",
"category": "electronics",
@@ -730,10 +730,10 @@ Account Features:
✅ Profile management
Auth Flow:
1. Login/Register → POST /api/v1/shop/auth/login (with Referer header)
1. Login/Register → POST /api/v1/storefront/auth/login (with Referer header)
2. Middleware → Extracts store from Referer
3. API → Validates credentials for store's customers
4. API → Returns JWT token + sets cookie (path=/shop)
4. API → Returns JWT token + sets cookie (path=/storefront)
5. JavaScript → Store token in localStorage
6. API Client → Add token to authenticated requests
7. Optional → Use account features (orders, profile, etc.)
@@ -745,9 +745,9 @@ Auth Flow:
All authentication pages use Tailwind CSS, Alpine.js, and theme integration
for a consistent, branded experience across all stores.
✅ Login Page (app/templates/shop/account/login.html)
✅ Login Page (app/templates/storefront/account/login.html)
──────────────────────────────────────────────────────────────────
Route: /shop/account/login
Route: /storefront/account/login
Features:
• Two-column layout (branding + form)
@@ -773,7 +773,7 @@ Alpine.js Component:
dark: false,
async handleLogin() {
// POST /api/v1/shop/auth/login
// POST /api/v1/storefront/auth/login
// Store token in localStorage
// Redirect to account or return URL
}
@@ -781,13 +781,13 @@ Alpine.js Component:
}
API Endpoint:
POST /api/v1/shop/auth/login
POST /api/v1/storefront/auth/login
Body: { email_or_username, password }
Returns: { access_token, user }
✅ Register Page (app/templates/shop/account/register.html)
✅ Register Page (app/templates/storefront/account/register.html)
──────────────────────────────────────────────────────────────────
Route: /shop/account/register
Route: /storefront/account/register
Features:
• Two-column layout with store branding
@@ -824,20 +824,20 @@ Alpine.js Component:
},
async handleRegister() {
// POST /api/v1/shop/auth/register
// POST /api/v1/storefront/auth/register
// Redirect to login?registered=true
}
}
}
API Endpoint:
POST /api/v1/shop/auth/register
POST /api/v1/storefront/auth/register
Body: { first_name, last_name, email, phone?, password, marketing_consent }
Returns: { message }
✅ Forgot Password Page (app/templates/shop/account/forgot-password.html)
✅ Forgot Password Page (app/templates/storefront/account/forgot-password.html)
──────────────────────────────────────────────────────────────────
Route: /shop/account/forgot-password
Route: /storefront/account/forgot-password
Features:
• Two-column layout with store branding
@@ -848,7 +848,7 @@ Features:
• Success state with checkmark icon
• Option to retry if email not received
• Theme-aware styling
• Links back to login and shop
• Links back to login and storefront
• Dark mode support
Alpine.js Component:
@@ -859,7 +859,7 @@ Alpine.js Component:
loading: false,
async handleSubmit() {
// POST /api/v1/shop/auth/forgot-password
// POST /api/v1/storefront/auth/forgot-password
// Show success message
// emailSent = true
}
@@ -867,7 +867,7 @@ Alpine.js Component:
}
API Endpoint:
POST /api/v1/shop/auth/forgot-password
POST /api/v1/storefront/auth/forgot-password
Body: { email }
Returns: { message }
@@ -907,7 +907,7 @@ Key Theme Elements:
Benefits:
✅ Each store's auth pages match their brand
✅ Consistent with main shop design
✅ Consistent with main storefront design
✅ Dark mode adapts to store colors
✅ Professional, polished appearance
@@ -959,17 +959,17 @@ No store_code needed! Store extracted from Referer header automatically.
Usage:
// Product catalog
const products = await fetch('/api/v1/shop/products');
const products = await fetch('/api/v1/storefront/products');
// Add to cart
const response = await fetch('/api/v1/shop/cart/session123/items', {
const response = await fetch('/api/v1/storefront/cart/session123/items', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ product_id: 1, quantity: 2 })
});
// Place order
const order = await fetch('/api/v1/shop/orders', {
const order = await fetch('/api/v1/storefront/orders', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(orderData)
@@ -987,7 +987,7 @@ Features:
Location: app/static/shared/js/log-config.js
Shop-Specific Logging:
Storefront-Specific Logging:
shopLog.info('Product added to cart', product);
shopLog.error('Checkout failed', error);
shopLog.debug('Search query', { query, results });
@@ -1008,7 +1008,7 @@ Usage:
<span x-html="$icon('shopping-cart', 'w-5 h-5')"></span>
<span x-html="$icon('search', 'w-6 h-6 text-primary')"></span>
Shop Icons:
Storefront Icons:
• shopping-cart, shopping-bag
• heart (wishlist)
• search, filter
@@ -1066,7 +1066,7 @@ Components:
• Category cards
• About store section
Data Sources:
• GET /api/v1/shop/products?is_featured=true
• GET /api/v1/storefront/products?is_featured=true
/products
──────────────────────────────────────────────────────────────────
@@ -1077,8 +1077,8 @@ Components:
• Sort dropdown
• Pagination
Data Sources:
• GET /api/v1/shop/products?skip=0&limit=20
• GET /api/v1/shop/products?search=query
• GET /api/v1/storefront/products?skip=0&limit=20
• GET /api/v1/storefront/products?search=query
• Filters applied client-side or server-side
/products/{product_id}
@@ -1091,8 +1091,8 @@ Components:
• Related products
• Reviews (optional)
Data Sources:
• GET /api/v1/shop/products/{id}
• GET /api/v1/shop/products?limit=4 (related products)
• GET /api/v1/storefront/products/{id}
• GET /api/v1/storefront/products?limit=4 (related products)
/cart
──────────────────────────────────────────────────────────────────
@@ -1116,7 +1116,7 @@ Components:
• Order summary
• Submit button
Data Sources:
• POST /api/v1/shop/orders
• POST /api/v1/storefront/orders
• Stripe/PayPal integration
/search
@@ -1128,7 +1128,7 @@ Components:
• Filter options
• Sort options
Data Sources:
• GET /api/v1/shop/products?search=query
• GET /api/v1/storefront/products?search=query
/category/{category_slug}
──────────────────────────────────────────────────────────────────
@@ -1139,7 +1139,7 @@ Components:
• Subcategories
• Filters
Data Sources:
• GET /api/v1/shop/products?category={slug}
• GET /api/v1/storefront/products?category={slug}
/about
──────────────────────────────────────────────────────────────────
@@ -1162,7 +1162,7 @@ Components:
• Business hours
• Social links
Data Sources:
• CMS content page (GET /api/v1/shop/content-pages/contact)
• CMS content page (GET /api/v1/storefront/content-pages/contact)
• Form submission to store email
@@ -1179,7 +1179,7 @@ For New Developers:
2. Study Existing Page (2 hours)
→ Open home.html
→ Open shop-layout.js
→ Open storefront-layout.js
→ Trace product loading flow
→ Examine cart management
@@ -1228,20 +1228,20 @@ Before Deploying:
Multi-Access Aware Error Pages:
All shop error pages (404, 500, etc.) are store-context aware and display
All storefront error pages (404, 500, etc.) are store-context aware and display
correct links based on the access method (domain, subdomain, or path-based).
Error Page Templates:
• app/templates/shop/errors/404.html - Not Found
• app/templates/shop/errors/400.html - Bad Request
• app/templates/shop/errors/401.html - Unauthorized
• app/templates/shop/errors/403.html - Forbidden
• app/templates/shop/errors/422.html - Validation Error
• app/templates/shop/errors/429.html - Rate Limited
• app/templates/shop/errors/500.html - Server Error
• app/templates/shop/errors/502.html - Bad Gateway
• app/templates/shop/errors/base.html - Base error template
• app/templates/shop/errors/generic.html - Generic error
• app/templates/storefront/errors/404.html - Not Found
• app/templates/storefront/errors/400.html - Bad Request
• app/templates/storefront/errors/401.html - Unauthorized
• app/templates/storefront/errors/403.html - Forbidden
• app/templates/storefront/errors/422.html - Validation Error
• app/templates/storefront/errors/429.html - Rate Limited
• app/templates/storefront/errors/500.html - Server Error
• app/templates/storefront/errors/502.html - Bad Gateway
• app/templates/storefront/errors/base.html - Base error template
• app/templates/storefront/errors/generic.html - Generic error
Error Renderer (app/exceptions/error_renderer.py):
@@ -1252,7 +1252,7 @@ Calculates base_url dynamically based on store access method:
access_method = getattr(request.state, "access_method", None)
store_context = getattr(request.state, "store_context", None)
# Calculate base_url for shop links
# Calculate base_url for storefront links
base_url = "/"
if access_method == "path" and store:
full_prefix = store_context.get('full_prefix', '/store/')
@@ -1280,13 +1280,13 @@ All error page links use {{ base_url }} prefix for correct routing:
How It Works:
1. Error occurs (404, 500, etc.)
2. Exception handler detects shop context
2. Exception handler detects storefront context
3. error_renderer.py calculates base_url from store_context
4. Error template renders with correct base_url
5. Links work for all access methods:
- Domain: customshop.com → base_url = "/"
- Subdomain: orion.platform.com → base_url = "/"
- Path: localhost/stores/orion/ → base_url = "/stores/orion/"
- Path: localhost/storefront/orion/ → base_url = "/storefront/orion/"
Benefits:
✅ Error pages work correctly regardless of access method
@@ -1333,13 +1333,13 @@ Documentation:
• FastAPI: https://fastapi.tiangolo.com/
Internal Docs:
• Page Template Guide: FRONTEND_SHOP_ALPINE_PAGE_TEMPLATE.md
• Multi-Theme Guide: MULTI_THEME_SHOP_GUIDE.md
• Page Template Guide: FRONTEND_STOREFRONT_ALPINE_PAGE_TEMPLATE.md
• Multi-Theme Guide: MULTI_THEME_STOREFRONT_GUIDE.md
• API Documentation: API_REFERENCE.md
• Database Schema: DATABASE_SCHEMA.md
══════════════════════════════════════════════════════════════════
SHOP FRONTEND ARCHITECTURE
STOREFRONT FRONTEND ARCHITECTURE
Theme-Driven, Customer-Focused, Brand-Consistent
══════════════════════════════════════════════════════════════════

View File

@@ -1,8 +1,8 @@
# Shop Authentication Pages
# Storefront Authentication Pages
## Overview
This document details the implementation of customer authentication pages in the shop frontend. All pages use Tailwind CSS, Alpine.js, and integrate with the multi-theme system for a branded, consistent experience across all stores.
This document details the implementation of customer authentication pages in the storefront frontend. All pages use Tailwind CSS, Alpine.js, and integrate with the multi-theme system for a branded, consistent experience across all stores.
## Implementation Date
2025-11-24
@@ -12,8 +12,8 @@ This document details the implementation of customer authentication pages in the
## 📄 Available Pages
### 1. Login Page
**Location:** `app/templates/shop/account/login.html`
**Route:** `/shop/account/login`
**Location:** `app/templates/storefront/account/login.html`
**Route:** `/storefront/account/login`
#### Features
- Two-column layout with store branding on the left
@@ -41,7 +41,7 @@ function customerLogin() {
async handleLogin() {
// Validates input
// Calls POST /api/v1/shop/auth/login
// Calls POST /api/v1/storefront/auth/login
// Stores token in localStorage
// Redirects to account page or return URL
}
@@ -50,15 +50,15 @@ function customerLogin() {
```
#### API Integration
- **Endpoint:** `POST /api/v1/shop/auth/login`
- **Endpoint:** `POST /api/v1/storefront/auth/login`
- **Request:** `{ email_or_username: string, password: string }`
- **Response:** `{ access_token: string, user: object }`
---
### 2. Register Page
**Location:** `app/templates/shop/account/register.html`
**Route:** `/shop/account/register`
**Location:** `app/templates/storefront/account/register.html`
**Route:** `/storefront/account/register`
#### Features
- Two-column layout with store branding
@@ -110,7 +110,7 @@ function customerRegistration() {
async handleRegister() {
// Validates form
// Calls POST /api/v1/shop/auth/register
// Calls POST /api/v1/storefront/auth/register
// Shows success message
// Redirects to login with ?registered=true
}
@@ -119,15 +119,15 @@ function customerRegistration() {
```
#### API Integration
- **Endpoint:** `POST /api/v1/shop/auth/register`
- **Endpoint:** `POST /api/v1/storefront/auth/register`
- **Request:** `{ first_name: string, last_name: string, email: string, phone?: string, password: string, marketing_consent: boolean }`
- **Response:** `{ message: string }`
---
### 3. Forgot Password Page
**Location:** `app/templates/shop/account/forgot-password.html`
**Route:** `/shop/account/forgot-password`
**Location:** `app/templates/storefront/account/forgot-password.html`
**Route:** `/storefront/account/forgot-password`
#### Features
- Two-column layout with store branding
@@ -142,7 +142,7 @@ function customerRegistration() {
- Instructions to check inbox
- Option to retry if email not received
- Theme-aware styling
- Links back to login and shop homepage
- Links back to login and storefront homepage
- Dark mode support
- Mobile responsive
@@ -159,7 +159,7 @@ function forgotPassword() {
async handleSubmit() {
// Validates email
// Calls POST /api/v1/shop/auth/forgot-password
// Calls POST /api/v1/storefront/auth/forgot-password
// Sets emailSent = true on success
// Shows confirmation message
}
@@ -168,7 +168,7 @@ function forgotPassword() {
```
#### API Integration
- **Endpoint:** `POST /api/v1/shop/auth/forgot-password`
- **Endpoint:** `POST /api/v1/storefront/auth/forgot-password`
- **Request:** `{ email: string }`
- **Response:** `{ message: string }`
@@ -214,7 +214,7 @@ All authentication pages inject the store's theme CSS variables for consistent b
### Benefits
- ✅ Each store's auth pages automatically match their brand
- ✅ Consistent with main shop design
- ✅ Consistent with main storefront design
- ✅ Dark mode adapts to store colors
- ✅ Professional, polished appearance
- ✅ No custom CSS needed per store
@@ -303,7 +303,7 @@ All authentication pages inject the store's theme CSS variables for consistent b
## 🔗 Navigation Flow
```
Shop Homepage
Storefront Homepage
Login Page ←→ Register Page
↓ ↓
@@ -314,16 +314,16 @@ Check Email Account/Cart
### Link Structure
- **Login Page:**
- "Forgot password?" → `/shop/account/forgot-password`
- "Create an account" → `/shop/account/register`
- "← Continue shopping" → `/shop/`
- "Forgot password?" → `/storefront/account/forgot-password`
- "Create an account" → `/storefront/account/register`
- "← Continue shopping" → `/storefront/`
- **Register Page:**
- "Already have an account? Sign in instead" → `/shop/account/login`
- "Already have an account? Sign in instead" → `/storefront/account/login`
- **Forgot Password Page:**
- "Remember your password? Sign in" → `/shop/account/login`
- "← Continue shopping" → `/shop/`
- "Remember your password? Sign in" → `/storefront/account/login`
- "← Continue shopping" → `/storefront/`
All links use `{{ base_url }}` for multi-access routing support.
@@ -386,12 +386,12 @@ No code changes needed - all controlled via theme configuration.
```
app/
├── templates/shop/account/
├── templates/storefront/account/
│ ├── login.html ← Customer login page
│ ├── register.html ← Customer registration page
│ └── forgot-password.html ← Password reset page
└── api/v1/shop/
└── api/v1/storefront/
└── auth.py ← Authentication endpoints
static/shared/css/
@@ -463,7 +463,7 @@ Possible additions:
## 📚 Related Documentation
- [Shop Frontend Architecture](./architecture.md)
- [Storefront Frontend Architecture](./architecture.md)
- [Page Template Guide](./page-templates.md)
- [Theme System Overview](../../architecture/theme-system/overview.md)
- [Theme Presets](../../architecture/theme-system/presets.md)

View File

@@ -28,7 +28,7 @@ This document proposes a comprehensive set of reusable Jinja macro components fo
### Priority 1: Core Shopping Components
#### 1.1 Product Card
**File:** `app/templates/shared/macros/shop/product-card.html`
**File:** `app/templates/shared/macros/storefront/product-card.html`
A versatile product card for grids, carousels, and lists.
@@ -63,7 +63,7 @@ A versatile product card for grids, carousels, and lists.
---
#### 1.2 Product Grid
**File:** `app/templates/shared/macros/shop/product-grid.html`
**File:** `app/templates/shared/macros/storefront/product-grid.html`
Responsive grid layout for product listings.
@@ -85,7 +85,7 @@ Responsive grid layout for product listings.
---
#### 1.3 Add to Cart Button
**File:** `app/templates/shared/macros/shop/add-to-cart.html`
**File:** `app/templates/shared/macros/storefront/add-to-cart.html`
Standardized add-to-cart functionality.
@@ -115,7 +115,7 @@ Standardized add-to-cart functionality.
Shop-specific wrapper with stock validation:
```jinja
{{ shop_quantity_selector(
{{ storefront_quantity_selector(
model='quantity',
max='product.stock',
disabled_var='addingToCart',
@@ -128,7 +128,7 @@ Shop-specific wrapper with stock validation:
### Priority 2: Cart Components
#### 2.1 Mini Cart (Header Dropdown)
**File:** `app/templates/shared/macros/shop/mini-cart.html`
**File:** `app/templates/shared/macros/storefront/mini-cart.html`
Dropdown cart preview in the header.
@@ -151,7 +151,7 @@ Dropdown cart preview in the header.
---
#### 2.2 Cart Item Row
**File:** `app/templates/shared/macros/shop/cart-item.html`
**File:** `app/templates/shared/macros/storefront/cart-item.html`
Individual cart line item.
@@ -177,7 +177,7 @@ Individual cart line item.
---
#### 2.3 Cart Summary
**File:** `app/templates/shared/macros/shop/cart-summary.html`
**File:** `app/templates/shared/macros/storefront/cart-summary.html`
Order summary sidebar/section.
@@ -205,7 +205,7 @@ Order summary sidebar/section.
### Priority 3: Product Detail Components
#### 3.1 Product Gallery
**File:** `app/templates/shared/macros/shop/product-gallery.html`
**File:** `app/templates/shared/macros/storefront/product-gallery.html`
Image gallery with thumbnails and zoom.
@@ -229,7 +229,7 @@ Image gallery with thumbnails and zoom.
---
#### 3.2 Variant Selector
**File:** `app/templates/shared/macros/shop/variant-selector.html`
**File:** `app/templates/shared/macros/storefront/variant-selector.html`
Product variant selection (size, color, etc.).
@@ -255,7 +255,7 @@ Product variant selection (size, color, etc.).
---
#### 3.3 Product Info Block
**File:** `app/templates/shared/macros/shop/product-info.html`
**File:** `app/templates/shared/macros/storefront/product-info.html`
Product details section.
@@ -280,7 +280,7 @@ Product details section.
---
#### 3.4 Product Tabs
**File:** `app/templates/shared/macros/shop/product-tabs.html`
**File:** `app/templates/shared/macros/storefront/product-tabs.html`
Tabbed product information.
@@ -303,7 +303,7 @@ Tabbed product information.
### Priority 4: Navigation & Discovery
#### 4.1 Category Navigation
**File:** `app/templates/shared/macros/shop/category-nav.html`
**File:** `app/templates/shared/macros/storefront/category-nav.html`
Category browsing sidebar/menu.
@@ -326,12 +326,12 @@ Category browsing sidebar/menu.
---
#### 4.2 Breadcrumbs
**File:** `app/templates/shared/macros/shop/breadcrumbs.html`
**File:** `app/templates/shared/macros/storefront/breadcrumbs.html`
Navigation breadcrumb trail.
```jinja
{{ shop_breadcrumbs(
{{ storefront_breadcrumbs(
items=[
{'label': 'Home', 'url': '/'},
{'label': 'Electronics', 'url': '/category/electronics'},
@@ -343,7 +343,7 @@ Navigation breadcrumb trail.
---
#### 4.3 Search Bar
**File:** `app/templates/shared/macros/shop/search-bar.html`
**File:** `app/templates/shared/macros/storefront/search-bar.html`
Product search with autocomplete.
@@ -365,7 +365,7 @@ Product search with autocomplete.
---
#### 4.4 Filter Sidebar
**File:** `app/templates/shared/macros/shop/filter-sidebar.html`
**File:** `app/templates/shared/macros/storefront/filter-sidebar.html`
Product filtering panel.
@@ -390,7 +390,7 @@ Product filtering panel.
### Priority 5: Social Proof & Trust
#### 5.1 Star Rating
**File:** `app/templates/shared/macros/shop/star-rating.html`
**File:** `app/templates/shared/macros/storefront/star-rating.html`
Reusable star rating display.
@@ -407,7 +407,7 @@ Reusable star rating display.
---
#### 5.2 Review Card
**File:** `app/templates/shared/macros/shop/review-card.html`
**File:** `app/templates/shared/macros/storefront/review-card.html`
Individual product review.
@@ -431,7 +431,7 @@ Individual product review.
---
#### 5.3 Trust Badges
**File:** `app/templates/shared/macros/shop/trust-badges.html`
**File:** `app/templates/shared/macros/storefront/trust-badges.html`
Trust and security indicators.
@@ -454,7 +454,7 @@ Trust and security indicators.
### Priority 6: Promotional Components
#### 6.1 Sale Banner
**File:** `app/templates/shared/macros/shop/sale-banner.html`
**File:** `app/templates/shared/macros/storefront/sale-banner.html`
Promotional banner with countdown.
@@ -472,7 +472,7 @@ Promotional banner with countdown.
---
#### 6.2 Product Badge
**File:** `app/templates/shared/macros/shop/product-badge.html`
**File:** `app/templates/shared/macros/storefront/product-badge.html`
Product overlay badges.
@@ -486,7 +486,7 @@ Product overlay badges.
---
#### 6.3 Recently Viewed
**File:** `app/templates/shared/macros/shop/recently-viewed.html`
**File:** `app/templates/shared/macros/storefront/recently-viewed.html`
Recently viewed products carousel.
@@ -578,7 +578,7 @@ All shop components will use these CSS variables set by the store theme:
## File Structure
```
app/templates/shared/macros/shop/
app/templates/shared/macros/storefront/
├── product-card.html
├── product-grid.html
├── add-to-cart.html

View File

@@ -1,22 +1,22 @@
# Shop Navigation Flow
# Storefront Navigation Flow
Complete guide to navigation structure and URL hierarchy with landing pages.
## URL Hierarchy
```
/ (Store Root) → Landing Page (if exists) OR redirect to /shop/
├── /shop/ → E-commerce Homepage (Product Catalog)
│ ├── /shop/products → Product Catalog (same as /shop/)
│ ├── /shop/products/{id} → Product Detail Page
│ ├── /shop/cart → Shopping Cart
│ ├── /shop/checkout → Checkout Process
│ ├── /shop/account/login → Customer Login
│ ├── /shop/account/register → Customer Registration
│ ├── /shop/account/dashboard → Customer Dashboard (auth required)
│ ├── /shop/about → CMS Content Page
│ ├── /shop/contact → CMS Content Page
│ └── /shop/{slug} → Other CMS Pages
/ (Store Root) → Landing Page (if exists) OR redirect to /storefront/
├── /storefront/ → E-commerce Homepage (Product Catalog)
│ ├── /storefront/products → Product Catalog (same as /storefront/)
│ ├── /storefront/products/{id} → Product Detail Page
│ ├── /storefront/cart → Shopping Cart
│ ├── /storefront/checkout → Checkout Process
│ ├── /storefront/account/login → Customer Login
│ ├── /storefront/account/register → Customer Registration
│ ├── /storefront/account/dashboard → Customer Dashboard (auth required)
│ ├── /storefront/about → CMS Content Page
│ ├── /storefront/contact → CMS Content Page
│ └── /storefront/{slug} → Other CMS Pages
```
## Navigation Patterns
@@ -26,13 +26,13 @@ Complete guide to navigation structure and URL hierarchy with landing pages.
**URL Structure:**
```
customdomain.com/ → Landing Page (marketing/brand)
customdomain.com/shop/ → E-commerce Shop
customdomain.com/shop/products → Product Catalog
customdomain.com/storefront/ → E-commerce Storefront
customdomain.com/storefront/products → Product Catalog
```
**Navigation Flow:**
1. User visits store domain → **Landing Page**
2. Clicks "Shop Now" → **/shop/** (product catalog)
2. Clicks "Shop Now" → **/storefront/** (product catalog)
3. Clicks "Home" in breadcrumb → **/** (back to landing page)
4. Clicks logo → **/** (back to landing page)
@@ -47,46 +47,46 @@ Home > Products
**URL Structure:**
```
customdomain.com/ → Redirects to /shop/
customdomain.com/shop/ → E-commerce Shop
customdomain.com/shop/products → Product Catalog
customdomain.com/ → Redirects to /storefront/
customdomain.com/storefront/ → E-commerce Storefront
customdomain.com/storefront/products → Product Catalog
```
**Navigation Flow:**
1. User visits store domain → **Redirects to /shop/**
2. User browses shop
3. Clicks "Home" in breadcrumb → **/** (redirects to /shop/)
4. Clicks logo → **/** (redirects to /shop/)
1. User visits store domain → **Redirects to /storefront/**
2. User browses storefront
3. Clicks "Home" in breadcrumb → **/** (redirects to /storefront/)
4. Clicks logo → **/** (redirects to /storefront/)
**Breadcrumb Example (on Products page):**
```
Home > Products
/ → /shop/ (redirects)
/ → /storefront/ (redirects)
```
## Link References
### Base URL Calculation
The `base_url` variable is calculated in `shop_pages.py:get_shop_context()`:
The `base_url` variable is calculated in `storefront_pages.py:get_storefront_context()`:
```python
# For domain/subdomain access
base_url = "/"
# Result: /shop/products, /shop/cart, etc.
# Result: /storefront/products, /storefront/cart, etc.
# For path-based access
base_url = "/stores/orion/"
# Result: /stores/orion/shop/products, /stores/orion/shop/cart, etc.
base_url = "/storefront/orion/"
# Result: /storefront/orion/products, /storefront/orion/cart, etc.
```
### Template Links
**Logo / Home Link (Header):**
```jinja2
{# Points to store root (landing page or shop) #}
<a href="{{ base_url }}shop/">{{ store.name }}</a>
{# Points to store root (landing page or storefront) #}
<a href="{{ base_url }}storefront/">{{ store.name }}</a>
```
**Breadcrumb Home Link:**
@@ -95,20 +95,20 @@ base_url = "/stores/orion/"
<a href="{{ base_url }}">Home</a>
```
**Shop Links:**
**Storefront Links:**
```jinja2
{# All shop pages include /shop/ prefix #}
<a href="{{ base_url }}shop/products">Products</a>
<a href="{{ base_url }}shop/cart">Cart</a>
<a href="{{ base_url }}shop/checkout">Checkout</a>
{# All storefront pages include /storefront/ prefix #}
<a href="{{ base_url }}storefront/products">Products</a>
<a href="{{ base_url }}storefront/cart">Cart</a>
<a href="{{ base_url }}storefront/checkout">Checkout</a>
```
**CMS Page Links:**
```jinja2
{# CMS pages are under /shop/ #}
<a href="{{ base_url }}shop/about">About</a>
<a href="{{ base_url }}shop/contact">Contact</a>
<a href="{{ base_url }}shop/{{ page.slug }}">{{ page.title }}</a>
{# CMS pages are under /storefront/ #}
<a href="{{ base_url }}storefront/about">About</a>
<a href="{{ base_url }}storefront/contact">Contact</a>
<a href="{{ base_url }}storefront/{{ page.slug }}">{{ page.title }}</a>
```
## Complete URL Examples
@@ -116,46 +116,46 @@ base_url = "/stores/orion/"
### Path-Based Access (Development)
```
http://localhost:8000/stores/orion/
├── / (root) → Landing Page OR redirect to shop
├── /shop/ → Shop Homepage
├── /shop/products → Product Catalog
├── /shop/products/4 → Product Detail
├── /shop/cart → Shopping Cart
├── /shop/checkout → Checkout
├── /shop/account/login → Customer Login
├── /shop/about → About Page (CMS)
└── /shop/contact → Contact Page (CMS)
http://localhost:8000/storefront/orion/
├── / (root) → Landing Page OR redirect to storefront
├── /storefront/ → Storefront Homepage
├── /storefront/products → Product Catalog
├── /storefront/products/4 → Product Detail
├── /storefront/cart → Shopping Cart
├── /storefront/checkout → Checkout
├── /storefront/account/login → Customer Login
├── /storefront/about → About Page (CMS)
└── /storefront/contact → Contact Page (CMS)
```
### Subdomain Access (Production)
```
https://orion.platform.com/
├── / (root) → Landing Page OR redirect to shop
├── /shop/ → Shop Homepage
├── /shop/products → Product Catalog
├── /shop/products/4 → Product Detail
├── /shop/cart → Shopping Cart
├── /shop/checkout → Checkout
├── /shop/account/login → Customer Login
├── /shop/about → About Page (CMS)
└── /shop/contact → Contact Page (CMS)
├── / (root) → Landing Page OR redirect to storefront
├── /storefront/ → Storefront Homepage
├── /storefront/products → Product Catalog
├── /storefront/products/4 → Product Detail
├── /storefront/cart → Shopping Cart
├── /storefront/checkout → Checkout
├── /storefront/account/login → Customer Login
├── /storefront/about → About Page (CMS)
└── /storefront/contact → Contact Page (CMS)
```
### Custom Domain Access (Production)
```
https://customdomain.com/
├── / (root) → Landing Page OR redirect to shop
├── /shop/ → Shop Homepage
├── /shop/products → Product Catalog
├── /shop/products/4 → Product Detail
├── /shop/cart → Shopping Cart
├── /shop/checkout → Checkout
├── /shop/account/login → Customer Login
├── /shop/about → About Page (CMS)
└── /shop/contact → Contact Page (CMS)
├── / (root) → Landing Page OR redirect to storefront
├── /storefront/ → Storefront Homepage
├── /storefront/products → Product Catalog
├── /storefront/products/4 → Product Detail
├── /storefront/cart → Shopping Cart
├── /storefront/checkout → Checkout
├── /storefront/account/login → Customer Login
├── /storefront/about → About Page (CMS)
└── /storefront/contact → Contact Page (CMS)
```
## User Journeys
@@ -164,26 +164,26 @@ https://customdomain.com/
1. Visit `customdomain.com/`**Landing Page**
- Sees brand story, features, CTA
2. Clicks "Shop Now" → `/shop/`**Product Catalog**
2. Clicks "Shop Now" → `/storefront/`**Product Catalog**
- Browses products
3. Clicks product → `/shop/products/4`**Product Detail**
3. Clicks product → `/storefront/products/4`**Product Detail**
- Views product
4. Clicks "Home" in breadcrumb → `/`**Back to Landing Page**
5. Clicks logo → `/`**Back to Landing Page**
### Journey 2: Returning Customer (Direct to Shop)
### Journey 2: Returning Customer (Direct to Storefront)
1. Visit `customdomain.com/shop/`**Product Catalog**
- Already knows the brand, goes straight to shop
2. Adds to cart → `/shop/cart`**Shopping Cart**
3. Checkout → `/shop/checkout`**Checkout**
1. Visit `customdomain.com/storefront/`**Product Catalog**
- Already knows the brand, goes straight to storefront
2. Adds to cart → `/storefront/cart`**Shopping Cart**
3. Checkout → `/storefront/checkout`**Checkout**
4. Clicks "Home" → `/`**Landing Page** (brand homepage)
### Journey 3: Customer Account Management
1. Visit `customdomain.com/shop/account/login`**Login**
2. After login → `/shop/account/dashboard`**Dashboard**
3. View orders → `/shop/account/orders`**Order History**
1. Visit `customdomain.com/storefront/account/login`**Login**
2. After login → `/storefront/account/dashboard`**Dashboard**
3. View orders → `/storefront/account/orders`**Order History**
4. Clicks logo → `/`**Back to Landing Page**
## Navigation Components
@@ -192,32 +192,32 @@ https://customdomain.com/
```jinja2
{# Logo - always points to store root #}
<a href="{{ base_url }}shop/">
<a href="{{ base_url }}storefront/">
<img src="{{ theme.branding.logo }}" alt="{{ store.name }}">
</a>
{# Main Navigation #}
<nav>
<a href="{{ base_url }}shop/">Home</a>
<a href="{{ base_url }}shop/products">Products</a>
<a href="{{ base_url }}shop/about">About</a>
<a href="{{ base_url }}shop/contact">Contact</a>
<a href="{{ base_url }}storefront/">Home</a>
<a href="{{ base_url }}storefront/products">Products</a>
<a href="{{ base_url }}storefront/about">About</a>
<a href="{{ base_url }}storefront/contact">Contact</a>
</nav>
{# Actions #}
<a href="{{ base_url }}shop/cart">Cart</a>
<a href="{{ base_url }}shop/account">Account</a>
<a href="{{ base_url }}storefront/cart">Cart</a>
<a href="{{ base_url }}storefront/account">Account</a>
```
### Footer Navigation (base.html)
```jinja2
{# Quick Links #}
<a href="{{ base_url }}shop/products">Products</a>
<a href="{{ base_url }}storefront/products">Products</a>
{# CMS Pages (dynamic) #}
{% for page in footer_pages %}
<a href="{{ base_url }}shop/{{ page.slug }}">{{ page.title }}</a>
<a href="{{ base_url }}storefront/{{ page.slug }}">{{ page.title }}</a>
{% endfor %}
```
@@ -233,39 +233,39 @@ https://customdomain.com/
### ✅ DO:
1. **Use Landing Pages**: Create engaging landing pages at store root
2. **Clear Navigation**: Make it easy to get from landing to shop and back
2. **Clear Navigation**: Make it easy to get from landing to storefront and back
3. **Consistent "Home"**: Logo and "Home" breadcrumb both point to `/` (landing)
4. **Shop Links**: All shop-related links include `/shop/` prefix
5. **CMS Under Shop**: Keep CMS pages under `/shop/` for consistency
4. **Storefront Links**: All storefront-related links include `/storefront/` prefix
5. **CMS Under Storefront**: Keep CMS pages under `/storefront/` for consistency
### ❌ DON'T:
1. **Hardcode URLs**: Always use `{{ base_url }}` for store-aware links
2. **Skip /shop/**: Don't link directly to `/products`, use `/shop/products`
3. **Mix Landing & Shop**: Keep landing page separate from shop catalog
2. **Skip /storefront/**: Don't link directly to `/products`, use `/storefront/products`
3. **Mix Landing & Storefront**: Keep landing page separate from storefront catalog
4. **Forget Breadcrumbs**: Always provide "Home" link to go back
## Migration Notes
### Before Landing Pages
All links pointed to `/shop/`:
All links pointed to `/storefront/`:
```jinja2
<a href="{{ base_url }}shop/">Home</a> {# Logo #}
<a href="{{ base_url }}shop/">Home</a> {# Breadcrumb #}
<a href="{{ base_url }}storefront/">Home</a> {# Logo #}
<a href="{{ base_url }}storefront/">Home</a> {# Breadcrumb #}
```
### After Landing Pages
Separation of concerns:
```jinja2
<a href="{{ base_url }}shop/">Home</a> {# Logo - still goes to shop #}
<a href="{{ base_url }}storefront/">Home</a> {# Logo - still goes to storefront #}
<a href="{{ base_url }}">Home</a> {# Breadcrumb - goes to landing #}
```
This allows:
- Landing page at `/` for marketing/branding
- Shop catalog at `/shop/` for e-commerce
- Storefront catalog at `/storefront/` for e-commerce
- Clean navigation between the two
## Technical Implementation
@@ -273,27 +273,27 @@ This allows:
### Route Handlers (main.py)
```python
# Store root - serves landing page or redirects to shop
# Store root - serves landing page or redirects to storefront
@app.get("/")
@app.get("/stores/{store_code}/")
@app.get("/storefront/{store_code}/")
async def root(request: Request):
if has_landing_page():
return render_landing_page()
else:
return redirect_to_shop()
return redirect_to_storefront()
# Shop routes
@app.include_router(shop_pages.router, prefix="/shop")
@app.include_router(shop_pages.router, prefix="/stores/{store_code}/shop")
# Storefront routes
@app.include_router(storefront_pages.router, prefix="/storefront")
@app.include_router(storefront_pages.router, prefix="/storefront/{store_code}")
```
### Context Calculation (shop_pages.py)
### Context Calculation (storefront_pages.py)
```python
def get_shop_context(request: Request):
def get_storefront_context(request: Request):
base_url = "/"
if access_method == "path":
base_url = f"/stores/{store.subdomain}/"
base_url = f"/storefront/{store.subdomain}/"
return {
"base_url": base_url,
@@ -308,11 +308,11 @@ def get_shop_context(request: Request):
The navigation system creates a **two-tier structure**:
1. **Landing Page** (`/`) - Marketing, branding, store story
2. **Shop** (`/shop/`) - E-commerce, products, cart, checkout
2. **Storefront** (`/storefront/`) - E-commerce, products, cart, checkout
This gives stores flexibility to:
- Have a marketing homepage separate from their store
- Choose different landing page designs (minimal, modern, full)
- Or skip the landing page and go straight to the shop
- Or skip the landing page and go straight to the storefront
All while maintaining clean, consistent navigation throughout the experience.

View File

@@ -1,8 +1,8 @@
# Shop Frontend - Alpine.js/Jinja2 Page Template Guide
# Storefront Frontend - Alpine.js/Jinja2 Page Template Guide
## 📋 Overview
This guide provides complete templates for creating new customer-facing shop pages using the established Alpine.js + Jinja2 + Multi-Theme architecture. Follow these patterns to ensure consistency across all store shops while maintaining unique branding.
This guide provides complete templates for creating new customer-facing storefront pages using the established Alpine.js + Jinja2 + Multi-Theme architecture. Follow these patterns to ensure consistency across all store storefronts while maintaining unique branding.
---
@@ -10,9 +10,9 @@ This guide provides complete templates for creating new customer-facing shop pag
Three fully-implemented authentication pages are available for reference:
- **Login** (`app/templates/shop/account/login.html`) - Customer sign-in with email/password
- **Register** (`app/templates/shop/account/register.html`) - New customer account creation
- **Forgot Password** (`app/templates/shop/account/forgot-password.html`) - Password reset flow
- **Login** (`app/templates/storefront/account/login.html`) - Customer sign-in with email/password
- **Register** (`app/templates/storefront/account/register.html`) - New customer account creation
- **Forgot Password** (`app/templates/storefront/account/forgot-password.html`) - Password reset flow
All authentication pages feature:
- ✅ Tailwind CSS styling
@@ -24,7 +24,7 @@ All authentication pages feature:
- ✅ Loading states
- ✅ Error handling
See the [Shop Architecture Documentation](./architecture.md) (Authentication Pages section) for complete details.
See the [Storefront Architecture Documentation](./architecture.md) (Authentication Pages section) for complete details.
---
@@ -33,16 +33,16 @@ See the [Shop Architecture Documentation](./architecture.md) (Authentication Pag
### File Structure for New Page
```
app/
├── templates/shop/
├── templates/storefront/
│ └── [page-name].html # Jinja2 template
├── static/shop/js/
├── static/storefront/js/
│ └── [page-name].js # Alpine.js component
└── api/v1/shop/
└── api/v1/storefront/
└── pages.py # Route registration
```
### Checklist for New Page
- [ ] Create Jinja2 template extending shop/base.html
- [ ] Create Jinja2 template extending storefront/base.html
- [ ] Create Alpine.js JavaScript component
- [ ] Register route in pages.py
- [ ] Test with multiple store themes
@@ -58,11 +58,11 @@ app/
### 1. Jinja2 Template
**File:** `app/templates/shop/[page-name].html`
**File:** `app/templates/storefront/[page-name].html`
```jinja2
{# app/templates/shop/[page-name].html #}
{% extends "shop/base.html" %}
{# app/templates/storefront/[page-name].html #}
{% extends "storefront/base.html" %}
{# Page title for browser tab - includes store name #}
{% block title %}[Page Name] - {{ store.name }}{% endblock %}
@@ -174,7 +174,7 @@ app/
<!-- Item Image -->
<div class="aspect-w-1 aspect-h-1 w-full overflow-hidden rounded-t-lg bg-gray-100 dark:bg-gray-700">
<img :src="item.image || '/static/shop/img/placeholder-product.png'"
<img :src="item.image || '/static/storefront/img/placeholder-product.png'"
:alt="item.name"
class="w-full h-full object-cover object-center hover:scale-105 transition-transform"
loading="lazy">
@@ -247,7 +247,7 @@ app/
{# Page-specific JavaScript #}
{% block extra_scripts %}
<script src="{{ url_for('static', path='shop/js/[page-name].js') }}"></script>
<script src="{{ url_for('static', path='storefront/js/[page-name].js') }}"></script>
{% endblock %}
```
@@ -255,10 +255,10 @@ app/
### 2. Alpine.js Component
**File:** `app/static/shop/js/[page-name].js`
**File:** `app/static/storefront/js/[page-name].js`
```javascript
// static/shop/js/[page-name].js
// static/storefront/js/[page-name].js
/**
* [Page Name] Component
* Handles [describe functionality]
@@ -333,7 +333,7 @@ function shop[PageName]() {
});
const response = await fetch(
`/api/v1/shop/${this.storeCode}/items?${params}`
`/api/v1/storefront/${this.storeCode}/items?${params}`
);
if (!response.ok) {
@@ -444,14 +444,14 @@ function shop[PageName]() {
addToCart(item, quantity = 1) {
pageLog.info('Adding to cart:', item.name);
// Get cart from shop layout
// Get cart from storefront layout
const shopLayout = Alpine.store('shop') || window.storefrontLayoutData();
if (shopLayout && typeof shopLayout.addToCart === 'function') {
shopLayout.addToCart(item, quantity);
this.showToast(`${item.name} added to cart`, 'success');
} else {
pageLog.error('Shop layout not available');
pageLog.error('Storefront layout not available');
}
},
@@ -513,7 +513,7 @@ pageLog.info('[PageName] module loaded');
### 3. Route Registration
**File:** `app/api/v1/shop/pages.py`
**File:** `app/api/v1/storefront/pages.py`
```python
from fastapi import APIRouter, Request, Depends
@@ -536,7 +536,7 @@ async def [page_name]_page(
theme = request.state.theme
return templates.TemplateResponse(
"shop/[page-name].html",
"storefront/[page-name].html",
{
"request": request,
"store": store,
@@ -562,7 +562,7 @@ async loadProducts() {
this.loading = true;
try {
const response = await fetch(
`/api/v1/shop/${this.storeCode}/products?category=${this.category}`
`/api/v1/storefront/${this.storeCode}/products?category=${this.category}`
);
const data = await response.json();
this.products = data.products || [];
@@ -578,7 +578,7 @@ async loadProducts() {
```html
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
<template x-for="product in products" :key="product.id">
{% include 'shop/partials/product-card.html' %}
{% include 'storefront/partials/product-card.html' %}
</template>
</div>
```
@@ -598,7 +598,7 @@ async init() {
async loadProduct(id) {
const product = await fetch(
`/api/v1/shop/${this.storeCode}/products/${id}`
`/api/v1/storefront/${this.storeCode}/products/${id}`
).then(r => r.json());
this.product = product;
@@ -713,7 +713,7 @@ async performSearch() {
this.loading = true;
try {
const response = await fetch(
`/api/v1/shop/${this.storeCode}/search`,
`/api/v1/storefront/${this.storeCode}/search`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -750,10 +750,10 @@ Always use CSS variables for store colors:
### 2. Cart Integration
Always use the shop layout's cart methods:
Always use the storefront layout's cart methods:
```javascript
// ✅ GOOD: Uses shop layout
// ✅ GOOD: Uses storefront layout
const shopLayout = window.storefrontLayoutData();
shopLayout.addToCart(product, quantity);
@@ -881,7 +881,7 @@ Add proper ARIA labels and keyboard navigation:
### Reusable Partials
Create reusable components in `templates/shop/partials/`:
Create reusable components in `templates/storefront/partials/`:
**product-card.html:**
```html
@@ -945,12 +945,12 @@ Create reusable components in `templates/shop/partials/`:
```bash
# Create new page files
touch app/templates/shop/new-page.html
touch app/static/shop/js/new-page.js
touch app/templates/storefront/new-page.html
touch app/static/storefront/js/new-page.js
# Copy templates
cp template.html app/templates/shop/new-page.html
cp template.js app/static/shop/js/new-page.js
cp template.html app/templates/storefront/new-page.html
cp template.js app/static/storefront/js/new-page.js
# Update placeholders:
# - Replace [page-name] with actual name
@@ -969,7 +969,7 @@ cp template.js app/static/shop/js/new-page.js
- **Logo**: Available in both light and dark versions
- **Custom CSS**: Store-specific styles automatically injected
### Shop Layout Functions
### Storefront Layout Functions
- `addToCart(product, quantity)`: Add item to cart
- `showToast(message, type)`: Show notification
- `formatPrice(amount)`: Format as currency
@@ -991,4 +991,4 @@ await apiClient.post('/endpoint', { data });
---
This template provides a complete, theme-aware pattern for building shop pages with consistent structure, store branding, cart integration, and excellent user experience across all devices.
This template provides a complete, theme-aware pattern for building storefront pages with consistent structure, store branding, cart integration, and excellent user experience across all devices.

View File

@@ -21,7 +21,7 @@ Tailwind Standalone CLI (single binary, no npm)
├── static/admin/css/tailwind.css → tailwind.output.css (Admin)
├── static/store/css/tailwind.css → tailwind.output.css (Store)
├── static/shop/css/tailwind.css → tailwind.output.css (Shop)
├── static/storefront/css/tailwind.css → tailwind.output.css (Shop)
└── static/public/css/tailwind.css → tailwind.output.css (Platform)
```