"""Sitemap & robots.txt generation: tenant-aware SEO content.
Because this is a white-label app where each tenant has its own domain
(set via KMTN_WEBSITE_URL), the sitemap and robots.txt are generated
at runtime — no static files are needed. The FastAPI /api/sitemap/*
endpoints call these functions; Nginx proxies /sitemap.xml and
/robots.txt to those endpoints so search-engine crawlers hit the right
content at the root URL.
"""
# Public routes included in the sitemap with their change frequency and priority.
SEOMAP_ROUTES = [
{"path": "/", "changefreq": "daily", "priority": 1.0},
{"path": "/about", "changefreq": "weekly", "priority": 0.8},
{"path": "/schedule", "changefreq": "weekly", "priority": 0.8},
{"path": "/events", "changefreq": "daily", "priority": 0.8},
{"path": "/contact", "changefreq": "monthly", "priority": 0.5},
]
def build_sitemap_xml(base_url: str) -> str:
"""Build a valid sitemap.xml string for the given base URL."""
url = base_url.rstrip("/")
entries = []
for route in SEOMAP_ROUTES:
entries.append(
f" \n"
f" {url}{route['path']}\n"
f" {route['changefreq']}\n"
f" {route['priority']}\n"
f" "
)
return (
'\n'
'\n'
+ "\n".join(entries) + "\n"
"\n"
)
def build_robots_txt(base_url: str) -> str:
"""Build a robots.txt string that references the correct sitemap URL."""
sitemap = base_url.rstrip("/") + "/sitemap.xml"
return (
"User-agent: *\n"
"Allow: /\n"
"\n"
"Disallow: /admin\n"
"Disallow: /login\n"
"\n"
f"Sitemap: {sitemap}\n"
)