Skip to main content

Overview

This page documents the complete data flow through the llms.txt Generator system, from initial user request to final llms.txt file delivery.

User-Initiated Crawl Flow

Step-by-Step Flow Diagram

Detailed Step Breakdown

1

User Input

User enters website URL and configuration:
  • url: Target website (e.g., https://example.com)
  • maxPages: Page limit (default: 50)
  • descLength: Description length (default: 500)
  • enableAutoUpdate: Schedule recrawls (default: false)
  • recrawlIntervalMinutes: Recrawl frequency (default: 360)
  • llmEnhance: AI optimization (default: false)
  • useBrightdata: Use proxy for JS sites (default: false)
2

WebSocket Connection

Frontend establishes WebSocket connection:
3

Authentication

Backend validates credentials:
  • API Key: Query parameter ?api_key=xxx (main.py:98-101)
  • JWT Token: Alternative via ?token=xxx (main.py:92-96)
  • Rejection: Closes connection with code 1008 if invalid
4

Crawler Initialization

LLMCrawler instance created with configuration:
5

Sitemap Detection

Crawler attempts to find sitemap (llm_crawler.py:30-38):
  • Try /sitemap.xml
  • Try /sitemap_index.xml
  • Parse XML and extract URLs
  • If found: Populate queue with sitemap URLs
  • If not found: Use BFS crawl starting from homepage
6

Page Fetching

For each URL in queue (llm_crawler.py:66-95):Attempt 1: httpx (fast)
  • HTTP GET request with 10s timeout
  • Check if HTML has meaningful content
  • Success: Use this HTML
Attempt 2: Playwright (JavaScript support)
  • Only if httpx fails or no meaningful content
  • Launch headless Chromium browser
  • Wait for network idle
  • Extract rendered HTML
Attempt 3: Brightdata (optional)
  • Only if enabled and previous attempts fail
  • Use Brightdata’s scraping browser
  • Bypass anti-bot protections
7

Content Extraction

BeautifulSoup parses HTML (text.py):Title Extraction:
  • Try <title> tag
  • Fallback to <h1> tag
  • Fallback to “Untitled”
Description Extraction:
  • Try <meta name="description">
  • Fallback to <meta property="og:description">
  • Fallback to first paragraph
Text Content:
  • Extract visible text from body
  • Remove script/style tags
  • Clean whitespace
  • Create snippet (truncate to desc_length)
Link Discovery (scout.py):
  • Extract all <a href> links
  • Normalize URLs (relative → absolute)
  • Filter to same domain
  • Add to queue if not visited
8

llms.txt Generation

Format pages into llms.txt spec (formatter.py):Structure:
Features:
  • Hierarchical section grouping
  • Clean URL generation (prefer .md links)
  • Content truncation at semantic boundaries
  • Metadata header with timestamp
9

LLM Enhancement (Optional)

If llmEnhance: true (main.py:138-151):
  1. Send llms.txt to OpenRouter API
  2. Use Grok 4.1-Fast model
  3. Prompt: Summarize, optimize, improve readability
  4. Replace original with enhanced version
  5. Stream enhancement status to user
10

Storage: R2 Upload

Save to Cloudflare R2 (storage.py):
11

Database: Save Metadata

Store in Supabase (database.py:save_site_metadata):
12

Real-time Updates

Backend streams messages to frontend via WebSocket:Log Messages:
Result:
Public URL:
Errors:
13

UI Display

Frontend receives messages and updates UI:
  • Logs: Append to scrolling log viewer
  • Result: Display in preview pane
  • URL: Show copy/download buttons
  • Errors: Display error banner

Scheduled Recrawl Flow

Automatic Update Diagram

Recrawl Logic Details

This finds sites where:
  • They’ve been crawled before (last_crawled_at IS NOT NULL)
  • The next scheduled crawl time has passed
  • Limited to 100 sites per run
  • Site unreachable: Mark as failed, retry next cycle
  • Crawl timeout: Partial results saved if any pages succeeded
  • R2 upload fails: Log error, keep old URL in database
  • Database errors: Log and continue to next site

WebSocket Message Types

Message Format Reference

Data Storage Details

Supabase Schema

R2 Storage Structure

Each recrawl creates a new file with a timestamp. Old versions remain accessible unless manually deleted.

Performance Characteristics

Typical Crawl Times

  • Small site (5-10 pages): 10-30 seconds
  • Medium site (20-50 pages): 30-90 seconds
  • Large site (50+ pages with sitemap): 1-3 minutes
  • JS-heavy site (with Brightdata): 2-5 minutes

Bottlenecks

  1. Page Fetch Speed: Limited by target site’s response time
  2. Playwright Launch: ~2-3 seconds per browser instance
  3. LLM Enhancement: ~5-10 seconds per request
  4. R2 Upload: Negligible (under 1 second)

Optimization Strategies

  • Sitemap first: Faster than BFS crawl
  • httpx before Playwright: 10x faster for static sites
  • Concurrent fetching: asyncio for parallel requests
  • Skip unchanged sites: Hash comparison prevents redundant uploads

Next Steps

API Reference

Complete WebSocket API documentation

Deployment

Deploy your own instance