Overview
The formatter takes a list ofPageInfo objects and generates a structured markdown file following the llms.txt specification:
- Site title and summary from homepage
- Pages organized by URL path sections
- Optional markdown file linking (
.mdvariants) - Automatic content tagging
- Primary/secondary content separation
Core Functions
format_llms_txt()
Generates the complete llms.txt formatted output.str
required
The base URL of the crawled site
list[PageInfo]
required
List of crawled pages (first page should be homepage)
Dict[str, str]
default:"None"
Optional mapping from HTML URLs to markdown URLs
str
Formatted llms.txt content as a string
URL Processing
clean_url()
Removes query parameters and fragments from URLs.str
required
URL to clean
str
URL with only scheme, netloc, and path
get_md_url()
Converts an HTML URL to its potential markdown equivalent.str
required
Original URL
str
Converted markdown URL path
page.html→page.html.md/docs/→/docs/index.html.md/about→/about.md
check_md_exists()
Checks if a markdown version of a URL exists.str
required
URL to check
float
default:"5.0"
Request timeout in seconds
bool
True if markdown version returns 200
get_md_url_map()
Builds a mapping of HTML to markdown URLs for all pages.list[PageInfo]
required
List of pages to check
Dict[str, str]
Mapping from clean HTML URLs to markdown URLs (or original if no .md found)
- Sends HEAD requests concurrently for all pages
- Checks for markdown content types
- Falls back to original URL if no markdown exists
- Uses asyncio.gather for parallel requests
Text Processing
truncate()
Truncates text to specified length with ellipsis.str
required
Text to truncate
int
default:"150"
Maximum character length
str
Text truncated with ”…” if exceeded length, otherwise original
get_site_title()
Extracts site title from homepage, with fallback to domain name.PageInfo
required
Homepage page info
str
required
Site base URL
str
Site title (max 80 chars)
- Uses homepage title if meaningful
- Falls back to cleaned domain name for generic titles (“Home”, “Welcome”, “Index”)
- Truncated to 80 characters
get_summary()
Extracts site summary from homepage.PageInfo
required
Homepage page info
str
Site summary (max 200 chars)
- Homepage description
- Homepage snippet
- “No description available”
Section Processing
clean_section_name()
Cleanlifies section names for display.str
required
Raw section name from URL path
str
Capitalized, human-readable section name
- Replaces hyphens and underscores with spaces
- Capitalizes words
- Uppercases known abbreviations (API, REST, GraphQL, SDK, CLI, UI, UX, FAQ, RSS)
- Defaults to “Main” for empty names
is_secondary_section()
Determines if a section is secondary/optional content.str
required
Section name to check
bool
True if section matches secondary patterns
- Legal: privacy, terms, legal, cookie, disclaimer
- Meta: sitemap, changelog, release
- Community: contributing, code-of-conduct, governance, license
- Company: about, team, career, job, contact, company
- Social: twitter, github, linkedin, facebook, social
- Archive: archive, old, legacy, deprecated
Usage Examples
Basic Formatting
With Markdown URL Mapping
Section Organization
Content Tagging
The formatter integrates with thetagger module:
Related Modules
- crawler - Provides
PageInfoobjects - tagger - Assigns and formats content tags
- storage - Saves formatted output to R2