# Proposal: CMS Redesign — Alignment with Market Standards

**Date:** 2026-04-14
**Status:** Draft
**Author:** Samir / Claude

---

## Problem Statement

The CMS has good foundations but several design flaws that create confusion and limit usability:

1. **Template vs Theme are disconnected** — Theme (colors/fonts at `/admin/stores/{code}/theme`) and page template (layout structure in `ContentPage.template`) are separate concepts with overlapping names, no UI connection
2. **No template selector in admin** — The `template` field can only be set via seed data or API, not the UI
3. **Content vs Sections duality** — A page has both a freeform `content` field AND a structured `sections` JSON. Which one renders depends on the template. Confusing for admins
4. **Sections editor shows platform-only sections** — Pricing section appears for store pages where it makes no sense
5. **No title/content translation UI** — The `title_translations` and `content_translations` fields exist in the model but have no admin editor. Only seed data populates them. Store overrides lose translations
6. **Fixed section types** — Only 5-8 section types, can't be extended by modules
7. **No section reordering** — Sections render in a fixed order defined by the template
8. **Everything mixed in one list** — Platform marketing pages, store defaults, and store overrides all in `/admin/content-pages`

### Specific bug found
FASHIONHUB has a store override for `/about` with `title_translations=NULL`. The override was created without translations (no UI to add them), so it always shows "About Fashion Hub" regardless of language. The store default it overrides has full translations (`fr="À propos"`, etc.).

---

## Market Standard (Shopify, WordPress, Squarespace)

| Concept | Market Standard | Our Current State |
|---------|----------------|-------------------|
| **Page types** | "Page" (prose) vs "Landing page" (sections) — clearly distinct | Mixed: same model, hidden `template` field decides rendering |
| **Template** | A starting point you choose when creating a page, pre-populates layout | Hidden field, can't be changed in UI |
| **Sections** | Ordered list, drag-and-drop, add/remove any type | Fixed positions, hardcoded in template |
| **Theme** | Global visual styling (colors, fonts) applied to all templates | Separate system, works but disconnected |
| **Translations** | Per-field translations, always visible when editing | Fields exist but no admin UI for page title/content |
| **Content editing** | Rich text for prose pages, section editor for landing pages | Both shown on same edit page |
| **Storefront management** | Dedicated section (Shopify: "Online Store") | Mixed into Content Management |

---

## Proposed Admin Menu Restructure

### Current
```
Content Management (CMS module, order=70)
  ├── Content Pages      → /admin/content-pages     (everything mixed)
  └── Store Themes       → /admin/store-themes

Platform Admin (Tenancy module)
  ├── Merchants          → /admin/merchants
  ├── Stores             → /admin/stores
  └── Platforms          → /admin/platforms
```

### Proposed
```
Platform Admin (Tenancy module)
  ├── Merchants          → /admin/merchants
  ├── Stores             → /admin/stores
  ├── Storefronts        → /admin/storefronts        ← NEW (card grid per store)
  └── Platforms          → /admin/platforms

Content Management (CMS module)
  ├── Platform Pages     → /admin/platform-pages     (renamed, platform marketing only)
  └── Media Library      → /admin/media
```

### Storefronts page (`/admin/storefronts`)

Card grid layout (like current `/admin/store-themes` but expanded). Each store card shows:

```
┌─────────────────────────────────────┐
│  🏪 FashionHub                      │
│  loyalty platform · active          │
│                                     │
│  [Customize Theme]  [Edit Homepage] │
│  [Manage Pages]     [Preview →]     │
└─────────────────────────────────────┘
```

| Action | What it opens |
|--------|--------------|
| **Customize Theme** | `/admin/stores/{code}/theme` (existing, works well) |
| **Edit Homepage** | Landing page section editor for this store's `slug=home` page |
| **Manage Pages** | List of content pages for this store (about, contact, faq — with translations) |
| **Preview** | Opens storefront in new tab |

This replaces the current **Store Themes** menu item — themes become one tab/action within the broader Storefronts management.

### Platform Pages (`/admin/platform-pages`)

Renamed from "Content Pages". Only shows `is_platform_page=True` pages. Used for platform marketing (homepage, pricing, about, terms, privacy). This is what the admin uses to manage the platform marketing site — not individual store content.

---

## Proposed CMS Changes

### Change 1: Page type selector in admin UI

Add a **Page Type** dropdown at the top of the content page edit form:

| Page Type | Template field | Editor shows | Hides |
|-----------|---------------|-------------|-------|
| **Content Page** | `default` | Title (with translations), content editor (with translations), SEO | Sections editor |
| **Landing Page** | `full` | Title (with translations), section editor, SEO | Content field |

When switching types:
- Content → Landing: initialize empty sections if none exist, hide content field
- Landing → Content: show content field, hide sections editor
- Data is preserved in both cases (no deletion)

### Change 2: Title and content translation UI

Add **language tabs** to the title and content fields — same pattern the sections editor already uses:

```
[FR] [EN] [DE] [LB]
┌────────────────────────────┐
│ Title: À propos            │
└────────────────────────────┘
┌────────────────────────────┐
│ Content:                   │
│ Bienvenue chez ...         │
└────────────────────────────┘
```

- Default language tab edits `form.title` / `form.content` directly
- Other language tabs edit `form.title_translations[lang]` / `form.content_translations[lang]`
- When creating a store override from a default, pre-populate translations from the default

### Change 3: Template-driven section palette

The **template** (page type) defines which sections are available — not a hardcoded list filtered by context. The admin section editor loads the available section types from a template config.

| Template | Available Sections |
|----------|-------------------|
| `default` (platform homepage) | hero, features, products, pricing, testimonials, gallery, contact_info, cta |
| `full` (store landing page) | hero, features, testimonials, gallery, contact_info, cta |

Implementation: a `TEMPLATE_SECTION_PALETTE` dict mapping template name → list of allowed section types. The route handler passes the palette to the editor JS, which only renders sections in the palette. This keeps the logic in one place and sets up Phase C/D — when sections become an ordered array with add/remove, the template defines the palette of available types, and modules can extend that palette.

### Change 4: Sections as ordered list (future)

**Current:** Dict with fixed keys (`{"hero": {...}, "features": {...}, "cta": {...}}`)
**Proposed:** Ordered array:
```json
[
  {"type": "hero", "enabled": true, "data": {...}},
  {"type": "features", "enabled": true, "data": {...}},
  {"type": "cta", "enabled": true, "data": {...}}
]
```

Benefits:
- Admin can reorder (drag-and-drop)
- Admin can add/remove section types
- Template iterates array generically
- New section types don't require template changes

Migration: if `sections` is a dict → render in legacy order. If array → render in order.

### Change 5: Module-contributed section types (future)

New contract: `StorefrontSectionProviderProtocol`
- Catalog contributes: `product-showcase`, `category-grid`
- Loyalty contributes: `loyalty-signup`, `rewards-overview`
- Section registry aggregates from enabled modules
- Admin section editor shows available types from enabled modules

---

## What Stays the Same

- **3-tier content hierarchy** (platform → store default → store override) — solid
- **TranslatableText pattern** for sections — well-built
- **Section partials** as Jinja2 macros — reusable, themeable
- **Module-driven menus and widgets** — clean contracts
- **Theme system** (colors, fonts, CSS variables) — works well
- **CMS context providers** for header/footer pages — good pattern
- **ContentPage model** — no schema changes needed for Phase A

---

## Implementation Phases

### Phase A: Quick fixes (immediate, no schema changes)
- [ ] Title + content translation UI (language tabs on edit page)
- [ ] Page type selector (Content Page / Landing Page dropdown)
- [ ] Hide content field when Landing Page selected
- [ ] Template-driven section palette (template defines which sections are available)
- [ ] Fix: FASHIONHUB about page — add translations
- [ ] Fix: store theme API bug (done — `get_store_by_code_or_subdomain`)

### Phase B: Menu restructure + Storefronts page
- [ ] Add "Storefronts" menu item under Platform Admin
- [ ] Build card grid page at `/admin/storefronts`
- [ ] Rename "Content Pages" → "Platform Pages" (filter to `is_platform_page=True`)
- [ ] Move Store Themes into Storefronts
- [ ] "Edit Homepage" action on store card → section editor for store's home page
- [ ] "Manage Pages" action → filtered content page list for that store

### Phase C: Section ordering + add/remove
- [ ] Migrate sections from dict to ordered array
- [ ] Drag-and-drop reordering in admin section editor
- [ ] Add/remove sections from available types
- [ ] Template renders sections from ordered array
- [ ] Backward compatibility for dict-format sections

### Phase D: Module-contributed sections
- [ ] `StorefrontSectionProviderProtocol` contract
- [ ] Catalog: product-showcase section
- [ ] Loyalty: loyalty-signup section
- [ ] Section registry in CMS module
- [ ] Admin section editor shows available types from enabled modules

---

## Relation to Storefront Builder Vision

This proposal covers the CMS foundation. The broader [storefront builder vision](storefront-builder-vision.md) builds on top:

| Builder Vision Phase | CMS Redesign Phase |
|---------------------|-------------------|
| Phase 1: Wire sections to store homepages | ✅ Done |
| Phase 2: Module header actions | ✅ Done |
| Phase 3: Module-contributed sections | Phase D |
| Phase 4: Widget slots | Separate (post Phase D) |
| Phase 5: Per-store menus | Phase B sets up the UI |
| Phase 6: Visual editor | Post Phase C (drag-and-drop foundation) |

---

## Key Files

| Component | File |
|-----------|------|
| Content page edit template | `app/modules/cms/templates/cms/admin/content-page-edit.html` |
| Content page edit JS | `app/modules/cms/static/admin/js/content-page-edit.js` |
| ContentPage model | `app/modules/cms/models/content_page.py` |
| Section schemas | `app/modules/cms/schemas/homepage_sections.py` |
| Section partials | `app/modules/cms/templates/cms/platform/sections/_*.html` |
| CMS definition (admin menu) | `app/modules/cms/definition.py` |
| Tenancy definition (admin menu) | `app/modules/tenancy/definition.py` |
| Store theme page | `app/modules/cms/templates/cms/admin/store-theme.html` |
| Store themes list | `app/modules/cms/templates/cms/admin/store-themes.html` |
| Storefront landing templates | `app/modules/cms/templates/cms/storefront/landing-*.html` |
| Seed data | `scripts/seed/create_default_content_pages.py` |
