Add llms.txt and llms-all.txt endpoints for LLM-friendly content#474
Add llms.txt and llms-all.txt endpoints for LLM-friendly content#474SohamJuneja wants to merge 15 commits intojenkinsci:masterfrom
Conversation
…LLM-friendly content
| * <li>{@code {component}.md} - documentation for a single component</li> | ||
| * </ul> | ||
| */ | ||
| public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { |
| * <li>{@code {component}.md} - documentation for a single component</li> | ||
| * </ul> | ||
| */ | ||
| public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { |
|
Thanks for this. Liking the It's not showing any content not already available in |
555693c to
534d7f7
Compare
|
Thanks for the feedback and the homepage additions! Removed the per-component |
|
It'd be good to get some advice on this @SohamJuneja @timja - should |
|
I think llms-all.txt is worth keeping though, it's the file that contains the actual code snippets (Jelly/Java) from each component, which is what an LLM needs to generate correct Jenkins UI code. llms.txt alone is just a table of contents. This follows the llms.txt convention of having an index + a full content file. Waiting for your insights too!! |
There was a problem hiding this comment.
Am I doing something wrong?
llms.txt isn't linking to individual files.
llms-all.txt doesn't have all the content about the design library
This should load all the content from the files and ideally examples into something the llm can use.
I can't find how to load an individual component.
e.g. http://localhost:8080/jenkins/design-library/banner.md returns a 404
llms.txt
# Jenkins Design Library
> A reference library of UI components and patterns for building Jenkins plugin interfaces.
## Components
- App bars: Frames your page and contains your most important actions.
- Banner: Banners are a handy way to display small snippets of text and actions.
- Buttons: Triggers specific actions with a click or tap.
- Cards: Use cards to surface related information and controls to users.
- Checkboxes: Allows users to select one or more items from a list.
- Dialogs: Displays overlay windows for additional information or user input without navigating away.
- Empty States: For when there is no data, no configuration or no plugins installed that support the required feature an empty state can be provided instead.
- File: Enables file upload functionality.
- Inputs: Captures user input through various text or data entry formats.
- Menu: Menus allow you to group similar controls under one roof. They're an effective way to de-clutter your page whilst offering users the actions they need.
- Notifications: Jenkins can display in-page notifications with a simple-to-use JavaScript API.
- Progress: Indicates the completion status of a task or operation.
- Radios: Allows users to select a single option from a group.
- Repeatable list: Displays lists with varying content types within the same container.
- Select: Provides a dropdown for choosing one option from a predefined list.
- Symbols: Jenkins Symbols are an extensive and consistent collection of icons for use in Jenkins and plugins.
- Table: Displays structured data in rows and columns, with support for sorting and badges.
- Toggle switch: Enables users to switch between two states, such as on or off.
- Tooltips: Offers brief, contextual information when hovering over an element.
## Patterns
- Colors: Defines the palette for consistent use of color.
- JavaScript Proxy: Export arbitrary server-side Java object to JavaScript and invoke their methods from JavaScript.
- Layouts: Predefined layout structures and patterns to organize page content.
- Links: Creates navigational connections to internal or external destinations.
- Localization: Ensures texts can be displayed in the user's language.
- Spacing: Defines consistent padding, margins, and gaps between elements.
- Stylesheets: Provides reusable stylesheet principles and standards for maintaining consistency.
- Validation: Ensures user inputs meet specified criteria or rules before submission.
llms-all.txt
# Jenkins Design Library
> A reference library of UI components and patterns for building Jenkins plugin interfaces.
## Components
# App bars
> Frames your page and contains your most important actions.
**Category:** Components
---
# Banner
> Banners are a handy way to display small snippets of text and actions.
**Category:** Components
---
# Buttons
> Triggers specific actions with a click or tap.
**Category:** Components
---
# Cards
> Use cards to surface related information and controls to users.
**Category:** Components
**Since:** 2.479.1
---
# Checkboxes
> Allows users to select one or more items from a list.
**Category:** Components
---
# Dialogs
> Displays overlay windows for additional information or user input without navigating away.
**Category:** Components
**Since:** 2.426.1
---
# Empty States
> For when there is no data, no configuration or no plugins installed that support the required feature an empty state can be provided instead.
**Category:** Components
---
# File
> Enables file upload functionality.
**Category:** Components
---
# Inputs
> Captures user input through various text or data entry formats.
**Category:** Components
---
# Menu
> Menus allow you to group similar controls under one roof. They're an effective way to de-clutter your page whilst offering users the actions they need.
**Category:** Components
**Since:** 2.452.1
---
# Notifications
> Jenkins can display in-page notifications with a simple-to-use JavaScript API.
**Category:** Components
---
# Progress
> Indicates the completion status of a task or operation.
**Category:** Components
---
# Radios
> Allows users to select a single option from a group.
**Category:** Components
---
# Repeatable list
> Displays lists with varying content types within the same container.
**Category:** Components
---
# Select
> Provides a dropdown for choosing one option from a predefined list.
**Category:** Components
---
# Symbols
> Jenkins Symbols are an extensive and consistent collection of icons for use in Jenkins and plugins.
**Category:** Components
---
# Table
> Displays structured data in rows and columns, with support for sorting and badges.
**Category:** Components
---
# Toggle switch
> Enables users to switch between two states, such as on or off.
**Category:** Components
---
# Tooltips
> Offers brief, contextual information when hovering over an element.
**Category:** Components
---
## Patterns
# Colors
> Defines the palette for consistent use of color.
**Category:** Patterns
---
# JavaScript Proxy
> Export arbitrary server-side Java object to JavaScript and invoke their methods from JavaScript.
**Category:** Patterns
---
# Layouts
> Predefined layout structures and patterns to organize page content.
**Category:** Patterns
---
# Links
> Creates navigational connections to internal or external destinations.
**Category:** Patterns
---
# Localization
> Ensures texts can be displayed in the user's language.
**Category:** Patterns
---
# Spacing
> Defines consistent padding, margins, and gaps between elements.
**Category:** Patterns
---
# Stylesheets
> Provides reusable stylesheet principles and standards for maintaining consistency.
**Category:** Patterns
---
# Validation
> Ensures user inputs meet specified criteria or rules before submission.
**Category:** Patterns
---
|
The issue was that code example files are split between the webapp directory and the classpath, and the original implementation only checked one location. |
|
Better, llms.txt now loads to the individual markdown page. But only a couple of them are actually loading content / example above their description. Dialogs, tables and radios have a little bit generally the rest is missing, e.g. cards |
|
The root cause was in how the resource URL was constructed, new URL(base, relPath) uses relative URL resolution which breaks silently for jar: scheme URLs. For components like Cards and Buttons whose snippet files live only in src/main/webapp/, this caused every lookup to fail and fall through to a classpath-only search that could never find them. The fix uses explicit string concatenation instead: new URL(base + componentName + "/" + filename), which works correctly for both file: and jar: scheme URLs. A classloader-root fallback is also added as a safety net. |
|
build is failing |
|
It looks like we will need to run |
|
Are you actually testing this? (it has improved since the last iteration there is a lot more content though) go through each page and make sure at least the majority of the content is there. I got as far as the first page before I found missing content: http://localhost:8080/jenkins/design-library/app-bars.md All the do and don't are missing |
|
This time I tested every single one of the 27 component pages locally by running Jenkins via mvn clean hpi:run -Dskip.npm -Dport=8090 and checking each .md endpoint individually.
|
Can you compare more carefully please? - each iteration is getting better but I don't get past the first page without finding important missing content. |
| import org.kohsuke.accmod.restrictions.NoExternalUse; | ||
|
|
||
| @Restricted(NoExternalUse.class) | ||
| class LlmContent { |
There was a problem hiding this comment.
This isn't workable, better to just commit markdown files.
@janfaracik think its worth trying to generate jelly from markdown or just keep a markdown copy and a jelly version?
There was a problem hiding this comment.
Yeah that's fair, the Jelly-parsing approach technically works but it's fragile. Any new pattern someone adds to a component Jelly file would need another special case in the parser.
Even just building this I ran into a bunch of edge cases while manually checking each page, things like half-encoded tag names in property values, 'br' inside i18n strings causing two sentences to run together, Java generics inside code container spans getting stripped by the tag cleaner, and Colors using j:forEach which makes the Jelly basically unparseable statically. Each one took a while to track down. So I get why this isn't the right long-term approach.
One option, we could use the current implementation as a one-time generation tool to get all the content out, then delete LlmContent.java entirely and just commit the generated .md files directly. That way the content isn't lost but there's no fragile parser living in the codebase.
What do you think?
There was a problem hiding this comment.
yeah give it a go, will need to run it past others of whether we want:
- both committed
- markdown as the master and then generate jelly from it
There was a problem hiding this comment.
-
Where should the .md files live? Either alongside each component's existing resources (src/main/resources/.../AppBars/index.md) or in a dedicated top-level folder like docs/llms/app-bars.md?
-
Should the HTTP endpoints still work and serve these files, or are the committed files enough? If the URLs need to keep working, we still need some Java code.
There was a problem hiding this comment.
- alongside the jelly files I think
- not sure what you mean, the markdown files need to be served
| return null; | ||
| } | ||
|
|
||
| private java.net.URL getPluginResourceBase() { |
timja
left a comment
There was a problem hiding this comment.
The changes themself look good, I've not reviewed every page but I checked a few.
@janfaracik any thoughts on this?
not ideal to have to duplicate it, might be possible to generate the jelly as an alternative?
|
Yeah not ideal. I'll have a play around and see how easy it is to generate Markdown from Jelly. |
|
One thing that might be worth exploring, instead of parsing Jelly source directly, we could fetch the already-rendered HTML of each component page and extract content from that using something like Jsoup with CSS selectors. The tradeoff is it would need a running Jenkins instance to generate the files, but that could be a build step? |

Adds dynamically generated LLM-friendly endpoints to the Design Library, following the llms.txt convention:
/design-library/llms.txt— markdown index listing all components with links to individual .md pages/design-library/llms-all.txt— all component documentation concatenated into a single file/design-library/{component}.md— per-component markdown (e.g./design-library/buttons.md)Content is generated at runtime from the existing UISample extension list, so new components are automatically included with no extra work.
Fixes #473
Testing done
Submitter checklist