Skip to content

[docs-infra] Create llms.txt #46308

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Jun 18, 2025
Merged

[docs-infra] Create llms.txt #46308

merged 31 commits into from
Jun 18, 2025

Conversation

siriwatknp
Copy link
Member

@siriwatknp siriwatknp commented Jun 10, 2025

Result:

Summary

This PR introduces a new script to generate LLM-optimized documentation by processing MUI component
markdown files and creating standalone documentation with embedded code examples and API references.

What's included

New build script: buildLlmsDocs

  • Location: /scripts/buildLlmsDocs/index.ts
  • Purpose: Generates comprehensive markdown files optimized for LLM consumption
  • Features:
    • Replaces {{"demo": "filename.js"}} syntax with actual code snippets
    • Appends component API documentation (props, slots, CSS classes)
    • Supports non-component documentation (guides, customization docs)
    • Generates root llms.txt based on the project settings
    • Reusable across repositories via --projectSettings parameter

Core processing utilities

  • processComponent.ts: Handles demo replacement in markdown files
  • processApi.ts: Converts API JSON to markdown tables with proper formatting

Key improvements

  • Escapes pipe characters in union types for better markdown readability
  • Properly handles HTML-to-markdown conversion including lists
  • Uses existing API docs builder infrastructure for consistency
  • Supports grep filtering for selective generation

Usage

# Generate all Material UI component docs
pnpm tsx scripts/buildLlmsDocs/index.ts \
  --projectSettings ./packages/api-docs-builder-core/materialUi/projectSettings.ts

# Generate specific components and guides
pnpm tsx scripts/buildLlmsDocs/index.ts \
  --projectSettings ./packages/api-docs-builder-core/materialUi/projectSettings.ts \
  --nonComponentFolders system material/customization \
  --grep "Button|borders"

Output structure

- Components: docs/public/material-ui/react-{component}.md
- Guides: docs/public/material-ui/{category}/{topic}.md
- Index files: docs/public/{directory}/llms.txt

Testing

The script has been tested with Material UI components and documentation. Unit tests are included for the
core processing functions.

The script has been tested with Material UI components and documentation. Unit tests are included for the
core processing functions.

Part of mui/mui-public#423

@siriwatknp siriwatknp changed the title Docs/gen llms [docs-infra] Add a script to generate Material UI llms.txt and docs markdown. Jun 10, 2025
@mui-bot
Copy link

mui-bot commented Jun 10, 2025

Netlify deploy preview

https://deploy-preview-46308--material-ui.netlify.app/

Bundle size report

@mui/materialparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/labparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/systemparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/utilsparsed: 0B(0.00%) gzip: 0B(0.00%)

Show details for 100 more bundles (86 more not shown)

@mui/lab/AdapterDateFnsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/AdapterDayjsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/AdapterLuxonparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/AdapterMomentparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/CalendarPickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/CalendarPickerSkeletonparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/ClockPickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DatePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DateRangePickerDayparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DesktopDatePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DesktopDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DesktopDateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/DesktopTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/LoadingButtonparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/LocalizationProviderparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/Masonryparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/MobileDatePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/MobileDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/MobileDateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/MobileTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/MonthPickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/PickersDayparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/StaticDatePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/StaticDateRangePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/StaticDateTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/StaticTimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TabContextparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TabListparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TabPanelparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/Timelineparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineConnectorparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineContentparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineDotparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineItemparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineOppositeContentparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimelineSeparatorparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TimePickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TreeItemparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/TreeViewparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/useAutocompleteparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/lab/YearPickerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Accordionparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AccordionActionsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AccordionDetailsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AccordionSummaryparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Alertparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AlertTitleparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AppBarparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Autocompleteparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Avatarparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/AvatarGroupparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Backdropparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Badgeparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/BottomNavigationparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/BottomNavigationActionparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Boxparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Breadcrumbsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Buttonparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ButtonBaseparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ButtonGroupparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Cardparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CardActionAreaparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CardActionsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CardContentparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CardHeaderparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CardMediaparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Checkboxparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Chipparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CircularProgressparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ClickAwayListenerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Collapseparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Containerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/CssBaselineparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/DefaultPropsProviderparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Dialogparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/DialogActionsparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/DialogContentparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/DialogContentTextparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/DialogTitleparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Dividerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Drawerparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Fabparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Fadeparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FilledInputparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FormControlparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FormControlLabelparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FormGroupparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FormHelperTextparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/FormLabelparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/GlobalStylesparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Gridparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/GridLegacyparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Growparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/Iconparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/IconButtonparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ImageListparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ImageListItemparsed: 0B(0.00%) gzip: 0B(0.00%)
@mui/material/ImageListItemBarparsed: 0B(0.00%) gzip: 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against 7c9e60e

@siriwatknp siriwatknp added the scope: docs-infra Changes related to the docs-infra product. label Jun 10, 2025
@zannager zannager requested a review from DiegoAndai June 10, 2025 08:39
@siriwatknp siriwatknp removed the request for review from DiegoAndai June 10, 2025 10:34
@siriwatknp siriwatknp marked this pull request as draft June 10, 2025 10:34
@siriwatknp siriwatknp changed the title [docs-infra] Add a script to generate Material UI llms.txt and docs markdown. [WIP][docs-infra] Add a script to generate Material UI llms.txt and docs markdown. Jun 10, 2025
siriwatknp and others added 7 commits June 10, 2025 18:11
The extractMarkdownInfo function was incorrectly capturing "## Usage" as the description
for template README files. Updated the regex to use negative lookahead to exclude headers
and added an additional check to ensure captured text doesn't start with '#'.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@siriwatknp siriwatknp marked this pull request as ready for review June 13, 2025 08:39
Copy link
Contributor

@bharatkashyap bharatkashyap left a comment

Choose a reason for hiding this comment

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

Looks largely good to me! Great effort. Added a couple of comments.

package.json Outdated
@@ -22,7 +22,8 @@
"release:pack": "tsx scripts/releasePack.mts",
"docs:api": "rimraf --glob ./docs/pages/**/api-docs ./docs/pages/**/api && pnpm docs:api:build",
"docs:api:build": "tsx ./scripts/buidApiDocs/index.ts",
"docs:build": "pnpm --filter docs build",
"docs:llms:build": "rimraf --glob ./docs/public/material-ui/ && tsx ./scripts/buildLlmsDocs/index.ts --projectSettings ./packages/api-docs-builder-core/materialUi/projectSettings.ts --nonComponentFolders material/getting-started material/customization material/experimental-api material/guides material/integrations material/migration",
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we add nonComponentFolders as a list on the projectSettings to avoid having to pass a long list of folders in the command?


for (const file of files) {
// Calculate relative path from the baseDir to the file
const relativePath = file.outputPath.startsWith(`${baseDir}/`)
Copy link
Contributor

Choose a reason for hiding this comment

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

We should add absolute paths in the llms.txt (see: https://llms.mui.com/material-ui/7.1.0/llms.txt) so that an AI client is able to directly traverse/fetch content present in the links without needing to understand what the base URL should be

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point, updated.

domain can be specified to the CLI (for older versions), the default is mui.com.

Copy link
Member

@Janpot Janpot Jun 16, 2025

Choose a reason for hiding this comment

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

hard disagree. these docs are not built for a specific domain. e.g. thru are hosted on preview donations. we can make them root-relative if you want. any client consuming these links will have to resolve them, as is quite standard.

Copy link
Contributor

@bharatkashyap bharatkashyap Jun 16, 2025

Choose a reason for hiding this comment

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

Given this is built for LLMs, relying on LLMs to be able to reliably resolve domains is a mistake since we will invite consistent erroneous resolution with no deterministic way of correcting it. Benchmarked against many other llms.txt , all of them contain fully resolved URLs to aid AI, not make it harder for it:

Copy link
Member

Choose a reason for hiding this comment

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

an mcp will have to resolve them before feeding to the llm. you'll want to be able to test tooling against preview builds of our docs.

https://gitbook.com/docs/llms.txt

Copy link
Member

@Janpot Janpot Jun 16, 2025

Choose a reason for hiding this comment

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

My opposition is more because I think relative URLs here would be a mistake, not because it would be hard to do. We could very well do some sort of system prompt engineering in the MCP tools or some programmatic URL resolution in the tool itself, but I don't think we should.

Prompting it to resolve relative links would be unnecessary, the body of llms.txt passes through the mcp, it's trivial to parse and resolve these links and pass the document with resolved links. Relative linking is how the web works. When you follow the links through all your examples, e.g. https://vercel.com/docs/frameworks.md, you'll see that their inner links are relative. And that makes 100% sense, this is how the web works, so any tool that pretends to be able to consume it will need to be able to handle relative linking. i.e. the tool that fetches https://vercel.com/docs/frameworks.md will have to resolve these inner links for the LLM.

again, we have no reliable measure of determining which docs

Sure we do, if we try the chat 5 times with the same prompt and it answers wrong 4 times, we can check that ratio against another version of the docs. If it now answers wrong 2 out of 5 times we have successfully improved the docs.

Anyway, as I said before, if we want to absolute link, what's stopping us from generating correct links for the netlify preview, the url under which will be deployed should be in the environment? You just have to pass it to the CLI. (also should make the whole url configurable, not just the domain, protocol and subdomain matter). I could live with that.

Copy link
Member Author

Choose a reason for hiding this comment

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

@bharatkashyap What do you think about testing with relative links first since it's the default behavior? If we can prove that it's does not work well or is wrong with the MCP you work on, I can add the absolute links in a separate PR.

Copy link
Contributor

@bharatkashyap bharatkashyap Jun 17, 2025

Choose a reason for hiding this comment

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

Anyway, as I said before, if you're really set on absolute linking, what's stopping you from generating correct links for the netlify preview, the url under which will be deployed should be in the environment? You just have to pass it to the CLI. (also should make the whole url configurable, not just the domain, protocol and subdomain matter). I could live with that.

@siriwatknp This is the best option IMO, but I'll try out the llms.txt with relative links in the MCP and report

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, great. I'll merge this with the relative links and I'll help you test it out.

Copy link
Member

Choose a reason for hiding this comment

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

To note that the spec doesn't mention relative links and their reference implementation doesn't seem to support it. It also doesn't seem to support our idea of multiple llms.txt on a single host.

@siriwatknp siriwatknp changed the title [WIP][docs-infra] Add a script to generate Material UI llms.txt and docs markdown. [docs-infra] Add a script to generate Material UI llms.txt and docs markdown. Jun 16, 2025
siriwatknp and others added 7 commits June 16, 2025 09:00
…s.txt

- Add --domain CLI option with default value 'mui.com'
- Update generateLlmsTxt to use absolute URLs instead of relative paths
- Remove unused baseDir parameter from generateLlmsTxt function

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
…projectSettings

Move the nonComponentFolders configuration from command-line argument to projectSettings
for better maintainability and consistency with other project configurations.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Restore the --domain CLI option that was removed in the previous commit.
This allows configuring the domain for absolute URLs in llms.txt files.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
@siriwatknp siriwatknp merged commit 1119e25 into mui:master Jun 18, 2025
20 checks passed
@amerryma
Copy link

A bit late to the party here, but any plans on supporting an llms.txt for Mui X? I've been wanting to feed some better documentation to an LLM for complex things like DataGrid and Charts.

@oliviertassinari oliviertassinari changed the title [docs-infra] Add a script to generate Material UI llms.txt and docs markdown. [docs-infra] Add a script to generate Material UI llms.txt and docs markdown Aug 10, 2025
@oliviertassinari oliviertassinari changed the title [docs-infra] Add a script to generate Material UI llms.txt and docs markdown [docs-infra] Create llms.txt Aug 10, 2025
@oliviertassinari oliviertassinari added type: new feature Expand the scope of the product to solve a new problem. docs Improvements or additions to the documentation. labels Aug 10, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
docs Improvements or additions to the documentation. scope: docs-infra Changes related to the docs-infra product. type: new feature Expand the scope of the product to solve a new problem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants