Skip to content

GTM-4211: correct llms.txt facts and cover the pages it was missing - #1026

Merged
keenbeen32 merged 2 commits into
mainfrom
gtm-4211-llms-content
Aug 12, 2026
Merged

GTM-4211: correct llms.txt facts and cover the pages it was missing#1026
keenbeen32 merged 2 commits into
mainfrom
gtm-4211-llms-content

Conversation

@Jordy-Baby

@Jordy-Baby Jordy-Baby commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Five fixes to the generated llms.txt, the file AI assistants and answer engines read to understand Envio. The generator itself was working correctly. Everything here is content that was wrong, missing, or drifting.

1. The benchmark stat did not match our own benchmarks page

The header read:

Benchmark: Envio 1 min vs The Graph 143 min (Uniswap V2 Factory, Sentio, May 2025)

Our benchmarks page reports that case as Envio 8s against The Graph 19m, from April 2025. The 143 appears to be the "142x slower" multiplier read as minutes. envio.dev/llms.txt already stated it correctly, so the two files disagreed. This is the opening paragraph, so it is the line most likely to be quoted back at us.

Now quoted exactly as the benchmarks page reports it.

2. Chain count was hardcoded and had drifted

Said 70+, while the real figure was materially higher. Now interpolated from network-count.json, which is regenerated from the live chain API on every build. Confirmed working end to end: prebuild moved it 81 to 80 on its own during verification.

The count is EVM-only by construction, which is why Fuel stays named separately in the sentence.

3. Twenty live pages appeared in no llms file

19 showcase pages and /videos are live and in the sitemap, but were in none of the three files.

Both now collect from the same sources that render them, so there is no second list to keep in step. Showcase reads _data.js, standalone pages are globbed from src/pages. Neither has a .md twin, so both link to the rendered URL.

4. Relative links in the .md copies resolved to 404s

The copies are served from a flattened slug URL rather than their source directory, so source-relative links broke:

  • ../../static/img/sync.gif resolved to a 404, correct asset is /img/sync.gif
  • ../Advanced/hypersync.md resolved to a 404, correct page is /docs/HyperIndex/hypersync.md

Now resolved to absolute URLs. Resolution tries URL space first, matching how the rendered page behaves, then falls back to the source tree, and warns on anything it cannot place.

5. Smaller items

  • Five pages gained a frontmatter description, replacing generated "X section of the docs." filler and one empty description.
  • llms.txt now points at llms-full.txt and llms-full-blog.txt. Both referenced it, but not the other way round, so an agent entering through the index could not discover them.

Verification

Full yarn build, exit 0.

  • All 274 URLs in the generated file return 200 live, up from 253, checked with a deliberate bad URL as a control
  • 0 unresolved relative links, down from 3 affected pages
  • 0 filler or empty descriptions, down from 5
  • All 29 rewritten asset paths exist in the build
  • llms-full.txt and llms-full-blog.txt still match the index exactly, 96 docs pages and 79 posts

GTM-4211

The llms.txt header carried a benchmark line that did not match our own
benchmarks page on any value. It read "Envio 1 min vs The Graph 143 min
(Uniswap V2 Factory, Sentio, May 2025)". The benchmarks page has that case
at Envio 8s against The Graph 19m, from April 2025, and 143 appears to be
the "142x slower" multiplier read as minutes. envio.dev/llms.txt already
states it correctly, so the two files disagreed.

Changes here:

- Header quotes the benchmark exactly as the benchmarks page reports it.
- Chain count is interpolated from network-count.json, which is regenerated
  from the live chain API on every build, instead of a hardcoded "70+" that
  had drifted well below the real figure. The count is EVM-only by
  construction, which is why Fuel stays named separately in the sentence.
- Showcase entries and standalone pages are now collected. 19 showcase pages
  and /videos are live and in the sitemap but appeared in no llms file.
  Showcase reads the same _data.js that renders the pages and standalone
  pages are globbed from src/pages, so neither needs a second list to keep
  in step. Both link to the rendered URL, as they have no .md twin.
- Relative links in the per-page .md copies are resolved to absolute URLs.
  The copies are served from the flattened slug URL, not their source
  directory, so a link like ../../static/img/sync.gif or
  ../Advanced/hypersync.md resolved to a 404 for anything consuming them.
  Resolution tries URL space first, matching how the rendered page behaves,
  then the source tree, and warns on anything it cannot place.
- Five pages gained a frontmatter description, replacing the generated
  "X section of the docs." filler and one empty description.

Verified with a full build: builds clean, zero unresolved relative links,
zero filler descriptions, and all 19 new showcase URLs plus /videos return
200 live.
GTM-4211

llms-full.txt and llms-full-blog.txt both name llms.txt in their own headers,
but llms.txt named neither, so an agent entering through the index had no way
to find them. envio.dev/llms.txt already links both. Adds them to Optional.
@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
envio-docs Ready Ready Preview Aug 11, 2026 10:01pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds descriptive metadata to selected documentation pages and extends LLM output generation with dynamic HyperSync coverage, standalone pages, showcase entries, resource links, and relative-link rewriting for Markdown copies.

Changes

LLM documentation generation

Layer / File(s) Summary
Content metadata and network coverage
docs/HyperIndex/..., docs/HyperIndexV2/..., docusaurus.config.js
Documentation pages now include descriptions. The generated LLM header uses network-derived HyperSync chain counts and updated benchmark text.
Standalone and showcase entry collection
plugins/plugin-generate-llms.js, docusaurus.config.js
LLM generation collects standalone pages and showcase entries, formats their rendered URLs, adds Showcase and Other sections, and exposes full documentation and blog resources.
Markdown copy link rewriting
plugins/plugin-generate-llms.js
Relative links resolve to published Markdown URLs or root-relative assets. Unresolved links remain unchanged and produce warnings. Non-Markdown entries stay out of Markdown copies and the full-document pool.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant DocusaurusConfig
  participant PluginGenerateLLMs
  participant NetworkData
  participant PageSources
  participant LLMOutput
  DocusaurusConfig->>NetworkData: read generated network data
  DocusaurusConfig->>PluginGenerateLLMs: configure LLM sources and dynamic header
  PluginGenerateLLMs->>PageSources: collect standalone pages and showcase entries
  PageSources-->>PluginGenerateLLMs: return rendered URLs and metadata
  PluginGenerateLLMs->>LLMOutput: generate index and Markdown copies
  PluginGenerateLLMs->>LLMOutput: rewrite relative links and add resource links
Loading

Possibly related PRs

  • enviodev/docs#1019: Both PRs update HyperSync chain-count messaging and the hyperSyncChainCount data.
  • enviodev/docs#1023: Both PRs modify docs/HyperIndex/Advanced/config-schema-reference.md.

Suggested reviewers: nikbhintade, dzakh

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main changes to correct llms.txt facts and add previously missing pages.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@plugins/plugin-generate-llms.js`:
- Around line 696-705: Update the page directive generation in injectHtmlTags so
it only advertises an appended .md URL for documentation and blog pages,
matching the writeMarkdownCopies filter that excludes standalone pages and
showcase entries; preserve the existing directive for pages that actually
receive Markdown copies.
- Around line 261-288: Update the pageFiles glob options to also ignore Markdown
files under underscore-prefixed directories by adding the "**/_*/**" exclusion.
In the route computation for each collected page, special-case a root-level
index.md or index.mdx so its route is the site root rather than "/index", while
preserving existing nested index and extension handling.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f1e1be96-4149-42c1-9972-cec1dabccb5f

📥 Commits

Reviewing files that changed from the base of the PR and between bf75e88 and 7001b32.

📒 Files selected for processing (7)
  • docs/HyperIndex/Advanced/config-schema-reference.md
  • docs/HyperIndex/supported-networks/index.md
  • docs/HyperIndexV2/Advanced/config-schema-reference.md
  • docs/HyperIndexV2/Hosted_Service/hosted-service-features.md
  • docs/HyperIndexV2/Hosted_Service/hosted-service-monitoring.md
  • docusaurus.config.js
  • plugins/plugin-generate-llms.js

Comment on lines +261 to +288
const pageFiles = glob.sync("**/*.{md,mdx}", {
cwd: pagesAbsPath,
// Partials and data files are prefixed with _ by
// Docusaurus convention and are not routable.
ignore: ["**/_*.{md,mdx}"],
});

for (const file of pageFiles) {
const fullPath = path.join(pagesAbsPath, file);
const parsed = matter(
fs.readFileSync(fullPath, "utf-8")
);
const title = parsed.data.title;
if (!title) continue;

const route = toPosix(file).replace(
/(\/index)?\.(md|mdx)$/,
""
);

collectedDocs.push({
filePath: fullPath,
relativePath: toPosix(
path.relative(context.siteDir, fullPath)
),
title,
description: parsed.data.description || "",
pageUrl: `${url.replace(/\/$/, "")}/${route}`,

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

fd -t f -e md -e mdx . src/pages | sort
fd -t f -e md -e mdx . src/pages |
  rg '(^|/)_.*(/|$)|/index\.mdx?$' || true

Repository: enviodev/docs

Length of output: 172


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- plugin structure and relevant implementation ---'
sed -n '1,380p' plugins/plugin-generate-llms.js

printf '%s\n' '--- Docusaurus configuration and package versions ---'
fd -t f 'package.json|docusaurus.config.*|sidebars.*' . -x sh -c 'echo "--- $1"; sed -n "1,220p" "$1"' sh {}

Repository: enviodev/docs

Length of output: 43851


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- plugin configuration and page sources ---'
rg -n -C 5 'plugin-generate-llms|generate-llms|pages:|showcase:|src/pages|pagesDir|pagesAbsPath' \
  --glob '!plugins/plugin-generate-llms.js' \
  --glob '!package-lock.json' \
  --glob '!yarn.lock' .

printf '%s\n' '--- all page files and underscore paths ---'
fd -t f -e md -e mdx . | sort | rg '(^|/)src/pages(/|$)|(^|/)_[^/]*(/|$)' || true

printf '%s\n' '--- route transformation for representative page paths ---'
node - <<'JS'
const paths = [
  "index.md",
  "index.mdx",
  "videos.mdx",
  "guide/index.md",
  "_partial.md",
  "_data/entry.md",
  "guide/_partial.md",
  "_private/index.md",
];
for (const file of paths) {
  const current = file.replace(/(\\/index)?\\.(md|mdx)$/, "");
  const proposedPath = file.replace(/\\.(md|mdx)$/, "");
  const proposed =
    proposedPath === "index" ? "" : proposedPath.replace(/\\/index$/, "");
  console.log(JSON.stringify({file, current, proposed}));
}
JS

Repository: enviodev/docs

Length of output: 8461


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' '--- plugin configuration and page sources ---'
rg -n -C 5 'plugin-generate-llms|generate-llms|pages:|showcase:|src/pages|pagesDir|pagesAbsPath' \
  --glob '!plugins/plugin-generate-llms.js' \
  --glob '!package-lock.json' \
  --glob '!yarn.lock' .

printf '%s\n' '--- all page files and underscore paths ---'
fd -t f -e md -e mdx . | sort | rg '(^|/)src/pages(/|$)|(^|/)_[^/]*(/|$)' || true

printf '%s\n' '--- route transformation for representative page paths ---'
node - <<'JS'
const paths = [
  "index.md",
  "index.mdx",
  "videos.mdx",
  "guide/index.md",
  "_partial.md",
  "_data/entry.md",
  "guide/_partial.md",
  "_private/index.md",
];
for (const file of paths) {
  const current = file.replace(/(\/index)?\.(md|mdx)$/, "");
  const proposedPath = file.replace(/\.(md|mdx)$/, "");
  const proposed =
    proposedPath === "index" ? "" : proposedPath.replace(/\/index$/, "");
  console.log(JSON.stringify({file, current, proposed}));
}
JS

Repository: enviodev/docs

Length of output: 8319


Match Docusaurus page routing and exclusions.

The collector is enabled for src/pages. It must also ignore Markdown files inside underscore-prefixed directories, and it must map index.md(x) to the site root instead of /index. Add "**/_*/**" to ignore and special-case the root index route as shown in the proposed fix.

🧰 Tools
🪛 ast-grep (0.45.1)

[warning] 270-270: Filesystem path is not a string literal; a request-/variable-derived path can enable path traversal. Validate and normalize the path before use.
Context: fs.readFileSync(fullPath, "utf-8")
Note: [CWE-22] Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal').

(detect-non-literal-fs-filename)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/plugin-generate-llms.js` around lines 261 - 288, Update the pageFiles
glob options to also ignore Markdown files under underscore-prefixed directories
by adding the "**/_*/**" exclusion. In the route computation for each collected
page, special-case a root-level index.md or index.mdx so its route is the site
root rather than "/index", while preserving existing nested index and extension
handling.

Comment on lines +696 to +705
// Pages and showcase entries have no markdown source to
// copy, so they are excluded here and from llms-full.
writeMarkdownCopies(
collectedDocs.filter((d) => d.hasMarkdown !== false)
);

const fullDocsPool = collectedDocs.filter(
(d) => !excludeFromFullPluginIds.has(d.pluginId)
(d) =>
!excludeFromFullPluginIds.has(d.pluginId) &&
d.hasMarkdown !== false

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the page directive accurate.

These lines exclude standalone pages and showcase entries from .md output. injectHtmlTags still tells every rendered page that appending .md provides a Markdown version. Agents that follow this instruction from a showcase or standalone page receive a URL that this plugin does not generate.

Change the directive to scope Markdown copies to documentation and blog pages. Alternatively, generate copies for these entries.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@plugins/plugin-generate-llms.js` around lines 696 - 705, Update the page
directive generation in injectHtmlTags so it only advertises an appended .md URL
for documentation and blog pages, matching the writeMarkdownCopies filter that
excludes standalone pages and showcase entries; preserve the existing directive
for pages that actually receive Markdown copies.

@Jordy-Baby
Jordy-Baby requested review from keenbeen32 and removed request for nikbhintade August 12, 2026 08:48
@keenbeen32
keenbeen32 merged commit 2adccf8 into main Aug 12, 2026
3 checks passed
@keenbeen32
keenbeen32 deleted the gtm-4211-llms-content branch August 12, 2026 09:07
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