Multi-Platform CMS Architecture Implementation Plan 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. --- URL/Access Pattern Matrix Production Environment ┌─────────────┬──────────┬───────────────────────────────────────────┬────────────────────────────────────────┐ │ Persona │ Platform │ URL │ Purpose │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ Super Admin │ Global │ admin.wizamart.lu/ │ Global admin dashboard │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ admin.wizamart.lu/platforms │ Manage all platforms │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ admin.wizamart.lu/platforms/oms/pages │ OMS platform marketing pages │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ admin.wizamart.lu/platforms/oms/defaults │ OMS vendor default pages │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ admin.wizamart.lu/platforms/loyalty/pages │ Loyalty platform pages │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ Vendor │ OMS │ oms.lu/vendor/{code}/login │ Vendor login │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ oms.lu/vendor/{code}/dashboard │ Vendor dashboard │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ oms.lu/vendor/{code}/content-pages │ Manage CMS pages │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ Loyalty │ loyalty.lu/vendor/{code}/login │ Loyalty vendor login │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ Customer │ OMS │ {vendor}.oms.lu/ │ Vendor storefront (subdomain) │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ {vendor}.oms.lu/shop/ │ Shop pages │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ {vendor}.oms.lu/about │ Content page (3-tier fallback) │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ {customdomain}.com/ │ Custom domain storefront │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ Public │ OMS │ oms.lu/ │ Platform homepage │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ oms.lu/pricing │ Platform pricing page │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ │ oms.lu/about │ Platform about (is_platform_page=True) │ ├─────────────┼──────────┼───────────────────────────────────────────┼────────────────────────────────────────┤ │ │ Loyalty │ loyalty.lu/ │ Loyalty platform homepage │ └─────────────┴──────────┴───────────────────────────────────────────┴────────────────────────────────────────┘ Development Environment (localhost:9999) ┌─────────────┬──────────┬────────────────────────────────────────────┬───────────────────────────┐ │ Persona │ Platform │ URL │ Purpose │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ Super Admin │ Global │ localhost:9999/admin/ │ Global admin │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/admin/platforms │ Platform management │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/admin/platforms/oms/pages │ OMS platform pages │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ Vendor │ OMS │ localhost:9999/oms/vendor/{code}/login │ OMS vendor login │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/oms/vendor/{code}/dashboard │ OMS vendor dashboard │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ Loyalty │ localhost:9999/loyalty/vendor/{code}/login │ Loyalty vendor login │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ Customer │ OMS │ localhost:9999/oms/vendors/{code}/ │ Vendor root │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/oms/vendors/{code}/shop/ │ Vendor shop │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/oms/vendors/{code}/about │ Content page │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ Loyalty │ localhost:9999/loyalty/vendors/{code}/ │ Loyalty vendor storefront │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ Public │ OMS │ localhost:9999/oms/ │ OMS platform homepage │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ │ localhost:9999/oms/pricing │ OMS pricing │ ├─────────────┼──────────┼────────────────────────────────────────────┼───────────────────────────┤ │ │ Loyalty │ localhost:9999/loyalty/ │ Loyalty platform homepage │ └─────────────┴──────────┴────────────────────────────────────────────┴───────────────────────────┘ --- Three-Tier Content Resolution Customer visits: oms.lu/vendors/wizamart/about │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Tier 1: Vendor Override │ │ SELECT * FROM content_pages │ │ WHERE platform_id = 1 AND vendor_id = 123 AND slug = 'about' │ │ │ │ Found? → Return vendor's custom page │ └─────────────────────────────────────────────────────────────┘ │ Not found ▼ ┌─────────────────────────────────────────────────────────────┐ │ Tier 2: Platform Vendor Default │ │ SELECT * FROM content_pages │ │ 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 --- Data Models New: Platform Model File: models/database/platform.py class Platform(Base): id: Integer (PK) code: String(50) unique # "oms", "loyalty", "sites" name: String(100) # "Wizamart OMS" domain: String(255) # "oms.lu" (production) path_prefix: String(50) # "oms" (for localhost:9999/oms/*) logo: String(500) theme_config: JSON is_active: Boolean default_language: String(5) supported_languages: JSON New: VendorPlatform Junction Table File: models/database/vendor_platform.py class VendorPlatform(Base): id: Integer (PK) vendor_id: FK → vendors.id platform_id: FK → platforms.id tier_id: FK → platform_subscription_tiers.id is_active: Boolean is_primary: Boolean # Vendor's primary platform custom_subdomain: String(100) settings: JSON joined_at: DateTime # Constraints UniqueConstraint(vendor_id, platform_id) Updated: SubscriptionTier Model (Extend Existing) File: models/database/subscription.py Add fields to existing model: platform_id: FK → platforms.id (nullable for global tiers, set for platform-specific) cms_pages_limit: Integer (nullable) # NULL = unlimited cms_custom_pages_limit: Integer (nullable) Update constraint: UniqueConstraint(platform_id, code) # Allow same tier code per platform Updated: ContentPage Model File: models/database/content_page.py Add fields: platform_id: FK → platforms.id (NOT NULL) is_platform_page: Boolean (default=False) # True = Platform marketing page (homepage, pricing) # False = Vendor default OR vendor override/custom Update constraint: UniqueConstraint(platform_id, vendor_id, slug) New CMS Feature Codes File: models/database/feature.py CMS_BASIC = "cms_basic" CMS_CUSTOM_PAGES = "cms_custom_pages" CMS_UNLIMITED_PAGES = "cms_unlimited_pages" CMS_TEMPLATES = "cms_templates" CMS_SEO = "cms_seo" --- New Middleware: PlatformContextMiddleware File: middleware/platform_context.py Runs BEFORE VendorContextMiddleware. Detection Priority: 1. Path-based (dev): localhost:9999/oms/* → platform_code = "oms" 2. Domain-based (prod): oms.lu → platform_code = "oms" 3. Default: localhost → platform_code = "oms" (backwards compatibility) Sets: - request.state.platform → Platform object - request.state.platform_context → Detection metadata - request.state.platform_clean_path → Path without platform prefix --- Folder Organization Platform-Specific Folders (NEW) app/ ├── platforms/ # NEW - Platform-specific code │ ├── oms/ # OMS-specific │ │ ├── routes/ # OMS-specific routes │ │ ├── templates/ # OMS templates (homepage, etc.) │ │ └── config.py # OMS configuration │ ├── loyalty/ # Loyalty-specific │ │ ├── routes/ │ │ ├── templates/ │ │ └── config.py │ └── shared/ # Shared across platforms │ └── base_platform.py ├── services/ # Shared services (extended) │ ├── content_page_service.py # Add platform_id support │ ├── feature_service.py # Extend with platform awareness │ └── subscription_service.py # Extend with platform awareness ├── templates/ │ └── platform/ # Keep existing, used by platform router └── middleware/ └── platform_context.py # NEW - Platform detection Shared vs Platform-Specific ┌────────────────────┬─────────────────────────────────┬─────────────────────────────────────┐ │ Type │ Location │ Example │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Shared models │ models/database/ │ Platform, ContentPage, Vendor │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Shared services │ app/services/ │ FeatureService, SubscriptionService │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Shared middleware │ middleware/ │ PlatformContextMiddleware │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Platform routes │ app/platforms/{code}/routes/ │ OMS homepage, Loyalty dashboard │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Platform templates │ app/platforms/{code}/templates/ │ OMS-specific homepage │ ├────────────────────┼─────────────────────────────────┼─────────────────────────────────────┤ │ Platform config │ app/platforms/{code}/config.py │ Domain, features, defaults │ └────────────────────┴─────────────────────────────────┴─────────────────────────────────────┘ --- Critical Files to Modify ┌──────────────────────────────────────┬───────────────────────────────────────────────────────────────┐ │ File │ Changes │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ models/database/platform.py │ NEW - Platform model │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ models/database/vendor_platform.py │ NEW - Junction table │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ models/database/subscription.py │ Add platform_id, cms_pages_limit to existing SubscriptionTier │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ models/database/content_page.py │ Add platform_id, is_platform_page │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ models/database/feature.py │ Add CMS feature codes │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ middleware/platform_context.py │ NEW - Platform detection middleware │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ middleware/vendor_context.py │ Update to use platform_clean_path │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ app/services/content_page_service.py │ Add platform_id to all methods │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ app/services/feature_service.py │ Extend has_feature() with platform context │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ app/services/subscription_service.py │ Extend tier lookup with platform context │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ app/platforms/oms/ │ NEW - OMS-specific code │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ app/platforms/loyalty/ │ NEW - Loyalty-specific code │ ├──────────────────────────────────────┼───────────────────────────────────────────────────────────────┤ │ main.py │ Register PlatformContextMiddleware, platform-prefixed routes │ └──────────────────────────────────────┴───────────────────────────────────────────────────────────────┘ --- Migration Strategy Pre-Migration # 1. Create git tag git add -A && git commit -m "chore: prepare for multi-platform migration" git tag -a v1.0.0-pre-multiplatform -m "Before multi-platform CMS migration" git push origin v1.0.0-pre-multiplatform # 2. Backup database pg_dump wizamart > wizamart_backup_$(date +%Y%m%d).sql Migration Steps 1. Create platforms table with default "oms" platform 2. Create vendor_platforms junction table 3. Add platform_id, cms_pages_limit, cms_custom_pages_limit to existing subscription_tiers 4. Add platform_id and is_platform_page to content_pages 5. Backfill: Set all subscription_tiers.platform_id = OMS platform ID 6. Backfill: Set all content_pages.platform_id = OMS platform ID 7. Backfill: Set is_platform_page=True for extended slugs (homepage, pricing, about, contact, faq, terms, privacy, features, integrations) 8. Create vendor_platforms entries for all existing vendors → OMS 9. Update unique constraint on content_pages and subscription_tiers --- Implementation Phases Phase 1: Database & Models - Create Platform model - Create VendorPlatform junction table - Create PlatformSubscriptionTier model - Update ContentPage with platform_id, is_platform_page - Add CMS feature codes - Write Alembic migration - Test migration on dev database Phase 2: Middleware & Services - Create PlatformContextMiddleware - Update VendorContextMiddleware - Update ContentPageService with three-tier resolution - Create CMSLimitService - Update middleware registration order in main.py Phase 3: Admin Interface - Platform management UI (/admin/platforms) - Platform pages editor - Vendor defaults editor - Update content-pages list Phase 4: Vendor Dashboard - Show page source (Default/Override/Custom) - "Override" action for defaults - "Revert to Default" action - Page limit indicators Phase 5: Routes & Templates - Register platform-prefixed routes (dev mode) - Fix platform homepage to use CMS - Update shop routes with platform context - Test all URL patterns Phase 6: Loyalty Platform Setup - Create "loyalty" platform record - Create loyalty platform pages - Create loyalty vendor defaults - Test full flow --- Verification Steps 1. Git tag created: git tag -l | grep pre-multiplatform 2. Migration successful: SELECT * FROM platforms; SELECT COUNT(*) FROM vendor_platforms; SELECT platform_id, is_platform_page, COUNT(*) FROM content_pages GROUP BY 1, 2; 3. Dev URLs work: - localhost:9999/oms/ → OMS homepage - localhost:9999/loyalty/ → Loyalty homepage - localhost:9999/oms/vendor/wizamart/dashboard → Vendor dashboard 4. Three-tier resolution: - Create vendor override → shows override - Delete override → shows platform default - Delete default → shows 404 5. Page limits: Create pages until limit → shows upgrade prompt --- Open Questions Resolved ┌───────────────────────┬─────────────────────────────────────────────────────────────────────────────────────────┐ │ Question │ Answer │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ Domain routing │ Prod: separate domains / Dev: path-based │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ Vendor multi-platform │ Yes, junction table │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ Tier CMS restrictions │ Yes, integrate with existing feature system │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ MVP scope │ OMS + Loyalty, git tag first │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ Admin structure │ Global super admin only (/admin/*) │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ CMS page limits │ Essential: 3, Pro: 10, Business: 30, Enterprise: unlimited │ ├───────────────────────┼─────────────────────────────────────────────────────────────────────────────────────────┤ │ Platform page slugs │ platform_homepage, pricing, about, contact, faq, terms, privacy, features, integrations │ └───────────────────────┴─────────────────────────────────────────────────────────────────────────────────────────┘ --- CMS Tier Limits (Final) ┌──────────────┬─────────────┬──────────────┬─────────────────────────────────────────────────────┐ │ Tier │ Total Pages │ Custom Pages │ Features │ ├──────────────┼─────────────┼──────────────┼─────────────────────────────────────────────────────┤ │ Essential │ 3 │ 0 │ cms_basic │ ├──────────────┼─────────────┼──────────────┼─────────────────────────────────────────────────────┤ │ Professional │ 10 │ 5 │ cms_basic, cms_custom_pages, cms_seo │ ├──────────────┼─────────────┼──────────────┼─────────────────────────────────────────────────────┤ │ Business │ 30 │ 20 │ cms_basic, cms_custom_pages, cms_seo, cms_templates │ ├──────────────┼─────────────┼──────────────┼─────────────────────────────────────────────────────┤ │ Enterprise │ Unlimited │ Unlimited │ cms_unlimited_pages, cms_scheduling │ └──────────────┴─────────────┴──────────────┴─────────────────────────────────────────────────────┘ --- Platform Marketing Page Slugs (is_platform_page=True) These slugs will be marked as platform marketing pages during migration: - platform_homepage (or home) - pricing - about - contact - faq - terms - privacy - features - integrations All other vendor_id=NULL pages become vendor defaults (is_platform_page=False).