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>
This commit is contained in:
236
docs/proposals/hosting-architecture-decision.md
Normal file
236
docs/proposals/hosting-architecture-decision.md
Normal file
@@ -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"
|
||||
Reference in New Issue
Block a user