# app/modules/hosting/services/template_service.py """ Template service for the hosting module. Loads and manages industry templates from the templates_library directory. Templates are JSON files that define page content, themes, and sections for different business types (restaurant, construction, etc.). """ import json import logging from pathlib import Path logger = logging.getLogger(__name__) TEMPLATES_DIR = Path(__file__).parent.parent / "templates_library" class TemplateService: """Manages industry templates for POC site generation.""" def __init__(self): self._manifest = None self._cache: dict[str, dict] = {} def _load_manifest(self) -> dict: """Load the manifest.json file.""" if self._manifest is None: manifest_path = TEMPLATES_DIR / "manifest.json" self._manifest = json.loads(manifest_path.read_text(encoding="utf-8")) return self._manifest def list_templates(self) -> list[dict]: """List all available templates with metadata.""" manifest = self._load_manifest() templates = [] for entry in manifest.get("templates", []): template_id = entry["id"] meta = self._load_meta(template_id) templates.append({ "id": template_id, "name": meta.get("name", entry.get("name", template_id)), "description": meta.get("description", entry.get("description", "")), "tags": meta.get("tags", entry.get("tags", [])), "languages": meta.get("languages", []), "pages": entry.get("pages", []), }) return templates def get_template(self, template_id: str) -> dict | None: """Load a complete template with meta, theme, and all pages.""" if template_id in self._cache: return self._cache[template_id] template_dir = TEMPLATES_DIR / template_id if not template_dir.is_dir(): return None meta = self._load_meta(template_id) theme = self._load_json(template_dir / "theme.json") pages = self._load_pages(template_dir) template = { "id": template_id, "meta": meta, "theme": theme, "pages": pages, } self._cache[template_id] = template return template def get_theme(self, template_id: str) -> dict | None: """Load just the theme configuration for a template.""" template_dir = TEMPLATES_DIR / template_id return self._load_json(template_dir / "theme.json") def get_page(self, template_id: str, page_slug: str) -> dict | None: """Load a single page definition from a template.""" page_path = TEMPLATES_DIR / template_id / "pages" / f"{page_slug}.json" return self._load_json(page_path) def template_exists(self, template_id: str) -> bool: """Check if a template exists.""" return (TEMPLATES_DIR / template_id / "meta.json").is_file() def _load_meta(self, template_id: str) -> dict: """Load meta.json for a template.""" return self._load_json(TEMPLATES_DIR / template_id / "meta.json") or {} def _load_pages(self, template_dir: Path) -> list[dict]: """Load all page JSONs from a template's pages/ directory.""" pages_dir = template_dir / "pages" if not pages_dir.is_dir(): return [] pages = [] for page_file in sorted(pages_dir.glob("*.json")): page_data = self._load_json(page_file) if page_data: pages.append(page_data) return pages @staticmethod def _load_json(path: Path) -> dict | None: """Safely load a JSON file.""" if not path.is_file(): return None try: return json.loads(path.read_text(encoding="utf-8")) except (json.JSONDecodeError, OSError) as e: logger.warning("Failed to load template file %s: %s", path, e) return None template_service = TemplateService()