Files
orion/docs/proposals/hosting-architecture-decision.md
Samir Boulahtit 91963f3b87 docs: architecture decision — hosting sites reuse CMS + Store + StoreDomain
Hosted sites leverage existing CMS module (ContentPage, StoreTheme,
MediaFile) instead of building a separate site rendering system. Industry
templates (restaurant, construction, auto-parts, professional-services,
generic) are JSON presets that populate CMS entities for a new Store.

POC phase uses subdomain routing (acme.hostwizard.lu), go-live adds
custom domain via StoreDomain (acme.lu). All routing handled by existing
StoreContextMiddleware + Caddy wildcards.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 22:42:10 +02:00

9.1 KiB

Architecture Decision: Hosting Sites Leverage CMS + Store + StoreDomain

Decision

Hosted sites (POC and live) reuse the existing CMS module, Store entity, and StoreDomain routing — no separate site builder module.

Rationale

The CMS module already provides everything a hosted site needs:

  • ContentPage — store-scoped pages with three-tier inheritance (platform defaults → store overrides)
  • MediaFile — store-scoped media library
  • StoreTheme — per-store colors, fonts, logo, layout, custom CSS
  • Storefront rendering — Jinja2 templates that resolve store context and render CMS content

Building a parallel system would duplicate all of this.

How It Works

POC Phase (DRAFT → POC_READY → PROPOSAL_SENT)

  1. HostedSite.create() creates a Store on the hosting platform
  2. Store inherits default CMS pages from the hosting platform (homepage, about, contact, etc.)
  3. Admin selects an industry template (e.g., "restaurant", "construction") which applies:
    • Pre-built page sections (hero, services, gallery, testimonials, CTA)
    • Industry-appropriate theme (colors, fonts, layout)
    • Placeholder content that gets replaced with prospect data
  4. Admin customizes ContentPages + StoreTheme during POC phase
  5. POC preview accessible at subdomain: acme.hostwizard.lu

Go Live (ACCEPTED → LIVE)

  1. go_live(domain) calls store_domain_service.add_domain() — already implemented
  2. Custom domain acme.lu maps to the Store via StoreDomain
  3. StoreContextMiddleware resolves acme.lu → Store → CMS content
  4. Caddy + Cloudflare handle SSL and routing — already configured for wildcard subdomains

Content Flow

Prospect scanned (prospecting module)
    ↓ business_name, contacts, address, tech_profile
HostedSite created → Store created on hosting platform
    ↓
Industry template applied → ContentPages populated with prospect data
    ↓ homepage hero: "Acme Construction — Strasbourg"
    ↓ contact page: scraped email, phone, address
    ↓ theme: construction industry colors + layout
Admin refines content in CMS editor
    ↓
POC preview: acme.hostwizard.lu
    ↓
Client approves → go live: acme.lu

Industry Template System

What a Template Is

A template is NOT a separate rendering engine. It is a preset bundle that populates CMS entities for a new Store:

  • ContentPages: pre-built page slugs with section structures (hero, services, gallery, etc.)
  • StoreTheme: industry-appropriate colors, fonts, layout style
  • Media placeholders: stock images appropriate to the industry
  • Section blueprints: JSON structures for homepage sections

Template Registry

app/modules/hosting/templates_library/
├── manifest.json                    # Registry of all templates
├── restaurant/
│   ├── meta.json                    # Name, description, preview image, tags
│   ├── pages/                       # ContentPage seed data (JSON per page)
│   │   ├── homepage.json            # Sections: hero, menu-highlights, testimonials, reservation-cta
│   │   ├── about.json               # Our story, team, values
│   │   ├── menu.json                # Menu categories with placeholder items
│   │   └── contact.json             # Map, hours, reservation form
│   └── theme.json                   # Colors, fonts, layout config
├── construction/
│   ├── meta.json
│   ├── pages/
│   │   ├── homepage.json            # Sections: hero, services, projects-gallery, testimonials, cta
│   │   ├── services.json            # Service cards (renovation, new build, etc.)
│   │   ├── projects.json            # Portfolio gallery
│   │   └── contact.json             # Quote request form, address, phone
│   └── theme.json
├── auto-parts/
│   ├── meta.json
│   ├── pages/
│   │   ├── homepage.json            # Sections: hero, brands, categories, promotions
│   │   ├── catalog.json             # Category grid
│   │   └── contact.json             # Store locations, hours
│   └── theme.json
├── professional-services/           # Lawyers, accountants, consultants
│   ├── meta.json
│   ├── pages/
│   │   ├── homepage.json            # Sections: hero, expertise, team, testimonials
│   │   ├── services.json
│   │   ├── team.json
│   │   └── contact.json
│   └── theme.json
└── generic/                         # Fallback for any industry
    ├── meta.json
    ├── pages/
    │   ├── homepage.json
    │   ├── about.json
    │   └── contact.json
    └── theme.json

Template Meta Format

{
  "id": "restaurant",
  "name": "Restaurant & Dining",
  "description": "Elegant template for restaurants, cafés, and bars",
  "preview_image": "restaurant-preview.jpg",
  "tags": ["food", "dining", "hospitality"],
  "languages": ["en", "fr", "de"],
  "pages": ["homepage", "about", "menu", "contact"],
  "default_theme": {
    "theme_name": "modern",
    "colors": {
      "primary": "#b45309",
      "secondary": "#78350f",
      "accent": "#f59e0b",
      "background": "#fffbeb",
      "text": "#1c1917"
    },
    "font_family_heading": "Playfair Display",
    "font_family_body": "Inter",
    "layout_style": "grid",
    "header_style": "transparent"
  }
}

Page Section Format (homepage.json example)

{
  "slug": "homepage",
  "title": "{{business_name}}",
  "template": "full",
  "sections": {
    "hero": {
      "type": "hero",
      "headline": "{{business_name}}",
      "subheadline": "Quality dining in {{city}}",
      "cta_text": "Reserve a Table",
      "cta_link": "/contact",
      "background_image": "placeholder-restaurant-hero.jpg"
    },
    "features": {
      "type": "features_grid",
      "title": "Our Specialties",
      "items": [
        {"icon": "utensils", "title": "Fine Dining", "description": "..."},
        {"icon": "wine-glass", "title": "Wine Selection", "description": "..."},
        {"icon": "cake", "title": "Pastry", "description": "..."}
      ]
    },
    "testimonials": {
      "type": "testimonials",
      "title": "What Our Guests Say",
      "items": []
    },
    "cta": {
      "type": "cta_banner",
      "headline": "Ready to visit?",
      "cta_text": "Contact Us",
      "cta_link": "/contact"
    }
  }
}

{{business_name}}, {{city}}, {{phone}}, {{email}} are replaced with prospect data at POC creation time.

What Needs to Be Built

Phase 1 — Template Infrastructure (in hosting module)

Component Purpose
hosting/templates_library/ directory Template files (JSON)
hosting/services/template_service.py Load manifest, list templates, validate
hosting/services/poc_builder_service.py Apply template to Store: create ContentPages, set StoreTheme, replace placeholders with prospect data
hosting/schemas/template.py TemplateListResponse, TemplateDetailResponse
API: GET /admin/hosting/templates List available templates with previews
API: POST /admin/hosting/poc/build Build POC: {prospect_id, template_id, merchant_id}

Phase 2 — Template Content

Create 5 industry templates:

  1. Restaurant — hero, menu highlights, testimonials, reservation CTA
  2. Construction — hero, services, project gallery, quote CTA
  3. Auto Parts — hero, brand grid, product categories, store locator
  4. Professional Services — hero, expertise areas, team, case studies
  5. Generic — clean, minimal, works for any business

Each template needs:

  • 3-4 page JSONs with sections
  • Theme JSON (colors, fonts)
  • Meta JSON (name, description, tags, preview)
  • Placeholder images (can use free stock photos initially)

Phase 3 — Storefront Rendering Enhancement

The existing storefront templates render ContentPage.sections as HTML. Verify:

  • All section types used by templates are supported by the storefront renderer
  • Homepage sections (hero, features_grid, testimonials, cta_banner) render correctly
  • Theme colors/fonts apply to the storefront

If new section types are needed (e.g., menu, project_gallery, team_grid), add them to the storefront section renderer.

What Already Exists (No Work Needed)

  • Store creation with subdomain
  • StoreDomain custom domain assignment + verification
  • StoreContextMiddleware (subdomain + custom domain + path-based routing)
  • CMS ContentPage three-tier hierarchy
  • StoreTheme with colors, fonts, layout, custom CSS
  • MediaFile upload and serving
  • Storefront page rendering
  • Caddy wildcard SSL for *.hostwizard.lu
  • Cloudflare proxy + WAF for custom domains
  • go_live() already calls store_domain_service.add_domain()

Relationship to Other Proposals

  • hosting-site-creation-fix.md: Must be implemented first — site creation needs merchant_id or prospect_id (no system merchant hack)
  • security-audit-demo-poc-builder.md Phase 4: This document replaces Phase 4 with a more detailed architecture. The POC builder is now "apply industry template to Store CMS" rather than a vague "build better site"