feat(seo): config-driven llms.txt generator in seo-static plugin - #4274
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThis PR introduces config-driven ChangesLLMs.txt Generation Feature
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed: one or more packages not found in the registry. 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. Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4274 +/- ##
=======================================
Coverage 99.57% 99.58%
=======================================
Files 31 31
Lines 1182 1200 +18
Branches 340 352 +12
=======================================
+ Hits 1177 1195 +18
Misses 5 5 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds first-class llms.txt generation to the existing seo-static Vite plugin, following the same config-driven pattern as robots.txt, sitemap.xml, and manifest.json, so downstream apps can ship llms.txt via config rather than a static public file.
Changes:
- Add
buildLlmsTxt(llmsConfig, app)builder and emitllms.txtas a production-build asset when enabled. - Add unit tests covering
buildLlmsTxtrendering, null behavior, skipping malformed entries, and fixture rendering. - Extend
test.config.jsfixture with a genericapp.seo.llmsexample used by the tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
src/lib/plugins/seo-static.js |
Implements buildLlmsTxt and emits llms.txt from generateBundle when enabled. |
src/lib/plugins/tests/seo-static.unit.tests.js |
Adds buildLlmsTxt unit tests and updates the plugin emit-count assertion from 3 → 4. |
src/config/defaults/test.config.js |
Adds a generic seo.llms fixture used by the new tests. |
| * @param {object|undefined} llmsConfig - llms configuration object | ||
| * @param {object} app - app-level config (title fallback) | ||
| * @returns {string|null} llms.txt content or null if disabled |
# [2.2.0](v2.1.0...v2.2.0) (2026-07-01) ### Bug Fixes * **auth:** failed login no longer shows a 'success: Signed out' toast ([#4309](#4309)) ([464e022](464e022)), closes [#4305](#4305) [#4305](#4305) * **billing:** nav compute gauge — admin ∞ display + login refresh ([#4260](#4260), [#4261](#4261)) ([#4268](#4268)) ([2e614db](2e614db)) * **billing:** update VProgressLinear snapshots for Vuetify 4.1.0 ([#4257](#4257)) ([549bb39](549bb39)) * **configGuard:** warn-only by default, throw only on opt-in strict flag ([#4263](#4263)) ([f37050f](f37050f)), closes [#4258](#4258) * **core:** center footer version badge + show backend API version ([#4275](#4275)) ([a17795b](a17795b)) * **docs:** left-align /docs home search hero + uncap block trigger width ([#4323](#4323)) ([b701c3d](b701c3d)) * **e2e:** resolve flaky Playwright webServer boot-race ([#4378](#4378)) ([0fc1886](0fc1886)), closes [#4372](#4372) * **invitations:** inert referrals state when public signup is open ([#4306](#4306)) ([b1cb7d5](b1cb7d5)), closes [pierreb-devkit/Node#3833](pierreb-devkit/Node#3833) * **invitations:** pre-P9 UI hardening — revoked status, admin error banner, canonical verifyInvite ([#4293](#4293)) ([d977558](d977558)), closes [#4291](#4291) * **legal:** patch happy-dom Node.prototype.nodeName for DOMPurify 3.4.8 ([#4240](#4240)) ([#4256](#4256)) ([f0b0e41](f0b0e41)) * **skills/update-stack:** switch drift gate scan to git diff (catches missing-locally case) ([#4244](#4244)) ([32bd2d3](32bd2d3)), closes [#4233](#4233) * **theme:** re-apply OS theme post-hydration when dark='auto' (prerender light-lock) ([#4262](#4262)) ([9aa74cf](9aa74cf)), closes [#4230](#4230) * **ui:** invitations/org surfaces polish — app-level nudge, toolbar slot, card rhythm ([#4301](#4301)) ([d203d84](d203d84)), closes [#toolbar](https://github.com/pierreb-devkit/Vue/issues/toolbar) [#toolbar](https://github.com/pierreb-devkit/Vue/issues/toolbar) * Vue low-severity security hardening bundle (tabnabbing, href scheme, console creds, headers, npm ci, stale key) ([#4316](#4316)) ([9b21450](9b21450)) ### Features * **admin:** activation-aware tabs, readiness badge, activity search, invite copy-link ([#4308](#4308)) ([da419ac](da419ac)), closes [#4295](#4295) [#4297](#4297) [pierreb-devkit/Node#3836](pierreb-devkit/Node#3836) [#4296](#4296) [pierreb-devkit/Node#3834](pierreb-devkit/Node#3834) * **app/router:** add registerDownstreamRoutes extension hook for downstream route injection ([#4242](#4242)) ([54358f0](54358f0)) * **auth:** add beta seat getters to auth store ([#4229](#4229)) ([0560aab](0560aab)) * **auth:** reframe post-signup org-setup step as friendly workspace setup ([#4373](#4373)) ([27ec893](27ec893)) * **billing:** grouped feature sections + plan inheritance on pricing cards ([#4382](#4382)) ([ded622b](ded622b)) * **billing:** surface capacity equivalences on the nav compute gauge ([#4350](#4350)) ([dfeef01](dfeef01)), closes [#4349](#4349) * **configGuard:** block dev-host/port leak into production config ([#4235](#4235)) ([10c3f17](10c3f17)), closes [#949](#949) [pierreb-projects/infra#38](https://github.com/pierreb-projects/infra/issues/38) [#949](#949) [trawl_vue#949](https://github.com/trawl_vue/issues/949) * **core+home+tasks:** promote 4 generic improvements from trawl downstream ([#4239](#4239)) ([a00caa5](a00caa5)) * **docs:** cross-guide #anchor link rewrite in the article renderer ([#4343](#4343)) ([a89331c](a89331c)), closes [#anchor](https://github.com/pierreb-devkit/Vue/issues/anchor) [#4334](#4334) * **docs:** in-app docs module (/docs) + docs-aware SEO (flag-gated, default off) ([#4319](#4319)) ([32e3948](32e3948)), closes [#1](#1) [#2](#2) [#3](#3) [#4](#4) [#5](#5) [#6](#6) [#7](#7) [#8](#8) [#9](#9) [#11](#11) [#4310](#4310) * **docs:** link the OpenAPI reference from the docs nav ([#4330](#4330)) ([1b5c8dd](1b5c8dd)) * **footer:** display app version from DEVKIT_VUE_app_version build-arg ([#4259](#4259)) ([#4267](#4267)) ([14fe314](14fe314)) * **home+auth:** promote external-link safety + org-setup error UX from trawl ([#4237](#4237)) ([8e0be0f](8e0be0f)), closes [pierreb-projects/infra#38](https://github.com/pierreb-projects/infra/issues/38) * **invitations:** referrals summary + rewards placeholder on account view (P8b) ([#4292](#4292)) ([1c0db9d](1c0db9d)), closes [#5](#5) [#4282](#4282) * **invitations:** standalone Vue module + account Referrals tab + router gap-fixes (P6) ([#4289](#4289)) ([4366fa2](4366fa2)) * **organizations:** add-member UI + pending-invitations list + accept (P5b) ([#4288](#4288)) ([96b5b14](96b5b14)), closes [#4281](#4281) * **organizations:** owner_add lifecycle surfaces + signup error detail ([#4307](#4307)) ([e70dbf7](e70dbf7)), closes [pierreb-devkit/Node#3831](pierreb-devkit/Node#3831) [pierreb-devkit/Node#3832](pierreb-devkit/Node#3832) * **seo:** config-driven llms.txt generator in seo-static plugin ([#4274](#4274)) ([e9cedad](e9cedad)), closes [#4269](#4269) * **seo:** per-route self-referential canonical + og:url ([#4338](#4338)) ([94234ff](94234ff)) * **skills/update-stack:** drop ledger condition + auto-derive scan list ([#4232](#4232)) ([7be1220](7be1220)), closes [#4231](#4231) [infra#37](https://github.com/infra/issues/37)
Closes #4269
What
Adds a generic, config-driven
buildLlmsTxt(llmsConfig, app)builder tosrc/lib/plugins/seo-static.js, mirroringbuildRobotsTxt/buildSitemapXml/buildManifestJson, and emitsllms.txtfrom thegenerateBundlehook (prod build only, gated on config).Why
llms.txt is the emerging LLM/answer-engine site entry point (AEO). Keeping it in the stack plugin lets every downstream project ship its own
llms.txtfrom config, consistent with how robots/sitemap/manifest are already generated — instead of a hand-maintainedpublic/llms.txt.Rendering
# title(fallbackapp.title→'App'),> summary,intro, per-section## titlewith items as- [label](url): note(link) or- label: note(bullet), thenbodypassthrough; single trailing newline. Sections without atitleand items without alabelare skipped (noundefinedin output);appis null-guarded.Tests
src/lib/plugins/tests/seo-static.unit.tests.js—describe('buildLlmsTxt'): disabled→null, undefined→null, title fallback, summary/intro, link-vs-bullet + note, body passthrough + trailing newline,app=undefinedfallback, malformed-entry skipping,testConfigfixture render. Plugin emit-count test updated 3→4. Generic — zero project-specific strings.Scope
seo.llmscontent +/update-stackpropagation land on GTM driver C1-1 (board comes-io/projects/3) incomes-io/trawl_vue.🤖 First run of the "GTM Engineer generates the issue → the dev flow dépiles it" pattern. Driver: comes-io/projects/3 item C1-1. Plan:
infra/docs/superpowers/plans/2026-06-08-trawl-llms-txt.md. Draft — human merge gate (do not self-merge).Summary by CodeRabbit
New Features
llms.txtfile during production builds with configurable optionsTests