# 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, Store 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, store defaults, and marketing pages.

---

## Phase 1: Database & Models ✅ COMPLETE

### Completed Work

| Task | File | Status |
|------|------|--------|
| Platform model | `models/database/platform.py` | ✅ |
| StorePlatform junction table | `models/database/store_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 orion > orion_backup_$(date +%Y%m%d).sql

# 2. Run migration
alembic upgrade head

# 3. Verify migration
psql -d orion -c "SELECT * FROM platforms;"
psql -d orion -c "SELECT COUNT(*) FROM store_platforms;"
psql -d orion -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 StoreContextMiddleware
from middleware import PlatformContextMiddleware

# Order matters: Platform detection must run first
app.add_middleware(StoreContextMiddleware)  # Runs second (existing)
app.add_middleware(PlatformContextMiddleware)  # Runs first (NEW)
```

### 2.3 Update StoreContextMiddleware ✅ COMPLETE

File: `middleware/store_context.py`

Changes completed:
- [x] Use `request.state.platform_clean_path` instead of `request.url.path` for path-based store detection (line 52)
- [x] Skip store detection if no platform found (platform marketing pages like /oms/pricing)
- [x] Pass platform context to store lookup for multi-platform store support

### 2.4 Fix Platform Homepage Route

File: `app/routes/platform/homepage.py`

Current state (BROKEN):
- Uses hardcoded `homepage-orion.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-orion.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/store/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: Store Dashboard ✅ COMPLETE

### 4.1 Content Pages List Updates

| Task | File | Status |
|------|------|--------|
| Source indicators (Default/Override/Custom) | `app/templates/store/content-pages.html` | ✅ Already existed |
| Override Default button | `app/templates/store/content-pages.html` | ✅ Already existed |
| Revert to Default (delete override) | `static/store/js/content-pages.js` | ✅ Already existed |
| CMS usage API endpoint | `app/api/v1/store/content_pages.py` | ✅ New |
| CMS usage progress bar | `app/templates/store/content-pages.html` | ✅ New |
| Upgrade prompt at 80% limit | `app/templates/store/content-pages.html` | ✅ New |
| Load usage in JS | `static/store/js/content-pages.js` | ✅ New |

### 4.2 Page Editor Updates

| Task | File | Status |
|------|------|--------|
| Override info banner | `app/templates/store/content-page-edit.html` | ✅ Already existed |
| View Default button | `app/templates/store/content-page-edit.html` | ✅ New |
| Default preview modal | `app/templates/store/content-page-edit.html` | ✅ New |
| Platform default API | `app/api/v1/store/content_pages.py` | ✅ New |
| Show default preview JS | `static/store/js/content-page-edit.js` | ✅ New |
| Revert button (styled) | `app/templates/store/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/storefront/{code}/` → Store 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: `rewardflow.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 Store 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 MAIN_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/` | `orion.lu/` |
| OMS | `oms` | `localhost:9999/platforms/oms/` | `omsflow.lu/` |
| Loyalty | `loyalty` | `localhost:9999/platforms/loyalty/` | `rewardflow.lu/` |

### 7.4 Middleware Detection Logic

```
Request arrives
      │
      ▼
┌─────────────────────────────────────┐
│ Production domain? (omsflow.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 Store Default vs Store 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
- [ ] Store 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: orion.omsflow.lu/about
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ Tier 1: Store Override                                      │
│ WHERE platform_id=:pid AND store_id=123 AND slug='about'    │
│ Found? → Return store's custom page                         │
└─────────────────────────────────────────────────────────────┘
                         │ Not found
                         ▼
┌─────────────────────────────────────────────────────────────┐
│ Tier 2: Store Default                                       │
│ WHERE platform_id=:pid AND store_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 orion -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, MAIN_PLATFORM_CODE
print(f'MAIN_PLATFORM_CODE: {MAIN_PLATFORM_CODE}')
# Expected: main
"
```

---

## Files Created/Modified in Phase 1

### New Files (17)
```
models/database/platform.py
models/database/store_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/store.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 stores will be linked to OMS via `store_platforms`
- Migration is reversible (see downgrade function in migration file)
