Skip to content

feat: spec-conformant llms.txt for AI agents#9618

Merged
MarkusNeusinger merged 4 commits into
mainfrom
feat/llms-txt
Jul 8, 2026
Merged

feat: spec-conformant llms.txt for AI agents#9618
MarkusNeusinger merged 4 commits into
mainfrom
feat/llms-txt

Conversation

@MarkusNeusinger

Copy link
Copy Markdown
Owner

Summary

  • /llms.txt previously fell through to SPA routing and returned the index.html shell — Lighthouse's new Agentic Browsing audit flagged it as a non-conformant llms.txt ("missing required H1", "contains no links"). There was in fact no llms.txt at all.
  • Adds app/public/llms.txt following the llmstxt.org format: H1 title, summary blockquote, context paragraph, and H2 sections (Catalog, Docs, Optional) with described links — catalog pages, sitemap, palette, the MCP endpoint (https://api.anyplot.ai/mcp/) and the GitHub repo.
  • Adds exact-match location = /llms.txt { try_files $uri =404; } to both nginx server blocks (same pattern as robots.txt): llms.txt consumers are bots, and any UA in the $is_bot map would otherwise be proxied to /seo-proxy/llms.txt and 404.

Notes

  • Copy avoids stale counts where possible; "fifteen libraries across four languages" matches the current About-page copy.
  • Related follow-ups NOT in this PR (need decisions): the Cloudflare-managed robots.txt currently Disallow: / for ClaudeBot/GPTBot/CCBot (audit finding — dashboard setting, undermines llms.txt for those crawlers), and the $is_bot map doesn't include AI-agent UAs (GPTBot, ClaudeBot, PerplexityBot, …), so they get the SPA shell instead of prerendered HTML.

Plan

N/A (direct request — Lighthouse Agentic Browsing finding)

Test plan

  • yarn builddist/llms.txt present with correct content
  • File satisfies the flagged checks: H1 heading + links present, valid Markdown
  • Post-deploy: curl https://anyplot.ai/llms.txt returns the file (human UA) and curl -A Googlebot https://anyplot.ai/llms.txt returns the file too (not a seo-proxy 404)

/llms.txt previously fell through to SPA routing and returned the
index.html shell — Lighthouse's Agentic Browsing audit flagged it as a
non-conformant llms.txt (no H1, no links). Adds a proper llmstxt.org
file (H1 + summary blockquote + H2 link sections) covering the catalog,
docs, MCP endpoint and repo, plus exact-match nginx locations in both
server blocks so mapped crawler UAs get the file instead of being
proxied to /seo-proxy/llms.txt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 8, 2026 22:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a spec-conformant llms.txt file for AI agents and ensures it’s served as a real static asset (not the SPA shell) by nginx, addressing Lighthouse “Agentic Browsing” audit findings.

Changes:

  • Add app/public/llms.txt formatted per llmstxt.org (H1 + summary + link sections).
  • Update app/nginx.conf to serve /llms.txt via exact-match location = /llms.txt in both server blocks, bypassing bot proxy / SPA routing.
  • Document the change in CHANGELOG.md under [Unreleased].

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
CHANGELOG.md Adds an [Unreleased] “Added” entry describing the new llms.txt behavior and nginx serving change.
app/public/llms.txt Introduces the new llms.txt content with catalog/docs links and MCP endpoint reference.
app/nginx.conf Adds exact-match nginx routing for /llms.txt to avoid bot proxy / SPA fallback behavior.

Comment thread app/nginx.conf Outdated
@codecov

codecov Bot commented Jul 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Review feedback (Copilot): that server block's fallback has no bot
proxy, so the location is defensive consistency, not a necessity —
say so instead of implying the main-block rationale applies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 8, 2026 22:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread CHANGELOG.md Outdated
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 8, 2026 22:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

…ntries)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 8, 2026 22:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@MarkusNeusinger MarkusNeusinger merged commit 73b076e into main Jul 8, 2026
10 checks passed
@MarkusNeusinger MarkusNeusinger deleted the feat/llms-txt branch July 8, 2026 22:44
MarkusNeusinger added a commit that referenced this pull request Jul 8, 2026
… 403s runner IPs) (#9619)

## Summary
- The first dispatched `bot-serving-check.yml` run failed with **403 on
all four checks — including the human-UA control**: Cloudflare's bot
management blocks GitHub-runner (datacenter) IPs, and a UA-spoofed
"Googlebot" only passes verified-bot checks when coming from real Google
IPs. The monitor was structurally unable to run from Actions against the
proxied domain.
- Switch all checks to the Cloud Run origin
(`anyplot-app-…-ez.a.run.app`) — exactly the layer that broke in the
2026-06/07 incident, so this is also the more precise probe.
Cloudflare-edge issues are explicitly out of this monitor's reach
(documented in the header comment).
- Adds an `llms.txt` check (Googlebot UA must get the file, never a
seo-proxy 404) — guards the exact-match nginx location from #9618.

## Verification
- Dispatched run 28981172030 documented the failure mode (4× 403).
- The updated script was dry-run against the live origin: **5/5 OK, exit
0**.
- After merge I will dispatch the workflow once — expected green.

## Test plan
- [x] YAML valid; script dry-run against live origin passes 5/5
- [ ] Post-merge `workflow_dispatch` run is green

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants