refactor: migrate templates and static files to self-contained modules
Templates Migration: - Migrate admin templates to modules (tenancy, billing, monitoring, marketplace, etc.) - Migrate vendor templates to modules (tenancy, billing, orders, messaging, etc.) - Migrate storefront templates to modules (catalog, customers, orders, cart, checkout, cms) - Migrate public templates to modules (billing, marketplace, cms) - Keep shared templates in app/templates/ (base.html, errors/, partials/, macros/) - Migrate letzshop partials to marketplace module Static Files Migration: - Migrate admin JS to modules: tenancy (23 files), core (5 files), monitoring (1 file) - Migrate vendor JS to modules: tenancy (4 files), core (2 files) - Migrate shared JS: vendor-selector.js to core, media-picker.js to cms - Migrate storefront JS: storefront-layout.js to core - Keep framework JS in static/ (api-client, utils, money, icons, log-config, lib/) - Update all template references to use module_static paths Naming Consistency: - Rename static/platform/ to static/public/ - Rename app/templates/platform/ to app/templates/public/ - Update all extends and static references Documentation: - Update module-system.md with shared templates documentation - Update frontend-structure.md with new module JS organization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,435 @@
|
||||
# Multi-Platform CMS Architecture - Implementation Plan
|
||||
|
||||
> **Status:** All Phases Complete (1-7)
|
||||
> **Last Updated:** 2026-01-19
|
||||
> **Commits:**
|
||||
> - `408019d` (Phase 1: Database & Models)
|
||||
> - `9680026` (Phases 2-5: Migration, Admin, Docs, Vendor Dashboard)
|
||||
> - `32bcbc8` (Phase 6: Loyalty Platform Setup)
|
||||
> - `a2407ae` (Phase 7: Platform URL Routing Strategy)
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Transform the single-platform OMS into a multi-platform system supporting independent business offerings (OMS, Loyalty, Site Builder), each with its own CMS, vendor defaults, and marketing pages.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Database & Models ✅ COMPLETE
|
||||
|
||||
### Completed Work
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Platform model | `models/database/platform.py` | ✅ |
|
||||
| VendorPlatform junction table | `models/database/vendor_platform.py` | ✅ |
|
||||
| SubscriptionTier updates | `models/database/subscription.py` | ✅ |
|
||||
| ContentPage updates | `models/database/content_page.py` | ✅ |
|
||||
| CMS feature codes | `models/database/feature.py` | ✅ |
|
||||
| Model exports | `models/database/__init__.py` | ✅ |
|
||||
| PlatformContextMiddleware | `middleware/platform_context.py` | ✅ |
|
||||
| Middleware exports | `middleware/__init__.py` | ✅ |
|
||||
| ContentPageService updates | `app/services/content_page_service.py` | ✅ |
|
||||
| Alembic migration | `alembic/versions/z4e5f6a7b8c9_...py` | ✅ |
|
||||
| Platform folder structure | `app/platforms/` | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: OMS Migration & Integration ✅ COMPLETE
|
||||
|
||||
### 2.1 Run Database Migration
|
||||
|
||||
```bash
|
||||
# 1. Backup database first
|
||||
pg_dump wizamart > wizamart_backup_$(date +%Y%m%d).sql
|
||||
|
||||
# 2. Run migration
|
||||
alembic upgrade head
|
||||
|
||||
# 3. Verify migration
|
||||
psql -d wizamart -c "SELECT * FROM platforms;"
|
||||
psql -d wizamart -c "SELECT COUNT(*) FROM vendor_platforms;"
|
||||
psql -d wizamart -c "SELECT platform_id, is_platform_page, COUNT(*) FROM content_pages GROUP BY 1, 2;"
|
||||
```
|
||||
|
||||
### 2.2 Register PlatformContextMiddleware in main.py
|
||||
|
||||
```python
|
||||
# In main.py, add BEFORE VendorContextMiddleware
|
||||
from middleware import PlatformContextMiddleware
|
||||
|
||||
# Order matters: Platform detection must run first
|
||||
app.add_middleware(VendorContextMiddleware) # Runs second (existing)
|
||||
app.add_middleware(PlatformContextMiddleware) # Runs first (NEW)
|
||||
```
|
||||
|
||||
### 2.3 Update VendorContextMiddleware ✅ COMPLETE
|
||||
|
||||
File: `middleware/vendor_context.py`
|
||||
|
||||
Changes completed:
|
||||
- [x] Use `request.state.platform_clean_path` instead of `request.url.path` for path-based vendor detection (line 52)
|
||||
- [x] Skip vendor detection if no platform found (platform marketing pages like /oms/pricing)
|
||||
- [x] Pass platform context to vendor lookup for multi-platform vendor support
|
||||
|
||||
### 2.4 Fix Platform Homepage Route
|
||||
|
||||
File: `app/routes/platform/homepage.py`
|
||||
|
||||
Current state (BROKEN):
|
||||
- Uses hardcoded `homepage-wizamart.html` template
|
||||
- Admin CMS changes are saved but ignored by route
|
||||
|
||||
Fix required:
|
||||
```python
|
||||
# Get platform from middleware
|
||||
platform = request.state.platform
|
||||
|
||||
# Query CMS for platform homepage
|
||||
page = content_page_service.get_platform_page(
|
||||
db,
|
||||
platform_id=platform.id,
|
||||
slug="home"
|
||||
)
|
||||
|
||||
if page:
|
||||
# Render with selected template
|
||||
return templates.TemplateResponse(
|
||||
f"platform/homepage-{page.template}.html",
|
||||
{"request": request, "page": page}
|
||||
)
|
||||
else:
|
||||
# Fallback to hardcoded (temporary)
|
||||
return templates.TemplateResponse("platform/homepage-wizamart.html", {...})
|
||||
```
|
||||
|
||||
### 2.5 Update Content Page Routes
|
||||
|
||||
Files to update:
|
||||
- [ ] `app/routes/platform/content_pages.py` - Add platform_id from request.state.platform
|
||||
- [ ] `app/routes/vendor/content_pages.py` - Add platform_id to queries
|
||||
- [ ] `app/routes/admin/content_pages.py` - Add platform filtering
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Admin Interface ✅ COMPLETE
|
||||
|
||||
### 3.1 Platform Management UI
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Platform list page route | `app/routes/admin_pages.py` | ✅ |
|
||||
| Platform detail/edit routes | `app/routes/admin_pages.py` | ✅ |
|
||||
| Platform API endpoints | `app/api/v1/admin/platforms.py` | ✅ |
|
||||
| Register API router | `app/api/v1/admin/__init__.py` | ✅ |
|
||||
| Platforms template | `app/templates/admin/platforms.html` | ✅ |
|
||||
| Platforms JS component | `static/admin/js/platforms.js` | ✅ |
|
||||
| Sidebar menu item | `app/templates/admin/partials/sidebar.html` | ✅ |
|
||||
|
||||
### 3.2 Update Content Pages Admin
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Platform dropdown filter | `app/templates/admin/content-pages.html` | ✅ |
|
||||
| Four-tab tier view | `app/templates/admin/content-pages.html` | ✅ |
|
||||
| Tier badges (Blue/Teal/Purple) | `static/admin/js/content-pages.js` | ✅ |
|
||||
| Platform filter in JS | `static/admin/js/content-pages.js` | ✅ |
|
||||
| API schema with platform fields | `app/api/v1/admin/content_pages.py` | ✅ |
|
||||
| Model to_dict with platform_name | `models/database/content_page.py` | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: Vendor Dashboard ✅ COMPLETE
|
||||
|
||||
### 4.1 Content Pages List Updates
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Source indicators (Default/Override/Custom) | `app/templates/vendor/content-pages.html` | ✅ Already existed |
|
||||
| Override Default button | `app/templates/vendor/content-pages.html` | ✅ Already existed |
|
||||
| Revert to Default (delete override) | `static/vendor/js/content-pages.js` | ✅ Already existed |
|
||||
| CMS usage API endpoint | `app/api/v1/vendor/content_pages.py` | ✅ New |
|
||||
| CMS usage progress bar | `app/templates/vendor/content-pages.html` | ✅ New |
|
||||
| Upgrade prompt at 80% limit | `app/templates/vendor/content-pages.html` | ✅ New |
|
||||
| Load usage in JS | `static/vendor/js/content-pages.js` | ✅ New |
|
||||
|
||||
### 4.2 Page Editor Updates
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Override info banner | `app/templates/vendor/content-page-edit.html` | ✅ Already existed |
|
||||
| View Default button | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
| Default preview modal | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
| Platform default API | `app/api/v1/vendor/content_pages.py` | ✅ New |
|
||||
| Show default preview JS | `static/vendor/js/content-page-edit.js` | ✅ New |
|
||||
| Revert button (styled) | `app/templates/vendor/content-page-edit.html` | ✅ New |
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Routes & Templates ✅ COMPLETE
|
||||
|
||||
### 5.1 Platform-Prefixed Routes (Development)
|
||||
|
||||
Register in `main.py`:
|
||||
```python
|
||||
# Development mode: path-based routing
|
||||
if settings.environment == "development":
|
||||
app.mount("/oms", oms_router)
|
||||
app.mount("/loyalty", loyalty_router)
|
||||
```
|
||||
|
||||
### 5.2 Update Shop Routes ✅ COMPLETE
|
||||
|
||||
- [x] Add platform context to shop routes (`shop_pages.py` line 117)
|
||||
- [x] Use `request.state.platform` for template selection
|
||||
- [x] Pass platform to content page lookups (`platform_id` used in CMS queries)
|
||||
|
||||
### 5.3 Test All URL Patterns ✅ COMPLETE
|
||||
|
||||
Development (using /platforms/ prefix):
|
||||
- [x] `localhost:9999/platforms/oms/` → OMS homepage
|
||||
- [x] `localhost:9999/platforms/oms/pricing` → OMS pricing page
|
||||
- [x] `localhost:9999/platforms/oms/vendors/{code}/` → Vendor storefront
|
||||
- [x] `localhost:9999/platforms/loyalty/` → Loyalty homepage
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Loyalty Platform Setup ✅ COMPLETE
|
||||
|
||||
### 6.1 Database Setup ✅
|
||||
|
||||
Migration: `alembic/versions/z5f6g7h8i9j0_add_loyalty_platform.py`
|
||||
|
||||
Inserts Loyalty platform with:
|
||||
- code: `loyalty`
|
||||
- name: `Loyalty+`
|
||||
- domain: `loyalty.lu`
|
||||
- path_prefix: `loyalty`
|
||||
- theme_config: purple color scheme
|
||||
|
||||
### 6.2 Platform Marketing Pages ✅
|
||||
|
||||
| Page | Slug | Status |
|
||||
|------|------|--------|
|
||||
| Homepage | `home` | ✅ |
|
||||
| Pricing | `pricing` | ✅ |
|
||||
| Features | `features` | ✅ |
|
||||
| How It Works | `how-it-works` | ✅ |
|
||||
|
||||
### 6.3 Vendor Default Pages ✅
|
||||
|
||||
| Page | Slug | Status |
|
||||
|------|------|--------|
|
||||
| About | `about` | ✅ |
|
||||
| Rewards Catalog | `rewards-catalog` | ✅ |
|
||||
| Terms | `terms` | ✅ |
|
||||
| Privacy | `privacy` | ✅ |
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: Platform URL Routing Strategy ✅ COMPLETE
|
||||
|
||||
### 7.1 URL Structure Changes
|
||||
|
||||
**Previous approach (DEPRECATED):**
|
||||
- Development: `/oms/`, `/loyalty/` (first path segment = platform)
|
||||
- Ambiguity: `/faq` could be platform or page
|
||||
|
||||
**New approach:**
|
||||
- Development: `/platforms/oms/`, `/platforms/loyalty/` (explicit prefix)
|
||||
- Main marketing site: `/` (no prefix) → `main` platform
|
||||
- Clear separation: `/faq` = main site, `/platforms/oms/faq` = OMS
|
||||
|
||||
### 7.2 Implementation Details
|
||||
|
||||
| Task | File | Status |
|
||||
|------|------|--------|
|
||||
| Update middleware URL detection | `middleware/platform_context.py` | ✅ |
|
||||
| Change DEFAULT_PLATFORM_CODE | `middleware/platform_context.py` | ✅ |
|
||||
| Remove hardcoded /oms, /loyalty routes | `main.py` | ✅ |
|
||||
| Update platform_pages.py homepage | `app/routes/platform_pages.py` | ✅ |
|
||||
| Add 'main' platform migration | `alembic/versions/z6g7h8i9j0k1_...py` | ✅ |
|
||||
|
||||
### 7.3 URL Routing Summary
|
||||
|
||||
| Platform | Code | Dev URL | Prod URL |
|
||||
|----------|------|---------|----------|
|
||||
| Main Marketing | `main` | `localhost:9999/` | `wizamart.lu/` |
|
||||
| OMS | `oms` | `localhost:9999/platforms/oms/` | `oms.lu/` |
|
||||
| Loyalty | `loyalty` | `localhost:9999/platforms/loyalty/` | `loyalty.lu/` |
|
||||
|
||||
### 7.4 Middleware Detection Logic
|
||||
|
||||
```
|
||||
Request arrives
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Production domain? (oms.lu, etc.) │
|
||||
└─────────────────────────────────────┘
|
||||
│ YES → Route to that platform
|
||||
│
|
||||
▼ NO (localhost)
|
||||
┌─────────────────────────────────────┐
|
||||
│ Path starts with /platforms/{code}? │
|
||||
└─────────────────────────────────────┘
|
||||
│ YES → Strip prefix, route to platform
|
||||
│ /platforms/oms/pricing → /pricing
|
||||
│
|
||||
▼ NO
|
||||
┌─────────────────────────────────────┐
|
||||
│ Use 'main' platform (DEFAULT) │
|
||||
│ /faq → Main site FAQ page │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Documentation Requirements ✅ COMPLETE
|
||||
|
||||
### Architecture Documentation ✅ COMPLETE
|
||||
|
||||
Updated documentation for Phase 7:
|
||||
- [x] `docs/architecture/url-routing/overview.md` - Multi-platform URL routing section
|
||||
- [x] `docs/architecture/multi-platform-cms.md` - Request flow with path rewriting
|
||||
- [x] `docs/architecture/middleware.md` - PlatformContextMiddleware documentation
|
||||
- [x] Three-tier content hierarchy explanation
|
||||
- [x] Platform vs Vendor Default vs Vendor Override
|
||||
- [x] Database schema diagrams
|
||||
- [x] Request flow diagrams
|
||||
- [x] API endpoints reference
|
||||
- [x] Key files reference
|
||||
- [x] Adding new platform guide with URL summary
|
||||
|
||||
### API Documentation
|
||||
|
||||
OpenAPI specs auto-generated from FastAPI:
|
||||
- [x] Platform endpoints (`/api/v1/admin/platforms`)
|
||||
- [x] Content page endpoints with platform fields
|
||||
- [ ] Vendor platform membership endpoints (future)
|
||||
|
||||
### Developer Guide
|
||||
|
||||
Included in `docs/architecture/multi-platform-cms.md`:
|
||||
- [x] Step-by-step platform creation
|
||||
- [x] Required database records
|
||||
- [x] Key files reference
|
||||
- [x] Platform URL summary table
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Three-Tier Content Resolution
|
||||
|
||||
```
|
||||
Customer visits: oms.lu/vendors/wizamart/about
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Tier 1: Vendor Override │
|
||||
│ WHERE platform_id=1 AND vendor_id=123 AND slug='about' │
|
||||
│ Found? → Return vendor's custom page │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ Not found
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Tier 2: Vendor Default │
|
||||
│ WHERE platform_id=1 AND vendor_id IS NULL │
|
||||
│ AND is_platform_page=FALSE AND slug='about' │
|
||||
│ Found? → Return platform default │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
│ Not found
|
||||
▼
|
||||
Return 404
|
||||
```
|
||||
|
||||
### CMS Tier Limits
|
||||
|
||||
| Tier | Total Pages | Custom Pages |
|
||||
|------|-------------|--------------|
|
||||
| Essential | 3 | 0 |
|
||||
| Professional | 10 | 5 |
|
||||
| Business | 30 | 20 |
|
||||
| Enterprise | Unlimited | Unlimited |
|
||||
|
||||
### Platform Marketing Page Slugs
|
||||
|
||||
`home`, `platform_homepage`, `pricing`, `about`, `contact`, `faq`, `terms`, `privacy`, `features`, `integrations`
|
||||
|
||||
---
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
All phases are complete. Use these commands to verify:
|
||||
|
||||
```bash
|
||||
# 1. Check platforms in database
|
||||
psql -d wizamart -c "SELECT code, name, domain FROM platforms;"
|
||||
# Expected: main, oms, loyalty
|
||||
|
||||
# 2. Test main marketing site
|
||||
curl -s localhost:9999/ | grep -o "<title>.*</title>"
|
||||
# Expected: Main marketing site title
|
||||
|
||||
# 3. Test OMS platform
|
||||
curl -s localhost:9999/platforms/oms/ | grep -o "<title>.*</title>"
|
||||
# Expected: OMS platform title
|
||||
|
||||
# 4. Test Loyalty platform
|
||||
curl -s localhost:9999/platforms/loyalty/ | grep -o "<title>.*</title>"
|
||||
# Expected: Loyalty platform title
|
||||
|
||||
# 5. Verify middleware detection
|
||||
python -c "
|
||||
from middleware.platform_context import PlatformContextMiddleware, DEFAULT_PLATFORM_CODE
|
||||
print(f'DEFAULT_PLATFORM_CODE: {DEFAULT_PLATFORM_CODE}')
|
||||
# Expected: main
|
||||
"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files Created/Modified in Phase 1
|
||||
|
||||
### New Files (17)
|
||||
```
|
||||
models/database/platform.py
|
||||
models/database/vendor_platform.py
|
||||
middleware/platform_context.py
|
||||
alembic/versions/z4e5f6a7b8c9_add_multi_platform_support.py
|
||||
app/platforms/__init__.py
|
||||
app/platforms/oms/__init__.py
|
||||
app/platforms/oms/config.py
|
||||
app/platforms/oms/routes/__init__.py
|
||||
app/platforms/oms/templates/__init__.py
|
||||
app/platforms/loyalty/__init__.py
|
||||
app/platforms/loyalty/config.py
|
||||
app/platforms/loyalty/routes/__init__.py
|
||||
app/platforms/loyalty/templates/__init__.py
|
||||
app/platforms/shared/__init__.py
|
||||
app/platforms/shared/base_platform.py
|
||||
app/platforms/shared/routes/__init__.py
|
||||
app/platforms/shared/templates/__init__.py
|
||||
```
|
||||
|
||||
### Modified Files (7)
|
||||
```
|
||||
models/database/__init__.py
|
||||
models/database/content_page.py
|
||||
models/database/subscription.py
|
||||
models/database/feature.py
|
||||
models/database/vendor.py
|
||||
middleware/__init__.py
|
||||
app/services/content_page_service.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Git tag `v1.0.0-pre-multiplatform` was created before starting
|
||||
- All existing `content_pages` will be backfilled to OMS platform
|
||||
- All existing vendors will be linked to OMS via `vendor_platforms`
|
||||
- Migration is reversible (see downgrade function in migration file)
|
||||
Reference in New Issue
Block a user