Files
orion/app/modules/hosting/routes/pages/public.py
Samir Boulahtit e492e5f71c fix(hosting): render POC preview directly instead of iframe
The POC viewer was loading the storefront in an iframe, which hit the
StorefrontAccessMiddleware subscription check (POC sites don't have
subscriptions yet). Fixed by rendering CMS sections directly in the
preview template:
- Load ContentPages and StoreTheme from DB
- Render hero, features, testimonials, CTA sections inline
- Apply template colors/fonts via Tailwind CSS config
- HostWizard preview banner with nav links
- Footer with contact info
- No iframe, no subscription check needed

Also fixed Jinja2 dict.items collision (dict.items is the method,
not the 'items' key — use dict.get('items') instead).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 20:15:11 +02:00

103 lines
3.0 KiB
Python

# app/modules/hosting/routes/pages/public.py
"""
Hosting Public Page Routes.
Public-facing routes for POC site viewing:
- POC Viewer - Shows the Store's storefront with a HostWizard preview banner
"""
from fastapi import APIRouter, Depends, Path, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.orm import Session
from app.core.database import get_db
from app.templates_config import templates
router = APIRouter()
@router.get(
"/hosting/sites/{site_id}/preview",
response_class=HTMLResponse,
include_in_schema=False,
)
async def poc_site_viewer(
request: Request,
site_id: int = Path(..., description="Hosted Site ID"),
db: Session = Depends(get_db),
):
"""Render POC site viewer with HostWizard preview banner.
Renders CMS content directly (not via iframe to storefront) to
bypass the subscription access gate for pre-launch POC sites.
"""
from app.modules.cms.models.content_page import ContentPage
from app.modules.cms.models.store_theme import StoreTheme
from app.modules.hosting.models import HostedSite, HostedSiteStatus
from app.modules.tenancy.models import StorePlatform
site = db.query(HostedSite).filter(HostedSite.id == site_id).first()
# Only allow viewing for poc_ready or proposal_sent sites
if not site or site.status not in (
HostedSiteStatus.POC_READY,
HostedSiteStatus.PROPOSAL_SENT,
HostedSiteStatus.ACCEPTED,
):
return HTMLResponse(content="<h1>Site not available for preview</h1>", status_code=404)
store = site.store
# Get platform_id for CMS query
store_platform = (
db.query(StorePlatform)
.filter(StorePlatform.store_id == store.id)
.first()
) if store else None
platform_id = store_platform.platform_id if store_platform else None
# Load homepage (slug='homepage' from POC builder)
page = None
if platform_id:
page = (
db.query(ContentPage)
.filter(
ContentPage.platform_id == platform_id,
ContentPage.store_id == store.id,
ContentPage.slug == "homepage",
ContentPage.is_published.is_(True),
)
.first()
)
# Load all nav pages for this store
nav_pages = []
if platform_id:
nav_pages = (
db.query(ContentPage)
.filter(
ContentPage.platform_id == platform_id,
ContentPage.store_id == store.id,
ContentPage.is_published.is_(True),
ContentPage.show_in_header.is_(True),
)
.order_by(ContentPage.display_order)
.all()
)
# Load theme
theme = db.query(StoreTheme).filter(StoreTheme.store_id == store.id).first() if store else None
context = {
"request": request,
"site": site,
"store": store,
"page": page,
"nav_pages": nav_pages,
"theme": theme,
}
return templates.TemplateResponse(
"hosting/public/poc-viewer.html",
context,
)