Skip to main content

Purpose

Updates an AI website with content changes detected by detect-changes. Uses three parallel Gemini calls (same pattern as onboarding) for consistency and better results.

Architecture

Three Parallel Gemini Calls

CallInputOutputPurpose
1Current llms.txt + changesUpdated llms.txtAI-readable content
2Current homepage + changesUpdated Q&A structureHomepage + FAQ pages
3Current Schema.org + changesUpdated JSON-LDStructured data
All three calls run in parallel using asyncio.gather() for speed.

Request Body

Takes the output from detect-changes:
{
  "business_id": "org-slug-123",
  "new_pages": [...],        // Have markdown
  "changed_pages": [...],    // Have markdown
  "removed_urls": [...],
  "unchanged_pages": [...],  // NO markdown
  "updated_site_map": [...],
  "updated_hashes": {...},
  "business_info": {...}
}

What Gets Updated

FileWhen UpdatedGenerated By
llms.txtContent changes detectedGemini call 1
pages/index.jsContent changes detectedGemini call 2
data.jsonContent changes detectedGemini call 3
pages/*.js (replicas)New or changed pagesDeterministic
sitemap.xmlNew or removed pagesDeterministic
robots.txtNever (static)Deterministic

Efficiency

Only new_pages and changed_pages have markdown content (from Firecrawl batch scrape). unchanged_pages are NOT scraped - they keep their existing hashes. This means:
  • Gemini only processes changed content
  • Replica pages only regenerated for changed pages
  • Unchanged content is preserved

Response Format

{
  "status": "success",
  "files_updated": 42,
  "changed_urls": ["/about", "/pricing"],
  "deployment_url": "https://..."
}

Code Location

src/app/apis/cron/update_ai_site/
├── routes.py           # HTTP endpoint
└── mini_orchestrator.py # Update logic with 3 parallel Gemini calls

Next Step

After update, call submit-indexnow with changed_urls to notify search engines.