# CMS Data Model

Entity relationships and database schema for the CMS module.

## Entity Relationship Overview

```
Platform 1──* ContentPage
Store    1──* ContentPage
Store    1──* MediaFile
Store    1──1 StoreTheme
```

## Models

### ContentPage

Multi-language content pages with platform/store hierarchy. Pages can be platform marketing pages, store defaults, or store-specific overrides.

| Field | Type | Constraints | Description |
|-------|------|-------------|-------------|
| `id` | Integer | PK | Primary key |
| `platform_id` | Integer | FK, not null, indexed | Platform this page belongs to |
| `store_id` | Integer | FK, nullable, indexed | Store association (null = platform/default) |
| `is_platform_page` | Boolean | not null, default False | Platform marketing page vs store default |
| `slug` | String(100) | not null, indexed | Page identifier (about, faq, contact, etc.) |
| `title` | String(200) | not null | Page title |
| `content` | Text | not null | HTML or Markdown content |
| `content_format` | String(20) | default "html" | Format: html, markdown |
| `template` | String(50) | default "default" | Template: default, minimal, modern, full |
| `sections` | JSON | nullable | Structured homepage sections with i18n |
| `title_translations` | JSON | nullable | Language-keyed title dict {en, fr, de, lb} |
| `content_translations` | JSON | nullable | Language-keyed content dict {en, fr, de, lb} |
| `meta_description` | String(300) | nullable | SEO meta description |
| `meta_keywords` | String(300) | nullable | SEO keywords |
| `is_published` | Boolean | not null, default False | Publication status |
| `published_at` | DateTime | nullable, tz-aware | Publication timestamp |
| `display_order` | Integer | not null, default 0 | Menu/footer ordering |
| `show_in_footer` | Boolean | not null, default True | Footer visibility |
| `show_in_header` | Boolean | not null, default False | Header navigation |
| `show_in_legal` | Boolean | not null, default False | Legal bar visibility |
| `created_at` | DateTime | tz-aware | Record creation time |
| `updated_at` | DateTime | tz-aware | Record update time |
| `created_by` | Integer | FK, nullable | Creator user ID |
| `updated_by` | Integer | FK, nullable | Updater user ID |

**Unique Constraint**: `(platform_id, store_id, slug)`
**Composite Indexes**: `(platform_id, store_id, is_published)`, `(platform_id, slug, is_published)`, `(platform_id, is_platform_page)`

**Page tiers**: platform → store_default (store_id null, not platform) → store_override (store_id set)

### MediaFile

Media files (images, videos, documents) managed per-store.

| Field | Type | Constraints | Description |
|-------|------|-------------|-------------|
| `id` | Integer | PK | Primary key |
| `store_id` | Integer | FK, not null, indexed | Store owner |
| `filename` | String(255) | not null, indexed | UUID-based stored filename |
| `original_filename` | String(255) | nullable | Original upload name |
| `file_path` | String(500) | not null | Relative path from uploads/ |
| `media_type` | String(20) | not null | image, video, document |
| `mime_type` | String(100) | nullable | MIME type |
| `file_size` | Integer | nullable | File size in bytes |
| `width` | Integer | nullable | Image/video width in pixels |
| `height` | Integer | nullable | Image/video height in pixels |
| `thumbnail_path` | String(500) | nullable | Path to thumbnail |
| `alt_text` | String(500) | nullable | Alt text for images |
| `description` | Text | nullable | File description |
| `folder` | String(100) | default "general" | Folder: products, general, etc. |
| `tags` | JSON | nullable | Tags for categorization |
| `extra_metadata` | JSON | nullable | Additional metadata (EXIF, etc.) |
| `is_optimized` | Boolean | default False | Optimization status |
| `optimized_size` | Integer | nullable | Size after optimization |
| `usage_count` | Integer | default 0 | Usage tracking |
| `created_at` | DateTime | tz-aware | Record creation time |
| `updated_at` | DateTime | tz-aware | Record update time |

**Composite Indexes**: `(store_id, folder)`, `(store_id, media_type)`

### StoreTheme

Per-store theme configuration including colors, fonts, layout, and branding. One-to-one with Store.

| Field | Type | Constraints | Description |
|-------|------|-------------|-------------|
| `id` | Integer | PK | Primary key |
| `store_id` | Integer | FK, unique, not null | One-to-one with store |
| `theme_name` | String(100) | default "default" | Preset: default, modern, classic, minimal, vibrant |
| `is_active` | Boolean | default True | Theme active status |
| `colors` | JSON | default {...} | Color scheme: primary, secondary, accent, background, text, border |
| `font_family_heading` | String(100) | default "Inter, sans-serif" | Heading font |
| `font_family_body` | String(100) | default "Inter, sans-serif" | Body font |
| `logo_url` | String(500) | nullable | Store logo path |
| `logo_dark_url` | String(500) | nullable | Dark mode logo |
| `favicon_url` | String(500) | nullable | Favicon path |
| `banner_url` | String(500) | nullable | Homepage banner |
| `layout_style` | String(50) | default "grid" | Layout: grid, list, masonry |
| `header_style` | String(50) | default "fixed" | Header: fixed, static, transparent |
| `product_card_style` | String(50) | default "modern" | Card: modern, classic, minimal |
| `custom_css` | Text | nullable | Custom CSS overrides |
| `social_links` | JSON | default {} | Social media URLs |
| `meta_title_template` | String(200) | nullable | SEO title template |
| `meta_description` | Text | nullable | SEO meta description |
| `created_at` | DateTime | tz-aware | Record creation time |
| `updated_at` | DateTime | tz-aware | Record update time |

## Design Patterns

- **Three-tier content hierarchy**: Platform pages → store defaults → store overrides
- **JSON translations**: Title and content translations stored as JSON dicts with language keys
- **Media organization**: Files organized by store and folder with type classification
- **Theme presets**: Named presets with full customization via JSON color scheme and CSS overrides
- **SEO support**: Meta description, keywords, and title templates on pages and themes
