refactor: rename Wizamart to Orion across entire codebase

Replace all ~1,086 occurrences of Wizamart/wizamart/WIZAMART/WizaMart
with Orion/orion/ORION across 184 files. This includes database
identifiers, email addresses, domain references, R2 bucket names,
DNS prefixes, encryption salt, Celery app name, config defaults,
Docker configs, CI configs, documentation, seed data, and templates.

Renames homepage-wizamart.html template to homepage-orion.html.
Fixes duplicate file_pattern key in api.yaml architecture rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 16:46:56 +01:00
parent 34ee7bb7ad
commit e9253fbd84
184 changed files with 1227 additions and 1228 deletions

View File

@@ -99,7 +99,7 @@ Developers must remember:
### Broken Features
**Current Issue:** CMS pages not loading at `/stores/wizamart/about`
**Current Issue:** CMS pages not loading at `/stores/orion/about`
**Root Cause:**
- CMS API exists at `/api/v1/shop/content-pages/{slug}`

View File

@@ -21,9 +21,9 @@ Updated `StoreContextMiddleware` to support shop API routes:
- Shop API now receives store context from the page that made the API call
**How it works:**
1. Browser JavaScript on `/stores/wizamart/shop/products` calls `/api/v1/shop/products`
2. Browser automatically sends `Referer: http://localhost:8000/stores/wizamart/shop/products`
3. Middleware extracts `wizamart` from Referer path
1. Browser JavaScript on `/stores/orion/shop/products` calls `/api/v1/shop/products`
2. Browser automatically sends `Referer: http://localhost:8000/stores/orion/shop/products`
3. Middleware extracts `orion` from Referer path
4. Queries database to get Store object
5. Sets `request.state.store` for the API endpoint

View File

@@ -286,7 +286,7 @@ def get_products(
"sub": "user_id",
"username": "john.doe",
"store_id": 123, Store context
"store_code": "WIZAMART", Store code
"store_code": "ORION", Store code
"store_role": "Owner" Store role
}
```

View File

@@ -6,7 +6,7 @@ This document defines the harmonized architecture for all background tasks in th
## Task Queue Infrastructure
Wizamart uses **Celery with Redis** for production-grade background task processing:
Orion uses **Celery with Redis** for production-grade background task processing:
| Component | Purpose | Port |
|-----------|---------|------|

View File

@@ -1,6 +1,6 @@
# Capacity Planning & Infrastructure Sizing
This document provides comprehensive capacity planning guidelines for the Wizamart platform, including resource requirements, scaling thresholds, and monitoring recommendations.
This document provides comprehensive capacity planning guidelines for the Orion platform, including resource requirements, scaling thresholds, and monitoring recommendations.
> **Related:** [Pricing Strategy](../marketing/pricing.md) for tier definitions and limits

View File

@@ -175,16 +175,16 @@ Customer → DNS → Server → Nginx → FastAPI
FastAPI Middleware:
host = "store1.platform.com"
Step 1: Custom domain? NO (ends with .platform.com)
Step 2: Subdomain? YES
Extract "store1"
Query: SELECT * FROM stores
Query: SELECT * FROM stores
WHERE subdomain = 'store1'
Result: Store 1
request.state.store = Store 1
Route → Render Store 1's shop
```
@@ -195,18 +195,18 @@ Customer → localhost:8000/store/store1/
FastAPI Middleware:
host = "localhost:8000"
path = "/store/store1/"
Step 1: Custom domain? NO (localhost)
Step 2: Subdomain? NO (localhost has no subdomain)
Step 3: Path-based? YES
Extract "store1" from path
Query: SELECT * FROM stores
Query: SELECT * FROM stores
WHERE subdomain = 'store1'
Result: Store 1
request.state.store = Store 1
request.state.clean_path = "/" (strip /store/store1)
Route → Render Store 1's shop
```
@@ -402,7 +402,7 @@ Value: 123.45.67.89
TTL: 3600
Type: TXT
Name: _wizamart-verify
Name: _orion-verify
Value: abc123xyz (verification token from your platform)
TTL: 3600
```

View File

@@ -237,7 +237,7 @@
│ Exception Handler │
│ app/exceptions/handler.py │
│ │
│ @app.exception_handler(WizamartException) │
│ @app.exception_handler(OrionException) │
│ async def custom_exception_handler(...): │
│ return JSONResponse( │
│ status_code=exc.status_code, │
@@ -331,7 +331,7 @@ Step 2: Get Instructions
┌────────────────────────────────────┐
│ System returns instructions: │
│ "Add TXT record: │
│ _wizamart-verify.myshop.com │
│ _orion-verify.myshop.com │
│ Value: abc123..." │
└────────────────────────────────────┘
@@ -343,7 +343,7 @@ Step 3: Store Adds DNS Record
┌────────────────────────────────────┐
│ DNS Provider (GoDaddy/etc) │
│ _wizamart-verify.myshop.com TXT │
│ _orion-verify.myshop.com TXT │
│ "abc123..." │
└────────────────────────────────────┘

View File

@@ -10,7 +10,7 @@ The application serves multiple frontends from a single codebase:
|----------|-------------|--------------|
| **ADMIN** | Platform administration | `/admin/*`, `/api/v1/admin/*`, `admin.oms.lu/*` |
| **STORE** | Store dashboard | `/store/*`, `/api/v1/store/*` |
| **STOREFRONT** | Customer-facing shop | `/storefront/*`, `/stores/*`, `wizamart.oms.lu/*` |
| **STOREFRONT** | Customer-facing shop | `/storefront/*`, `/stores/*`, `orion.oms.lu/*` |
| **PLATFORM** | Marketing pages | `/`, `/pricing`, `/about` |
The `FrontendDetector` class provides centralized, consistent detection of which frontend a request targets.
@@ -70,7 +70,7 @@ The `FrontendDetector` uses the following priority order:
- /store/* or /api/v1/store/* → STORE
- /storefront/*, /shop/*, /stores/* → STOREFRONT
- /api/v1/platform/* → PLATFORM
3. Store subdomain (wizamart.oms.lu) → STOREFRONT
3. Store subdomain (orion.oms.lu) → STOREFRONT
4. Store context set by middleware → STOREFRONT
5. Default → PLATFORM
```
@@ -133,7 +133,7 @@ from app.modules.enums import FrontendType
# Full detection
frontend_type = FrontendDetector.detect(
host="wizamart.oms.lu",
host="orion.oms.lu",
path="/products",
has_store_context=True
)
@@ -160,7 +160,7 @@ if FrontendDetector.is_storefront(host, path, has_store_context=True):
| Store dashboard | localhost | /store/settings | STORE |
| Store API | localhost | /api/v1/store/products | STORE |
| Storefront | localhost | /storefront/products | STOREFRONT |
| Storefront (path-based) | localhost | /stores/wizamart/products | STOREFRONT |
| Storefront (path-based) | localhost | /stores/orion/products | STOREFRONT |
| Marketing | localhost | /pricing | PLATFORM |
### Production Mode (domains)
@@ -168,7 +168,7 @@ if FrontendDetector.is_storefront(host, path, has_store_context=True):
| Request | Host | Path | Frontend |
|---------|------|------|----------|
| Admin subdomain | admin.oms.lu | /dashboard | ADMIN |
| Store subdomain | wizamart.oms.lu | /products | STOREFRONT |
| Store subdomain | orion.oms.lu | /products | STOREFRONT |
| Custom domain | mybakery.lu | /products | STOREFRONT |
| Platform root | oms.lu | /pricing | PLATFORM |

View File

@@ -1,6 +1,6 @@
# Language & Internationalization (i18n) Architecture
This document defines **strict rules** for implementing language support across the Wizamart platform.
This document defines **strict rules** for implementing language support across the Orion platform.
> **IMPORTANT:** These rules are mandatory. Violations will cause runtime errors, inconsistent UX, or security issues.
@@ -49,7 +49,7 @@ language = "lux" # ❌ Use "lb"
Language is resolved in this order (highest to lowest priority):
1. **URL parameter** (`?lang=fr`)
2. **Cookie** (`wizamart_language`)
2. **Cookie** (`orion_language`)
3. **User preference** (database: `preferred_language`)
4. **Store default** (database: `storefront_language` or `dashboard_language`)
5. **Accept-Language header** (browser)
@@ -270,7 +270,7 @@ async def set_language(request: LanguageSetRequest, response: Response):
raise HTTPException(status_code=400, detail="Unsupported language")
response.set_cookie(
key="wizamart_language",
key="orion_language",
value=request.language,
max_age=365 * 24 * 60 * 60, # 1 year
httponly=True,

View File

@@ -2,7 +2,7 @@
## Executive Summary
This document defines the complete architecture for integrating Wizamart with multiple external marketplaces (Letzshop, Amazon, eBay) and digital product suppliers (CodesWholesale). The integration is **bidirectional**, supporting both inbound flows (products, orders) and outbound flows (inventory sync, fulfillment status).
This document defines the complete architecture for integrating Orion with multiple external marketplaces (Letzshop, Amazon, eBay) and digital product suppliers (CodesWholesale). The integration is **bidirectional**, supporting both inbound flows (products, orders) and outbound flows (inventory sync, fulfillment status).
**Key Capabilities:**
@@ -26,7 +26,7 @@ graph TB
AZ[Amazon<br/>API]
EB[eBay<br/>API]
CW[CodesWholesale<br/>Digital Supplier API]
WS[Store Storefront<br/>Wizamart Shop]
WS[Store Storefront<br/>Orion Shop]
end
subgraph "Integration Layer"
@@ -42,7 +42,7 @@ graph TB
end
end
subgraph "Wizamart Core"
subgraph "Orion Core"
MP[Marketplace Products]
P[Store Products]
O[Unified Orders]
@@ -263,7 +263,7 @@ graph TB
```python
class OrderChannel(str, Enum):
"""Order source channel."""
STOREFRONT = "storefront" # Store's own Wizamart shop
STOREFRONT = "storefront" # Store's own Orion shop
LETZSHOP = "letzshop"
AMAZON = "amazon"
EBAY = "ebay"
@@ -1325,7 +1325,7 @@ def map_codeswholesale_product(cw_product: dict) -> dict:
### Order Status Mapping
| Wizamart Status | Letzshop | Amazon | eBay |
| Orion Status | Letzshop | Amazon | eBay |
|-----------------|----------|--------|------|
| PENDING | PENDING | Pending | - |
| CONFIRMED | PAID | Unshipped | Paid |

View File

@@ -1,6 +1,6 @@
# Menu Management Architecture
The Wizamart platform provides a **module-driven menu system** where each module defines its own menu items. The `MenuDiscoveryService` aggregates menus from all enabled modules, applying visibility configuration and permission filtering.
The Orion platform provides a **module-driven menu system** where each module defines its own menu items. The `MenuDiscoveryService` aggregates menus from all enabled modules, applying visibility configuration and permission filtering.
## Overview

View File

@@ -2,7 +2,7 @@
## Overview
The Wizamart platform implements a hierarchical multi-tenant architecture where **Merchants** are the primary business entities and **Stores** are storefronts/brands that operate under merchants.
The Orion platform implements a hierarchical multi-tenant architecture where **Merchants** are the primary business entities and **Stores** are storefronts/brands that operate under merchants.
```
Merchant (Business Entity)

View File

@@ -103,11 +103,11 @@ INFO Response: 200 for GET /admin/dashboard (0.143s)
**Example**:
```
Request: https://wizamart.platform.com/shop/products
Request: https://orion.platform.com/shop/products
Middleware detects: store_code = "wizamart"
Middleware detects: store_code = "orion"
Queries database: SELECT * FROM stores WHERE code = 'wizamart'
Queries database: SELECT * FROM stores WHERE code = 'orion'
Injects: request.state.store = <Store object>
request.state.store_id = 1
@@ -141,7 +141,7 @@ Injects: request.state.store = <Store object>
- /store/* or /api/v1/store/* STORE
- /storefront/*, /shop/*, /stores/* STOREFRONT
- /api/v1/platform/* PLATFORM
3. Store subdomain (wizamart.oms.lu) STOREFRONT
3. Store subdomain (orion.oms.lu) STOREFRONT
4. Store context set by middleware STOREFRONT
5. Default PLATFORM
```
@@ -165,8 +165,8 @@ Injects: request.state.store = <Store object>
{
"primary_color": "#3B82F6",
"secondary_color": "#10B981",
"logo_url": "/static/stores/wizamart/logo.png",
"favicon_url": "/static/stores/wizamart/favicon.ico",
"logo_url": "/static/stores/orion/logo.png",
"favicon_url": "/static/stores/orion/favicon.ico",
"custom_css": "/* store-specific styles */"
}
```
@@ -376,7 +376,7 @@ async def get_products(request: Request):
### Example: Shop Product Page Request
**URL**: `https://wizamart.myplatform.com/shop/products`
**URL**: `https://orion.myplatform.com/shop/products`
**Middleware Processing**:
@@ -386,9 +386,9 @@ async def get_products(request: Request):
↓ Logs: "Request: GET /shop/products from 192.168.1.100"
2. StoreContextMiddleware
↓ Detects subdomain: "wizamart"
↓ Queries DB: store = get_store_by_code("wizamart")
↓ Sets: request.state.store = <Store: Wizamart>
↓ Detects subdomain: "orion"
↓ Queries DB: store = get_store_by_code("orion")
↓ Sets: request.state.store = <Store: Orion>
↓ Sets: request.state.store_id = 1
↓ Sets: request.state.clean_path = "/shop/products"
@@ -496,13 +496,13 @@ from middleware.store_context import StoreContextManager
def test_store_detection_subdomain():
# Mock request
request = create_mock_request(host="wizamart.platform.com")
request = create_mock_request(host="orion.platform.com")
# Test detection
manager = StoreContextManager()
store = manager.detect_store_from_subdomain(request)
assert store.code == "wizamart"
assert store.code == "orion"
```
### Integration Testing
@@ -513,11 +513,11 @@ Test the full middleware stack:
def test_shop_request_flow(client):
response = client.get(
"/shop/products",
headers={"Host": "wizamart.platform.com"}
headers={"Host": "orion.platform.com"}
)
assert response.status_code == 200
assert "Wizamart" in response.text
assert "Orion" in response.text
```
**See**: [Testing Guide](../testing/testing-guide.md)

View File

@@ -1,6 +1,6 @@
# Module System Architecture
The Wizamart platform uses a **plug-and-play modular architecture** where modules are fully self-contained and automatically discovered. Simply create a module directory with the required structure, and the framework handles registration, routing, and resource loading automatically.
The Orion platform uses a **plug-and-play modular architecture** where modules are fully self-contained and automatically discovered. Simply create a module directory with the required structure, and the framework handles registration, routing, and resource loading automatically.
## Key Features
@@ -1029,11 +1029,11 @@ __all__ = ["process_import", "export_products"]
### Exceptions
Module-specific exceptions inherit from `WizamartException`.
Module-specific exceptions inherit from `OrionException`.
| Location | Base Class | Usage |
|----------|------------|-------|
| `exceptions.py` | `WizamartException` | Domain errors |
| `exceptions.py` | `OrionException` | Domain errors |
**Structure:**
```
@@ -1044,9 +1044,9 @@ app/modules/{module}/
**Example:**
```python
# app/modules/orders/exceptions.py
from app.exceptions import WizamartException
from app.exceptions import OrionException
class OrderException(WizamartException):
class OrderException(OrionException):
"""Base exception for orders module."""
pass

View File

@@ -2,7 +2,7 @@
## Overview
The Multi-Platform CMS enables Wizamart to serve multiple business offerings (OMS, Loyalty, Site Builder) from a single codebase, each with its own marketing site and store ecosystem.
The Multi-Platform CMS enables Orion to serve multiple business offerings (OMS, Loyalty, Site Builder) from a single codebase, each with its own marketing site and store ecosystem.
## Three-Tier Content Hierarchy
@@ -71,7 +71,7 @@ CREATE TABLE platforms (
code VARCHAR(50) UNIQUE NOT NULL, -- 'oms', 'loyalty', 'sitebuilder'
name VARCHAR(100) NOT NULL, -- 'Order Management System'
description TEXT,
domain VARCHAR(255), -- 'oms.wizamart.lu'
domain VARCHAR(255), -- 'oms.orion.lu'
path_prefix VARCHAR(50), -- '/oms'
logo VARCHAR(255),
logo_dark VARCHAR(255),
@@ -122,7 +122,7 @@ The system uses different URL patterns for development vs production:
- Platform sites: `localhost:9999/platforms/{code}/` → specific platform
**Production (custom domains):**
- Main marketing site: `wizamart.lu/``main` platform
- Main marketing site: `orion.lu/``main` platform
- Platform sites: `oms.lu/`, `loyalty.lu/` → specific platform
### Request Processing
@@ -284,6 +284,6 @@ Request: GET /about
| Platform | Code | Dev URL | Prod URL |
|----------|------|---------|----------|
| Main Marketing | `main` | `localhost:9999/` | `wizamart.lu/` |
| Main Marketing | `main` | `localhost:9999/` | `orion.lu/` |
| OMS | `oms` | `localhost:9999/platforms/oms/` | `oms.lu/` |
| Loyalty | `loyalty` | `localhost:9999/platforms/loyalty/` | `loyalty.lu/` |

View File

@@ -4,7 +4,7 @@ Complete guide to the multi-tenant architecture supporting custom domains, subdo
## Overview
The Wizamart platform supports **three deployment modes** for multi-tenancy, allowing each store to have their own isolated shop while sharing the same application instance and database.
The Orion platform supports **three deployment modes** for multi-tenancy, allowing each store to have their own isolated shop while sharing the same application instance and database.
**Key Concept**: One application, multiple isolated store shops, each accessible via different URLs.
@@ -148,15 +148,15 @@ For path-based routing, clean paths are extracted:
**Path-Based Shop Routes** (Development):
```
Original: /stores/WIZAMART/shop/products
Extracted: store_code = "WIZAMART"
Original: /stores/ORION/shop/products
Extracted: store_code = "ORION"
Clean: /shop/products
```
**Store Dashboard Routes** (All environments):
```
Original: /store/WIZAMART/dashboard
Extracted: store_code = "WIZAMART"
Original: /store/ORION/dashboard
Extracted: store_code = "ORION"
Clean: /dashboard
```
@@ -197,13 +197,13 @@ CREATE TABLE store_domains (
```sql
-- Stores
INSERT INTO stores (code, name) VALUES
('wizamart', 'Wizamart Shop'),
('orion', 'Orion Shop'),
('techstore', 'Tech Store'),
('fashionhub', 'Fashion Hub');
-- Custom Domains
INSERT INTO store_domains (store_id, domain) VALUES
(1, 'wizamart.com'),
(1, 'orion.lu'),
(2, 'mytechstore.net');
```
@@ -421,16 +421,16 @@ Host: customdomain.com
**Request**:
```http
GET /shop/products HTTP/1.1
Host: wizamart.myplatform.com
Host: orion.myplatform.com
```
**Processing**:
```
1. StoreContextMiddleware
- Checks: host != "myplatform.com"
- Extracts: subdomain = "wizamart"
- Queries: stores WHERE code = "wizamart"
- Sets: request.state.store = <Store "wizamart">
- Extracts: subdomain = "orion"
- Queries: stores WHERE code = "orion"
- Sets: request.state.store = <Store "orion">
2-4. Same as Example 1
```
@@ -439,7 +439,7 @@ Host: wizamart.myplatform.com
**Request**:
```http
GET /stores/WIZAMART/shop/products HTTP/1.1
GET /stores/ORION/shop/products HTTP/1.1
Host: myplatform.com
```
@@ -447,15 +447,15 @@ Host: myplatform.com
```
1. StoreContextMiddleware
- Checks: path starts with "/store/"
- Extracts: code = "WIZAMART"
- Queries: stores WHERE code = "WIZAMART"
- Extracts: code = "ORION"
- Queries: stores WHERE code = "ORION"
- Sets: request.state.store = <Store>
- Sets: request.state.clean_path = "/shop/products"
2. FastAPI Router
- Routes registered with prefix: /stores/{store_code}/shop
- Matches: /stores/WIZAMART/shop/products
- store_code path parameter = "WIZAMART"
- Matches: /stores/ORION/shop/products
- store_code path parameter = "ORION"
3-4. Same as previous examples (Context, Theme middleware)
```
@@ -491,9 +491,9 @@ def test_shop_page_multi_tenant(client):
# Test subdomain routing
response = client.get(
"/shop/products",
headers={"Host": "wizamart.platform.com"}
headers={"Host": "orion.platform.com"}
)
assert "Wizamart" in response.text
assert "Orion" in response.text
# Test different store
response = client.get(

View File

@@ -1,6 +1,6 @@
# Observability Framework
The Wizamart platform includes a comprehensive observability framework for monitoring application health, collecting metrics, and tracking errors. This is part of the Framework Layer - infrastructure that modules depend on.
The Orion platform includes a comprehensive observability framework for monitoring application health, collecting metrics, and tracking errors. This is part of the Framework Layer - infrastructure that modules depend on.
## Overview

View File

@@ -1,10 +1,10 @@
# System Architecture
High-level overview of the Wizamart multi-tenant e-commerce platform architecture.
High-level overview of the Orion multi-tenant e-commerce platform architecture.
## Overview
Wizamart is a **multi-tenant e-commerce platform** that supports three distinct interfaces:
Orion is a **multi-tenant e-commerce platform** that supports three distinct interfaces:
- **Admin** - Platform administration and store management
- **Store** - Store dashboard for managing shops
- **Shop** - Customer-facing storefronts

View File

@@ -1,6 +1,6 @@
# Request Flow
Complete journey of a request through the Wizamart platform, from client to response.
Complete journey of a request through the Orion platform, from client to response.
## Overview
@@ -42,8 +42,8 @@ graph TB
```http
# Shop page request (subdomain mode)
GET https://wizamart.platform.com/shop/products
Host: wizamart.platform.com
GET https://orion.platform.com/shop/products
Host: orion.platform.com
# API request
GET https://platform.com/api/v1/products?store_id=1
@@ -86,13 +86,13 @@ logger.info(f"Request: GET /shop/products from 192.168.1.100")
```python
# Input
host = "wizamart.platform.com"
host = "orion.platform.com"
path = "/shop/products"
# Detection logic
if host != settings.platform_domain:
# Subdomain detected
store_code = host.split('.')[0] # "wizamart"
store_code = host.split('.')[0] # "orion"
# Query database
store = db.query(Store).filter(
@@ -107,7 +107,7 @@ if host != settings.platform_domain:
**Request State After**:
```python
request.state.store = <Store: Wizamart>
request.state.store = <Store: Orion>
request.state.store_id = 1
request.state.clean_path = "/shop/products"
```
@@ -127,10 +127,10 @@ request.state.clean_path = "/shop/products"
app.include_router(shop_pages.router, prefix="/shop")
app.include_router(shop_pages.router, prefix="/stores/{store_code}/shop")
# Request: /stores/WIZAMART/shop/products
# Request: /stores/ORION/shop/products
# Matches: Second router (/stores/{store_code}/shop)
# Route: @router.get("/products")
# store_code available as path parameter = "WIZAMART"
# store_code available as path parameter = "ORION"
```
**Note:** Previous implementations used `PathRewriteMiddleware` to rewrite paths. This has been replaced with FastAPI's native routing via double router mounting.
@@ -194,7 +194,7 @@ if hasattr(request.state, 'store_id'):
request.state.theme = {
"primary_color": "#3B82F6",
"secondary_color": "#10B981",
"logo_url": "/static/stores/wizamart/logo.png",
"logo_url": "/static/stores/orion/logo.png",
"custom_css": "..."
}
```
@@ -289,7 +289,7 @@ async def shop_products_page(
<!DOCTYPE html>
<html>
<head>
<title>Wizamart - Products</title>
<title>Orion - Products</title>
<style>
:root {
--primary-color: #3B82F6;
@@ -298,7 +298,7 @@ async def shop_products_page(
</style>
</head>
<body>
<h1>Wizamart Shop</h1>
<h1>Orion Shop</h1>
<div class="products">
<div class="product-card">
<h2>Product 1</h2>
@@ -412,7 +412,7 @@ sequenceDiagram
Logging->>Store: Pass request
Store->>DB: Query store by subdomain
DB-->>Store: Store object
Note over Store: Set store, store_id, clean_path
Note over Store: Set store, store_id, clean_path
Store->>Path: Pass request
Note over Path: Path already clean
Path->>Context: Pass request
@@ -443,14 +443,14 @@ Initial State: {}
store_id: 1,
clean_path: "/shop/products"
}
After FrontendTypeMiddleware:
{
store: <Store: Orion>,
store_id: 1,
clean_path: "/shop/products",
frontend_type: FrontendType.STOREFRONT
}
}
After ThemeContextMiddleware:
{
@@ -458,14 +458,14 @@ After FrontendTypeMiddleware:
store_id: 1,
clean_path: "/shop/products",
frontend_type: FrontendType.STOREFRONT,
theme: {
theme: {
primary_color: "#3B82F6",
secondary_color: "#10B981",
logo_url: "/static/stores/orion/logo.png",
custom_css: "..."
}
}
```
```
## Performance Metrics

View File

@@ -1,8 +1,8 @@
# Wizamart Multi-Tenant URL Routing Guide
# Orion Multi-Tenant URL Routing Guide
## Quick Answer
**How do customers access a store's storefront in Wizamart?**
**How do customers access a store's storefront in Orion?**
There are three ways depending on the deployment mode:
@@ -13,8 +13,8 @@ There are three ways depending on the deployment mode:
https://STORE_SUBDOMAIN.platform.com/storefront/products
Example:
https://acme.wizamart.com/storefront/products
https://techpro.wizamart.com/storefront/categories/electronics
https://acme.orion.lu/storefront/products
https://techpro.orion.lu/storefront/categories/electronics
```
### 2. **CUSTOM DOMAIN MODE** (Production - Premium)
@@ -39,7 +39,7 @@ http://localhost:8000/platforms/loyalty/stores/techpro/storefront/checkout
## Multi-Platform URL Routing
Wizamart supports multiple platforms (OMS, Loyalty, Site Builder), each with its own marketing site and store ecosystem.
Orion supports multiple platforms (OMS, Loyalty, Site Builder), each with its own marketing site and store ecosystem.
### Platform URL Structure
@@ -61,8 +61,8 @@ Wizamart supports multiple platforms (OMS, Loyalty, Site Builder), each with its
| URL | What it serves |
|-----|----------------|
| `wizamart.lu/` | Main marketing site homepage |
| `wizamart.lu/about` | Main marketing site about page |
| `orion.lu/` | Main marketing site homepage |
| `orion.lu/about` | Main marketing site about page |
| `oms.lu/` | OMS platform homepage |
| `oms.lu/pricing` | OMS platform pricing page |
| `oms.lu/admin/` | Admin panel for OMS platform |
@@ -138,7 +138,7 @@ Request arrives
| Platform | Code | Dev URL | Prod Domain |
|----------|------|---------|-------------|
| Main Marketing | `main` | `localhost:8000/` | `wizamart.lu` |
| Main Marketing | `main` | `localhost:8000/` | `orion.lu` |
| OMS | `oms` | `localhost:8000/platforms/oms/` | `oms.lu` |
| Loyalty | `loyalty` | `localhost:8000/platforms/loyalty/` | `loyalty.lu` |
| Site Builder | `site-builder` | `localhost:8000/platforms/site-builder/` | `sitebuilder.lu` |
@@ -155,12 +155,12 @@ Request arrives
**Example:**
- Store subdomain: `acme`
- Platform domain: `wizamart.com`
- Customer Storefront URL: `https://acme.wizamart.com/storefront/products`
- Product Detail: `https://acme.wizamart.com/storefront/products/123`
- Platform domain: `orion.lu`
- Customer Storefront URL: `https://acme.orion.lu/storefront/products`
- Product Detail: `https://acme.orion.lu/storefront/products/123`
**How It Works:**
1. Customer visits `https://acme.wizamart.com/storefront/products`
1. Customer visits `https://acme.orion.lu/storefront/products`
2. `store_context_middleware` detects subdomain `"acme"`
3. Queries: `SELECT * FROM stores WHERE subdomain = 'acme'`
4. Finds Store with ID=1 (ACME Store)
@@ -171,7 +171,7 @@ Request arrives
9. Renders template with ACME's colors, logo, and products
**Advantages:**
- Single SSL certificate for all stores (*.wizamart.com)
- Single SSL certificate for all stores (*.orion.lu)
- Easy to manage DNS (just add subdomains)
- Customers don't need to bring their own domain
@@ -199,7 +199,7 @@ id | store_id | domain | is_active | is_verified
**How It Works:**
1. Customer visits `https://store.acme-corp.com/storefront/products`
2. `store_context_middleware` detects custom domain (not *.wizamart.com, not localhost)
2. `store_context_middleware` detects custom domain (not *.orion.lu, not localhost)
3. Normalizes domain to `"store.acme-corp.com"`
4. Queries: `SELECT * FROM store_domains WHERE domain = 'store.acme-corp.com'`
5. Finds `StoreDomain` with `store_id = 1`
@@ -249,17 +249,17 @@ id | store_id | domain | is_active | is_verified
### Subdomain/Custom Domain (PRODUCTION)
```
https://acme.wizamart.com/storefront/ → Homepage
https://acme.wizamart.com/storefront/products → Product Catalog
https://acme.wizamart.com/storefront/products/123 → Product Detail
https://acme.wizamart.com/storefront/categories/electronics → Category Page
https://acme.wizamart.com/storefront/cart → Shopping Cart
https://acme.wizamart.com/storefront/checkout → Checkout
https://acme.wizamart.com/storefront/search?q=laptop → Search Results
https://acme.wizamart.com/storefront/account/login → Customer Login
https://acme.wizamart.com/storefront/account/dashboard → Account Dashboard (Auth Required)
https://acme.wizamart.com/storefront/account/orders → Order History (Auth Required)
https://acme.wizamart.com/storefront/account/profile → Profile (Auth Required)
https://acme.orion.lu/storefront/ → Homepage
https://acme.orion.lu/storefront/products → Product Catalog
https://acme.orion.lu/storefront/products/123 → Product Detail
https://acme.orion.lu/storefront/categories/electronics → Category Page
https://acme.orion.lu/storefront/cart → Shopping Cart
https://acme.orion.lu/storefront/checkout → Checkout
https://acme.orion.lu/storefront/search?q=laptop → Search Results
https://acme.orion.lu/storefront/account/login → Customer Login
https://acme.orion.lu/storefront/account/dashboard → Account Dashboard (Auth Required)
https://acme.orion.lu/storefront/account/orders → Order History (Auth Required)
https://acme.orion.lu/storefront/account/profile → Profile (Auth Required)
```
### Path-Based (DEVELOPMENT)
@@ -304,7 +304,7 @@ POST /api/v1/storefront/stores/1/products/{id}/reviews → Add product review
### Example: No Cross-Store Leakage
```python
# Customer on acme.wizamart.com tries to access TechPro's products
# Customer on acme.orion.lu tries to access TechPro's products
# They make API call to /api/v1/storefront/stores/2/products
# Backend checks:
@@ -317,14 +317,14 @@ if store.id != requested_store_id: # if 1 != 2
## Request Lifecycle: Complete Flow
### Scenario: Customer visits `https://acme.wizamart.com/storefront/products`
### Scenario: Customer visits `https://acme.orion.lu/storefront/products`
```
┌─────────────────────────────────────────────────────────────────┐
│ 1. REQUEST ARRIVES │
└─────────────────────────────────────────────────────────────────┘
method: GET
host: acme.wizamart.com
host: acme.orion.lu
path: /storefront/products
┌─────────────────────────────────────────────────────────────────┐
@@ -332,7 +332,7 @@ if store.id != requested_store_id: # if 1 != 2
└─────────────────────────────────────────────────────────────────┘
A) store_context_middleware
├─ Detects host: "acme.wizamart.com"
├─ Detects host: "acme.orion.lu"
├─ Extracts subdomain: "acme"
├─ Queries: SELECT * FROM stores WHERE subdomain = 'acme'
└─ Sets: request.state.store = Store(ACME Store)
@@ -391,7 +391,7 @@ if store.id != requested_store_id: # if 1 != 2
Each store's storefront is fully branded with their custom theme:
```python
# Theme loaded for https://acme.wizamart.com
# Theme loaded for https://acme.orion.lu
request.state.theme = {
"theme_name": "modern",
"colors": {
@@ -438,7 +438,7 @@ In Jinja2 template:
- Each store looks completely separate and branded
### 2. Store Perspective
- Stores can use a subdomain (free/standard): `acme.wizamart.com`
- Stores can use a subdomain (free/standard): `acme.orion.lu`
- Or their own custom domain (premium): `store.acme-corp.com`
- Both routes go to the exact same backend code
@@ -471,7 +471,7 @@ app.include_router(storefront_pages.router, prefix="/stores/{store_code}/storefr
**How This Works:**
1. **For Subdomain/Custom Domain Mode:**
- URL: `https://acme.wizamart.com/storefront/products`
- URL: `https://acme.orion.lu/storefront/products`
- Matches: First router with `/storefront` prefix
- Route: `@router.get("/products")` → Full path: `/storefront/products`
@@ -528,4 +528,4 @@ Set-Cookie: customer_token=eyJ...; Path=/storefront; HttpOnly; SameSite=Lax
---
Generated: January 30, 2026
Wizamart Version: Current Development
Orion Version: Current Development