From 91963f3b879f8e2e59a3e89f5d3f3a71062ad45e Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Tue, 31 Mar 2026 22:42:10 +0200 Subject: [PATCH] =?UTF-8?q?docs:=20architecture=20decision=20=E2=80=94=20h?= =?UTF-8?q?osting=20sites=20reuse=20CMS=20+=20Store=20+=20StoreDomain?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- .../hosting-architecture-decision.md | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 docs/proposals/hosting-architecture-decision.md diff --git a/docs/proposals/hosting-architecture-decision.md b/docs/proposals/hosting-architecture-decision.md new file mode 100644 index 00000000..e3667c35 --- /dev/null +++ b/docs/proposals/hosting-architecture-decision.md @@ -0,0 +1,236 @@ +# 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"