# 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 ```json { "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) ```json { "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"