"""XML sitemap endpoint for runtime and direct backend access."""
from flask import Blueprint, Response, current_app
from app.extensions import limiter
sitemap_bp = Blueprint("sitemap", __name__)
STATIC_PAGES = [
("/", "daily", "1.0"),
("/about", "monthly", "0.4"),
("/contact", "monthly", "0.4"),
("/privacy", "yearly", "0.3"),
("/terms", "yearly", "0.3"),
("/pricing", "monthly", "0.7"),
("/blog", "weekly", "0.6"),
("/developers", "monthly", "0.5"),
]
BLOG_SLUGS = [
"how-to-compress-pdf-online",
"convert-images-without-losing-quality",
"ocr-extract-text-from-images",
"merge-split-pdf-files",
"ai-chat-with-pdf-documents",
]
TOOL_SLUGS = [
"pdf-to-word",
"word-to-pdf",
"compress-pdf",
"merge-pdf",
"split-pdf",
"rotate-pdf",
"pdf-to-images",
"images-to-pdf",
"watermark-pdf",
"remove-watermark-pdf",
"protect-pdf",
"unlock-pdf",
"page-numbers",
"reorder-pdf",
"extract-pages",
"pdf-editor",
"pdf-flowchart",
"pdf-to-excel",
"sign-pdf",
"crop-pdf",
"flatten-pdf",
"repair-pdf",
"pdf-metadata",
"image-converter",
"image-resize",
"compress-image",
"remove-background",
"image-crop",
"image-rotate-flip",
"ocr",
"chat-pdf",
"summarize-pdf",
"translate-pdf",
"extract-tables",
"html-to-pdf",
"qr-code",
"video-to-gif",
"word-counter",
"text-cleaner",
"pdf-to-pptx",
"excel-to-pdf",
"pptx-to-pdf",
"barcode-generator",
]
SEO_TOOL_SLUGS = [
"pdf-to-word",
"word-to-pdf",
"compress-pdf-online",
"convert-jpg-to-pdf",
"merge-pdf-files",
"remove-pdf-password",
"pdf-to-word-editable",
"convert-pdf-to-text",
"split-pdf-online",
"jpg-to-pdf",
"png-to-pdf",
"images-to-pdf-online",
"pdf-to-jpg",
"pdf-to-png",
"compress-pdf-for-email",
"compress-scanned-pdf",
"merge-pdf-online-free",
"combine-pdf-files",
"extract-pages-from-pdf",
"reorder-pdf-pages",
"rotate-pdf-pages",
"add-page-numbers-to-pdf",
"protect-pdf-with-password",
"unlock-pdf-online",
"watermark-pdf-online",
"remove-watermark-from-pdf",
"edit-pdf-online-free",
"pdf-to-excel-online",
"extract-tables-from-pdf",
"html-to-pdf-online",
"scan-pdf-to-text",
"chat-with-pdf",
"summarize-pdf-online",
"translate-pdf-online",
"convert-image-to-pdf",
"convert-webp-to-jpg",
"resize-image-online",
"compress-image-online",
"remove-image-background",
]
SEO_COLLECTION_SLUGS = [
"best-pdf-tools",
"free-pdf-tools-online",
"convert-files-online",
"pdf-converter-tools",
"secure-pdf-tools",
"ai-document-tools",
"image-to-pdf-tools",
"online-image-tools",
"office-to-pdf-tools",
"scanned-document-tools",
"arabic-pdf-tools",
]
def _site_origin() -> str:
return str(current_app.config.get("SITE_DOMAIN", "https://dociva.io")).strip().rstrip("/")
def _url_tag(loc: str, changefreq: str, priority: str) -> str:
return (
" \n"
f" {loc}\n"
" 2026-03-21\n"
f" {changefreq}\n"
f" {priority}\n"
" "
)
@sitemap_bp.route("/sitemap.xml", methods=["GET"])
@limiter.exempt
def sitemap_xml() -> Response:
"""Return an XML sitemap for direct backend access."""
origin = _site_origin()
entries = []
entries.extend(_url_tag(f"{origin}{path}", changefreq, priority) for path, changefreq, priority in STATIC_PAGES)
entries.extend(_url_tag(f"{origin}/blog/{slug}", "monthly", "0.6") for slug in BLOG_SLUGS)
entries.extend(_url_tag(f"{origin}/tools/{slug}", "weekly", "0.8") for slug in TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/{slug}", "weekly", "0.88") for slug in SEO_TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/ar/{slug}", "weekly", "0.8") for slug in SEO_TOOL_SLUGS)
entries.extend(_url_tag(f"{origin}/{slug}", "weekly", "0.82") for slug in SEO_COLLECTION_SLUGS)
entries.extend(_url_tag(f"{origin}/ar/{slug}", "weekly", "0.74") for slug in SEO_COLLECTION_SLUGS)
xml = (
'\n'
'\n'
+ "\n".join(entries)
+ "\n\n"
)
return Response(xml, mimetype="application/xml")