Improve Leadtype docs pipeline readability#28
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughPR implements optional docs.config.* discovery via jiti in the CLI, validates and merges product+groups metadata (CLI overrides supported), splits docs groups into docs-site and package-docs, adds search and MDX/TOC documentation pages and example routes, migrates the bundle docs route to package-docs with AGENTS.md bundling guidance, updates generated route tree and eval fixtures, and adds/adjusts tests and README/docs text. ChangesConfig-Driven Docs Pipeline & Documentation Restructuring
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 104f79f801
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| } | ||
|
|
||
| return { | ||
| groups: await inferGroups(docsDir), |
There was a problem hiding this comment.
Defer fallback group inference until after filters
When no docs.config.* exists, this scans every MDX file in the original docs directory before createSourceMirror applies --include/--exclude, and the result is then discarded because runGenerateCommand re-infers groups from sourceMirror.docsDir. In a filtered run, an excluded MDX file with malformed frontmatter (or another read/parse problem) can now fail leadtype generate --include ... before the filter is honored, even though the generated subset would be valid.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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 `@apps/example/src/routes/docs/build/add-search.tsx`:
- Around line 7-14: Define a shared path constant (e.g., const PATH =
"/docs/build/add-search" as const) and use it in both createFileRoute(PATH) and
createDocsHead(PATH) to avoid duplicating the literal; then convert the
component declaration function AddSearchRoute to a short arrow const (e.g.,
const AddSearchRoute = () => <AddSearchDoc />) so Route, AddSearchRoute,
createFileRoute, and createDocsHead reference the single PATH constant and
follow the arrow-function guideline.
In `@apps/example/src/routes/docs/build/render-mdx-and-toc.tsx`:
- Around line 7-14: Extract the repeated path literal into a single constant
(e.g., ROUTE_PATH = "/docs/build/render-mdx-and-toc" as const) and use that
constant in the createFileRoute call and in createDocsHead to avoid drift; also
convert the short component function RenderMdxAndTocRoute to an arrow function
(const RenderMdxAndTocRoute = () => <RenderMdxAndTocDoc />) so it follows the
callback/short-function style, keeping references to Route, createFileRoute,
createDocsHead, RenderMdxAndTocRoute, and RenderMdxAndTocDoc intact.
In `@packages/leadtype/src/cli/generate.ts`:
- Around line 328-330: The Jiti instance created via createJiti(import.meta.url)
is using its default runtime module cache, causing stale configs on repeated
runGenerateCommand() invocations; update the createJiti call (the symbol
createJiti) to disable Jiti's module cache by passing moduleCache: false (and
optionally fsCache: false) so that imports loaded via jiti.import(configPath,
...) always read a fresh config per invocation.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro
Run ID: b1a82564-d391-4e41-86fe-715f682e2b69
⛔ Files ignored due to path filters (5)
apps/example/src/generated/agent-readability.jsonis excluded by!**/generated/**apps/example/src/generated/docs-nav.jsonis excluded by!**/generated/**apps/example/src/generated/docs-search-content.jsonis excluded by!**/generated/**apps/example/src/generated/docs-search-index.jsonis excluded by!**/generated/**bun.lockis excluded by!**/*.lock
📒 Files selected for processing (26)
README.mdapps/example/src/routeTree.gen.tsapps/example/src/routes/docs/build/add-search.tsxapps/example/src/routes/docs/build/render-mdx-and-toc.tsxdocs/authoring/components.mdxdocs/authoring/frontmatter.mdxdocs/build/add-search.mdxdocs/build/bundle-package-docs.mdxdocs/build/connect-docs-site.mdxdocs/build/optimize-docs-for-agents.mdxdocs/build/render-mdx-and-toc.mdxdocs/build/validate-in-ci.mdxdocs/docs.config.tsdocs/how-it-works.mdxdocs/index.mdxdocs/methodology.mdxdocs/quickstart.mdxdocs/reference/cli.mdxdocs/reference/llm.mdxpackages/leadtype/README.mdpackages/leadtype/package.jsonpackages/leadtype/scripts/generate-docs.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/cli.tspackages/leadtype/src/cli/generate.tspackages/leadtype/src/llm/llm.ts
💤 Files with no reviewable changes (1)
- packages/leadtype/src/cli.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/leadtype/scripts/generate-docs.tsapps/example/src/routes/docs/build/add-search.tsxapps/example/src/routes/docs/build/render-mdx-and-toc.tsxdocs/docs.config.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/cli/generate.tsapps/example/src/routeTree.gen.tspackages/leadtype/src/llm/llm.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code
Files:
packages/leadtype/scripts/generate-docs.tsapps/example/src/routes/docs/build/add-search.tsxapps/example/src/routes/docs/build/render-mdx-and-toc.tsxdocs/docs.config.tspackages/leadtype/src/cli.test.tspackages/leadtype/src/cli/generate.tsapps/example/src/routeTree.gen.tspackages/leadtype/src/llm/llm.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx}: Use function components over class components in React
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use thekeyprop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props
Don't define components inside other components
AvoiddangerouslySetInnerHTMLunless absolutely necessary
Use proper image components (e.g., Next.js<Image>) over<img>tags
Use Next.js<Image>component for images
Usenext/heador App Router metadata API for head elements in Next.js
Use Server Components for async data fetching instead of async Client Components in Next.js
Use ref as a prop instead ofReact.forwardRefin React 19+
Files:
apps/example/src/routes/docs/build/add-search.tsxapps/example/src/routes/docs/build/render-mdx-and-toc.tsx
**/*.{jsx,tsx,html}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx,html}: Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, use semantic elements instead of divs with roles
Addrel="noopener"when usingtarget="_blank"on links
Files:
apps/example/src/routes/docs/build/add-search.tsxapps/example/src/routes/docs/build/render-mdx-and-toc.tsx
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions insideit()ortest()blocks
Avoid done callbacks in async tests - use async/await instead
Don't use.onlyor.skipin committed code
Keep test suites reasonably flat - avoid excessivedescribenesting
Files:
packages/leadtype/src/cli.test.ts
🪛 LanguageTool
docs/quickstart.mdx
[grammar] ~15-~15: Use a hyphen to join words.
Context: ...ode="install" /> leadtype ships a CLI plus focused library entry points. Start...
(QB_NEW_EN_HYPHEN)
[grammar] ~15-~15: Use a hyphen to join words.
Context: ...install" /> leadtype ships a CLI plus focused library entry points. Start with...
(QB_NEW_EN_HYPHEN)
docs/build/add-search.mdx
[style] ~95-~95: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ed JSON bodies. - getClientIdentifier to read common proxy IP headers. - `create...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
docs/build/optimize-docs-for-agents.mdx
[style] ~203-~203: To form a complete sentence, be sure to include a subject or ‘there’.
Context: ..., must-revalidate. readMarkdownFile` may be sync or async. In Node/Bun, read fro...
(MISSING_IT_THERE)
[style] ~203-~203: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ..., fetch from KV/R2 or an asset binding. In Vercel Edge, fetch from the deployment'...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
docs/build/connect-docs-site.mdx
[uncategorized] ~189-~189: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... — hosted routing index with page-level markdown links. - public/llms-full.txt — all g...
(MARKDOWN_NNP)
[uncategorized] ~190-~190: Did you mean the formatting language “Markdown” (= proper noun)?
Context: ... public/llms-full.txt — all generated markdown docs in one fallback file. - `public/do...
(MARKDOWN_NNP)
🔍 Remote MCP
Excellent! Now I have comprehensive information about jiti. Let me search for additional context about the TanStack Router changes and docs configuration patterns that are relevant to this PR:Perfect! I have gathered sufficient context about the key technical components of this PR. Let me compile the additional context findings:
Additional Context for PR #28 Review
Key Technical Dependency: Jiti Library
Jiti (version ^2.7.0) provides seamless TypeScript and ESM syntax support for Node.js with seamless interoperability between ESM and CommonJS. This new dependency is critical to the PR's objective of automatically loading docs.config.{ts,js,mjs,cjs} files at runtime.
Configuration Loading Capabilities:
Jiti is a tool that lets you run TypeScript files directly in Node.js without compiling them first. It transforms TypeScript code, resolves ES modules, loads JSON files, and caches everything intelligently.
Performance Characteristics:
Jiti provides filesystem caching that significantly improves startup performance—cached loads can be over 16 times faster than uncached versions, and in real applications with multiple TypeScript files, this can turn a 5-second startup time into a 300-millisecond startup time.
Industry Adoption:
There are 2394 projects in the npm registry using jiti, and the UnJS team built this lightweight loader, and it now powers major projects like Nuxt, Docusaurus, Tailwind CSS, and ESLint with over 60 million monthly downloads.
TanStack Router File-Based Routing Context
The PR adds new documentation routes using TanStack Router's file-based routing. When using TanStack Router's file-based routing through one of the supported bundlers, the plugin automatically generates route configuration through the bundler's dev and build processes.
The routeTree.gen.ts file is automatically generated when the development server runs and contains the generated route tree along with TypeScript utilities that enable type-safety. The changes to apps/example/src/routeTree.gen.ts in this PR reflect the addition of new documentation pages and are expected to be auto-generated, not manually maintained.
MDX Integration:
TanStack Router supports importing MDX files directly as route components, allowing developers to use the createLazyFileRoute function to import .mdx files as page components.
Configuration Validation Patterns
The PR implements configuration loading with validation. Docusaurus uses jiti with configuration options like cache: true for transpilation caching, requireCache: false to bypass Node.js runtime caching (similar to "import-fresh"), and interopDefault: true to normalize return values across CJS/ESM/TS modules.
🔇 Additional comments (16)
packages/leadtype/src/llm/llm.ts (1)
1012-1015: Comment update is accurate and clearer.The revised wording matches the offline/package-bundle behavior and improves intent clarity without changing behavior.
packages/leadtype/package.json (1)
97-97: Dependency addition is aligned with the feature goal.Adding
jitihere is consistent with the new docs config auto-loading behavior described for this PR.docs/methodology.mdx (1)
20-20: Positioning text is clear and consistent.This revision cleanly reflects the current artifact model (
llms-full.txtfallback + optional bundledAGENTS.md).docs/how-it-works.mdx (1)
68-69: Bundle-mode guidance is internally consistent.The updated artifact description, audience flow, and consumer pattern all align with the package-bundled offline docs behavior.
Also applies to: 105-105, 109-109
docs/index.mdx (1)
3-3: Landing-page copy updates are strong and cohesive.The revised intro, diagram text, and path cards clearly communicate the generated artifacts and offline package workflow.
Also applies to: 9-9, 22-22, 34-35, 38-50, 61-65
docs/build/optimize-docs-for-agents.mdx (1)
4-4: Middleware section rewrite is clear and practical.The consolidated example improves readability while preserving the important runtime behaviors for discovery and markdown responses.
Also applies to: 65-67, 70-143, 194-194, 203-203
docs/build/render-mdx-and-toc.mdx (1)
1-95: Great addition—this closes an important docs gap.The page gives actionable guidance for keeping rendered heading IDs and generated TOC data in sync.
docs/reference/llm.mdx (1)
300-301: Reference updates are accurate and well aligned.The revised
generateAgentsMddescription and TOC cross-linking match the new docs structure and usage model.Also applies to: 381-382
docs/authoring/components.mdx (1)
30-30: Great docs boundary + artifact wording update.These edits clearly separate docs-app runtime concerns from leadtype conversion concerns and keep output-path terminology consistent.
Also applies to: 142-142
packages/leadtype/README.md (1)
6-6: Docs output paths and bundle semantics are now much clearer.The hosted/bundled split, root
llms-full.txtfallback, and tarball expectations are documented consistently.Also applies to: 24-25, 35-35, 45-45, 70-71, 81-81
packages/leadtype/scripts/generate-docs.ts (1)
49-51: Comment clarification is accurate and useful.Nice improvement to explain why bundled
AGENTS.mdlinks remain valid after install without network fetches.README.md (1)
10-10: README messaging is consistent with the updated pipeline model.The output artifact descriptions and next-step links are coherent and easy to follow.
Also applies to: 31-31, 53-53, 61-63
docs/quickstart.mdx (1)
3-3: Quickstart flow is much clearer and better staged.The revised sequence (generate once → inspect artifacts → pick next integration path) is concise and actionable.
Also applies to: 9-9, 15-15, 33-33, 35-35, 41-41, 44-44, 61-61, 63-63, 65-71, 75-77, 80-82, 85-87, 90-92
docs/build/validate-in-ci.mdx (1)
4-4: Group reassignment looks correct.Using
docs-sitehere aligns this page with the updated build-docs grouping.docs/build/connect-docs-site.mdx (1)
167-171: ⚡ Quick winNo issues found. The
baseUrlparameter is optional (baseUrl?: string) in theResolveDocsNavigationConfigtype definition, so the documentation example is correct and will type-check. Both passingbaseUrl(as in the docs) and omitting it (as in the implementation) are valid uses of the API.> Likely an incorrect or invalid review comment.apps/example/src/routeTree.gen.ts (1)
32-36: Generated route tree updates are internally consistent.Both new docs routes are correctly imported, instantiated, added to route/type registries, module augmentation, and
/docschild wiring. No correctness gaps found in these changes.Also applies to: 145-150, 169-173, 228-232, 260-264, 295-299, 331-335, 363-367, 397-401, 566-572, 594-600, 660-664, 682-687
| export const Route = createFileRoute("/docs/build/add-search")({ | ||
| component: AddSearchRoute, | ||
| head: () => createDocsHead("/docs/build/add-search"), | ||
| }); | ||
|
|
||
| function AddSearchRoute() { | ||
| return <AddSearchDoc />; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
Use a shared route constant and arrow-form short component here as well.
Line 7 and Line 9 repeat the route path; centralize it to avoid accidental divergence. Line 12 should follow the short-function arrow guideline.
♻️ Proposed refactor
+const ROUTE_PATH = "/docs/build/add-search" as const;
+
-export const Route = createFileRoute("/docs/build/add-search")({
+export const Route = createFileRoute(ROUTE_PATH)({
component: AddSearchRoute,
- head: () => createDocsHead("/docs/build/add-search"),
+ head: () => createDocsHead(ROUTE_PATH),
});
-function AddSearchRoute() {
- return <AddSearchDoc />;
-}
+const AddSearchRoute = () => <AddSearchDoc />;As per coding guidelines “Use arrow functions for callbacks and short functions” and “Use const assertions (as const) for immutable values and literal types”.
🤖 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 `@apps/example/src/routes/docs/build/add-search.tsx` around lines 7 - 14,
Define a shared path constant (e.g., const PATH = "/docs/build/add-search" as
const) and use it in both createFileRoute(PATH) and createDocsHead(PATH) to
avoid duplicating the literal; then convert the component declaration function
AddSearchRoute to a short arrow const (e.g., const AddSearchRoute = () =>
<AddSearchDoc />) so Route, AddSearchRoute, createFileRoute, and createDocsHead
reference the single PATH constant and follow the arrow-function guideline.
| export const Route = createFileRoute("/docs/build/render-mdx-and-toc")({ | ||
| component: RenderMdxAndTocRoute, | ||
| head: () => createDocsHead("/docs/build/render-mdx-and-toc"), | ||
| }); | ||
|
|
||
| function RenderMdxAndTocRoute() { | ||
| return <RenderMdxAndTocDoc />; | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
Extract one ROUTE_PATH constant and switch the short component to an arrow function.
Line 7 and Line 9 duplicate the same path literal; centralizing it prevents route/head drift. Line 12 can follow the short-function arrow style.
♻️ Proposed refactor
+const ROUTE_PATH = "/docs/build/render-mdx-and-toc" as const;
+
-export const Route = createFileRoute("/docs/build/render-mdx-and-toc")({
+export const Route = createFileRoute(ROUTE_PATH)({
component: RenderMdxAndTocRoute,
- head: () => createDocsHead("/docs/build/render-mdx-and-toc"),
+ head: () => createDocsHead(ROUTE_PATH),
});
-function RenderMdxAndTocRoute() {
- return <RenderMdxAndTocDoc />;
-}
+const RenderMdxAndTocRoute = () => <RenderMdxAndTocDoc />;As per coding guidelines “Use arrow functions for callbacks and short functions” and “Use const assertions (as const) for immutable values and literal types”.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| export const Route = createFileRoute("/docs/build/render-mdx-and-toc")({ | |
| component: RenderMdxAndTocRoute, | |
| head: () => createDocsHead("/docs/build/render-mdx-and-toc"), | |
| }); | |
| function RenderMdxAndTocRoute() { | |
| return <RenderMdxAndTocDoc />; | |
| } | |
| const ROUTE_PATH = "/docs/build/render-mdx-and-toc" as const; | |
| export const Route = createFileRoute(ROUTE_PATH)({ | |
| component: RenderMdxAndTocRoute, | |
| head: () => createDocsHead(ROUTE_PATH), | |
| }); | |
| const RenderMdxAndTocRoute = () => <RenderMdxAndTocDoc />; |
🤖 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 `@apps/example/src/routes/docs/build/render-mdx-and-toc.tsx` around lines 7 -
14, Extract the repeated path literal into a single constant (e.g., ROUTE_PATH =
"/docs/build/render-mdx-and-toc" as const) and use that constant in the
createFileRoute call and in createDocsHead to avoid drift; also convert the
short component function RenderMdxAndTocRoute to an arrow function (const
RenderMdxAndTocRoute = () => <RenderMdxAndTocDoc />) so it follows the
callback/short-function style, keeping references to Route, createFileRoute,
createDocsHead, RenderMdxAndTocRoute, and RenderMdxAndTocDoc intact.
| function validateProductInfo(value: unknown): ProductInfo | undefined { | ||
| if (!isPlainRecord(value)) { | ||
| return; | ||
| } | ||
| if (typeof value.name !== "string" || typeof value.summary !== "string") { | ||
| return; | ||
| } | ||
| return value as ProductInfo; | ||
| } | ||
|
|
||
| function validateDocsGroups(value: unknown): DocsGroup[] | undefined { | ||
| if (!Array.isArray(value)) { | ||
| return; | ||
| } | ||
| for (const group of value) { | ||
| if (!isPlainRecord(group)) { | ||
| return; | ||
| } | ||
| if (typeof group.slug !== "string" || typeof group.title !== "string") { | ||
| return; | ||
| } | ||
| if ( | ||
| group.children !== undefined && | ||
| validateDocsGroups(group.children) === undefined | ||
| ) { | ||
| return; | ||
| } | ||
| } | ||
| return value as DocsGroup[]; | ||
| } | ||
|
|
||
| function validateDocsConfig(value: unknown, configPath: string): DocsConfig { | ||
| if (!isPlainRecord(value)) { | ||
| throw new Error(`docs config at "${configPath}" must export an object`); | ||
| } | ||
| const product = validateProductInfo(value.product); | ||
| if (!product) { | ||
| throw new Error( | ||
| `docs config at "${configPath}" must export product.name and product.summary` | ||
| ); | ||
| } | ||
| const groups = validateDocsGroups(value.groups); | ||
| if (!groups) { | ||
| throw new Error( | ||
| `docs config at "${configPath}" must export groups as an array of { slug, title } entries` | ||
| ); | ||
| } | ||
| return { groups, product }; | ||
| } |
There was a problem hiding this comment.
Validate the full config shape before treating it as DocsConfig.
This only checks the required minimum keys and then casts the original input. A config with malformed optional fields like product.bestStartingPoints, product.bullets, product.agentGuidance, or group.description will still pass here and fail later in generation instead of producing the clear config-load error this PR is meant to add. Please either validate those optional fields too or construct sanitized ProductInfo/DocsGroup objects instead of returning value as ....
As per coding guidelines, "Leverage TypeScript's type narrowing instead of type assertions."
- Move bundle guide to /docs/package-docs/bundle so URL matches sidebar group - Add ProductInfo TypeTable to llm reference - Dedupe middleware listing in optimize-docs-for-agents - Add apps/example callout to quickstart - Fix index card label and update evals/tests for the new path
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
docs/reference/cli.mdx (1)
106-113:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winBroaden custom-script guidance to all supported config extensions.
Line 108 currently implies TS-only (
docs.config.ts), but this page documents support fordocs.config.js|mjs|cjstoo. Align this section so JS-config users aren’t sent down the wrong path.✏️ Suggested wording update
- Custom build scripts do not auto-discover config. Import `docs.config.ts` directly and pass the values to the lower-level APIs: + Custom build scripts do not auto-discover config. Import your docs config module directly (`docs.config.ts`, `docs.config.js`, `docs.config.mjs`, or `docs.config.cjs`) and pass the values to the lower-level APIs:🤖 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 `@docs/reference/cli.mdx` around lines 106 - 113, The documentation currently suggests importing docs.config.ts specifically; update the "Custom script config" section to state that custom build scripts can import the docs config using any supported extension (docs.config.ts, .js, .mjs, .cjs) and pass the imported object to the lower-level APIs (e.g., generateLlmsTxt). Replace the hardcoded TypeScript example text to indicate "import your docs.config (TS or JS: .ts, .js, .mjs, .cjs) and pass the values to generateLlmsTxt" so JS-config users are covered.
🤖 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 `@packages/leadtype/src/cli.test.ts`:
- Around line 221-437: The test suite only covers docs.config.ts but the feature
auto-discovers docs.config.js|mjs|cjs as well; add a parameterized test that
iterates the four extensions (ts, js, mjs, cjs) and for each creates
docs/docs.config.<ext> with the same exported default object, then repeat the
assertions from the existing "loads docs.config.ts for product metadata and
group order" test (use the same helpers: createTempDir, writeFile, writeMdxPage,
runCli, createCapture) to verify product fields, group order, and generated
llms.txt output; locate and mirror the logic in the existing test case in
cli.test.ts to keep behavior identical and only vary the filename extension.
---
Outside diff comments:
In `@docs/reference/cli.mdx`:
- Around line 106-113: The documentation currently suggests importing
docs.config.ts specifically; update the "Custom script config" section to state
that custom build scripts can import the docs config using any supported
extension (docs.config.ts, .js, .mjs, .cjs) and pass the imported object to the
lower-level APIs (e.g., generateLlmsTxt). Replace the hardcoded TypeScript
example text to indicate "import your docs.config (TS or JS: .ts, .js, .mjs,
.cjs) and pass the values to generateLlmsTxt" so JS-config users are covered.
🪄 Autofix (Beta)
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: ASSERTIVE
Plan: Pro
Run ID: 9f716d0c-d956-4aad-b391-3b3bd3096bbd
⛔ Files ignored due to path filters (4)
apps/example/src/generated/agent-readability.jsonis excluded by!**/generated/**apps/example/src/generated/docs-nav.jsonis excluded by!**/generated/**apps/example/src/generated/docs-search-content.jsonis excluded by!**/generated/**apps/example/src/generated/docs-search-index.jsonis excluded by!**/generated/**
📒 Files selected for processing (17)
README.mdapps/example/src/routeTree.gen.tsapps/example/src/routes/docs/build/bundle-package-docs.tsxapps/example/src/routes/docs/package-docs/bundle.tsxdocs/build/optimize-docs-for-agents.mdxdocs/docs.config.tsdocs/index.mdxdocs/package-docs/bundle.mdxdocs/quickstart.mdxdocs/reference/cli.mdxdocs/reference/evals.mdxdocs/reference/llm.mdxevals/evals/bundle-own-docs/EVAL.tsevals/lib/llms-variants.tsevals/llms/cross-group-agent-flows/expected.jsonpackages/leadtype/README.mdpackages/leadtype/src/cli.test.ts
💤 Files with no reviewable changes (1)
- apps/example/src/routes/docs/build/bundle-package-docs.tsx
📜 Review details
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
apps/example/src/routes/docs/package-docs/bundle.tsxevals/evals/bundle-own-docs/EVAL.tsevals/lib/llms-variants.tsdocs/docs.config.tspackages/leadtype/src/cli.test.tsapps/example/src/routeTree.gen.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code
Files:
apps/example/src/routes/docs/package-docs/bundle.tsxevals/evals/bundle-own-docs/EVAL.tsevals/lib/llms-variants.tsdocs/docs.config.tspackages/leadtype/src/cli.test.tsapps/example/src/routeTree.gen.ts
**/*.{jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx}: Use function components over class components in React
Call hooks at the top level only, never conditionally
Specify all dependencies in hook dependency arrays correctly
Use thekeyprop for elements in iterables (prefer unique IDs over array indices)
Nest children between opening and closing tags instead of passing as props
Don't define components inside other components
AvoiddangerouslySetInnerHTMLunless absolutely necessary
Use proper image components (e.g., Next.js<Image>) over<img>tags
Use Next.js<Image>component for images
Usenext/heador App Router metadata API for head elements in Next.js
Use Server Components for async data fetching instead of async Client Components in Next.js
Use ref as a prop instead ofReact.forwardRefin React 19+
Files:
apps/example/src/routes/docs/package-docs/bundle.tsx
**/*.{jsx,tsx,html}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{jsx,tsx,html}: Use semantic HTML and ARIA attributes for accessibility: provide meaningful alt text for images, use proper heading hierarchy, add labels for form inputs, include keyboard event handlers alongside mouse events, use semantic elements instead of divs with roles
Addrel="noopener"when usingtarget="_blank"on links
Files:
apps/example/src/routes/docs/package-docs/bundle.tsx
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{test,spec}.{js,ts,jsx,tsx}: Write assertions insideit()ortest()blocks
Avoid done callbacks in async tests - use async/await instead
Don't use.onlyor.skipin committed code
Keep test suites reasonably flat - avoid excessivedescribenesting
Files:
packages/leadtype/src/cli.test.ts
🪛 LanguageTool
docs/build/optimize-docs-for-agents.mdx
[style] ~203-~203: To form a complete sentence, be sure to include a subject or ‘there’.
Context: ..., must-revalidate. readMarkdownFile` may be sync or async. In Node/Bun, read fro...
(MISSING_IT_THERE)
[style] ~203-~203: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ..., fetch from KV/R2 or an asset binding. In Vercel Edge, fetch from the deployment'...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~222-~222: You have already used ‘right’ in nearby sentences. Consider using an alternative word to let your writing stand out and sound more polished.
Context: ...ew, staging, and prod all advertise the right URLs without per-environment config. T...
(REP_RIGHT)
docs/quickstart.mdx
[grammar] ~15-~15: Use a hyphen to join words.
Context: ...ode="install" /> leadtype ships a CLI plus focused library entry points. Start...
(QB_NEW_EN_HYPHEN)
[grammar] ~15-~15: Use a hyphen to join words.
Context: ...install" /> leadtype ships a CLI plus focused library entry points. Start with...
(QB_NEW_EN_HYPHEN)
🔍 Remote MCP Context7
Additional context relevant to reviewing PR #28
-
Jiti (new dependency /unjs/jiti) supports runtime loading of TS/JS/ESM configs with options useful to this PR: createJiti(importMetaUrl, { fsCache/moduleCache/interopDefault, extensions, tryNative }), and provides jiti.import(id, { default?, try?, conditions?, parentURL? }) plus evalModule. Filesystem caching and interopDefault are enabled by default in examples — relevant for loading docs.config.{ts,js,mjs,cjs} reliably and fast.
-
TanStack Router file-based routing (library /tanstack/router) documents createFileRoute and generated route trees: route files export a Route constant created via createFileRoute(path)({...}), are discovered/typed by the router bundler/CLI (routeTree.gen.ts is auto-generated), and MDX files can be used as route components. This matches the PR changes that add/remove createFileRoute modules and update apps/example/src/routeTree.gen.ts.
Sources used:
- Context7 docs for jiti (resolve + docs): Context7_resolve-library-id → Context7_query_docs for /unjs/jiti
- Context7 docs for TanStack Router (resolve + docs): Context7_resolve-library-id → Context7_query_docs for /tanstack/router
🔇 Additional comments (27)
docs/reference/evals.mdx (1)
20-21: LGTM!The updated group count accurately reflects the five groups now present in the corpus (Get Started, Authoring, Build, Ship Package Docs, and Reference), aligning with the package-docs group addition in this PR.
docs/reference/llm.mdx (4)
47-79: LGTM!The new
ProductInfosection clearly documents the sharedproductobject shape with well-structured property definitions. The TypeTable component usage provides a clean, scannable reference for the configuration API.
333-333: LGTM!The updated wording correctly emphasizes the technical implementation (relative filesystem links) without prescribing specific AI tools, making the documentation more accurate and future-proof.
377-377: LGTM!The link correctly points to the new bundle documentation location at
/docs/package-docs/bundle, matching the route restructuring in this PR.
414-414: LGTM!The updated reference correctly points to the new MDX rendering and TOC documentation page, aligning with the docs restructuring in this PR.
README.md (4)
10-10: LGTM!The diagram correctly shows
llms-full.txtat the top level of the public directory, matching the revised output structure where it serves as a root-level fallback rather than topic-scoped bundles.
31-31: LGTM!The updated description effectively emphasizes the version-matching benefit of bundled docs, clarifying that consumers get version-matched documentation after install.
53-53: LGTM!The output description accurately reflects the new structure with
llms-full.txtat the top level and correctly explains that bundled docs use relative links that remain valid after npm install.
61-62: LGTM!The documentation links are correctly updated to match the new docs structure, with the bundle guide now pointing to
/docs/package-docs/bundleand clearer link titles for discoverability.packages/leadtype/README.md (6)
6-6: LGTM!The updated description accurately characterizes
llms-full.txtas a root-level fallback, matching the revised output structure documented throughout this PR.
24-25: LGTM!The output paths correctly reflect the new structure with
llms-full.txtat the public directory root alongside other top-level artifacts.
35-35: LGTM!The description clearly distinguishes between website and bundled output modes, effectively explaining how each serves different audiences and the version-matching benefit of bundled docs.
70-70: LGTM!The enhanced description more accurately conveys the purpose of
AGENTS.mdas a version-matched entry point for offline agent reading, improving clarity for package consumers.
81-81: LGTM!This clarification helpfully distinguishes website-style artifacts from bundled package docs, preventing confusion about which outputs are included in the npm tarball versus served from the hosted site.
44-45: LGTM!The documentation links are correctly updated to reference the new paths, maintaining consistency with the docs restructuring throughout this PR.
evals/evals/bundle-own-docs/EVAL.ts (1)
24-27: LGTM!The test assertion correctly verifies the agent reads from the new bundle guide location at
docs/package-docs/bundle.md, and the test description accurately reflects the updated content structure.apps/example/src/routes/docs/package-docs/bundle.tsx (2)
12-14: LGTM!The component implementation is clean and follows React best practices. The simple wrapper around the MDX component is appropriate for a route handler.
1-1: 💤 Low valueThis "use client" directive aligns with the project's consistent pattern for all route files.
All route files in the docs structure (
apps/example/src/routes/docs/) use the "use client" directive, suggesting this is an intentional architectural decision rather than an unnecessary addition. The directive appears to be required by the project's setup or TanStack Router configuration.> Likely an incorrect or invalid review comment.evals/llms/cross-group-agent-flows/expected.json (1)
9-10: LGTM!The test fixture correctly reflects the docs restructuring, updating both the expected groups (from
buildtopackage-docs) and the page path to match the new bundle guide location.docs/docs.config.ts (2)
19-21: LGTM!The best starting points are appropriately updated to include the new search documentation and reflect the relocated bundle guide, improving discoverability of key documentation pages.
40-50: LGTM!The group restructuring effectively separates the two distinct workflows (building a hosted docs site vs. shipping package docs) with clear, actionable descriptions. The new structure improves navigation clarity for users choosing between deployment strategies.
evals/lib/llms-variants.ts (1)
30-35:package-docsmigration is wired cleanly.The new group type, group metadata, and relocated bundle page path/group are aligned, and the existing group-iteration rendering logic will include it automatically.
Also applies to: 55-60, 141-146
docs/index.mdx (1)
34-51: Docs landing updates are consistent with the new pipeline model.The new card links and artifact messaging match the route/path changes introduced elsewhere in this PR.
Also applies to: 61-65
docs/package-docs/bundle.mdx (1)
4-12: Bundle-docs guidance is clear and consistent after the group/path move.The updated flow and
node_modules/<your-package>/AGENTS.mdconsumption instructions match the new package-docs structure.Also applies to: 21-33, 154-164
docs/build/optimize-docs-for-agents.mdx (1)
65-143: Middleware consolidation is a solid readability improvement.The single-handler example clearly covers docs markdown negotiation plus sitemap/robots regeneration with origin rebasing.
Also applies to: 194-223
docs/quickstart.mdx (1)
35-76: Quickstart flow is clearer and better aligned with current outputs.The generated-artifacts section and next-step matrix/card links now map cleanly to the updated docs routes.
Also applies to: 79-97
apps/example/src/routeTree.gen.ts (1)
31-37: Generated route tree changes are internally consistent.The newly added/replaced docs paths are reflected across imports, route updates, file-route maps, module augmentation, and child registration.
Also applies to: 140-172, 227-367, 558-599, 659-687
| it("loads docs.config.ts for product metadata and group order", async () => { | ||
| const srcDir = await createTempDir(); | ||
| const outDir = await createTempDir(); | ||
| const capture = createCapture(); | ||
|
|
||
| await writeFile( | ||
| path.join(srcDir, "package.json"), | ||
| JSON.stringify({ | ||
| description: "Package fallback summary.", | ||
| name: "package-fallback", | ||
| }) | ||
| ); | ||
| await mkdir(path.join(srcDir, "docs"), { recursive: true }); | ||
| await writeFile( | ||
| path.join(srcDir, "docs", "docs.config.ts"), | ||
| `export default { | ||
| product: { | ||
| name: "Configured Product", | ||
| summary: "Configured product summary.", | ||
| }, | ||
| groups: [ | ||
| { slug: "zeta", title: "Zeta First" }, | ||
| { slug: "alpha", title: "Alpha Second" }, | ||
| ], | ||
| };` | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "alpha.mdx", | ||
| 'title: "Alpha"\ndescription: "Alpha docs."\ngroup: alpha' | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "zeta.mdx", | ||
| 'title: "Zeta"\ndescription: "Zeta docs."\ngroup: zeta' | ||
| ); | ||
|
|
||
| const code = await runCli( | ||
| ["generate", "--src", srcDir, "--out", outDir, "--format", "json"], | ||
| capture.io | ||
| ); | ||
|
|
||
| expect(code).toBe(0); | ||
| const result = JSON.parse(capture.stdout) as { | ||
| groups: Array<{ slug: string; title: string }>; | ||
| product: { name: string; summary: string }; | ||
| }; | ||
| expect(result.product).toEqual({ | ||
| name: "Configured Product", | ||
| summary: "Configured product summary.", | ||
| }); | ||
| expect(result.groups.map((group) => group.slug)).toEqual(["zeta", "alpha"]); | ||
| expect(result.groups.map((group) => group.title)).toEqual([ | ||
| "Zeta First", | ||
| "Alpha Second", | ||
| ]); | ||
|
|
||
| const llmsTxt = await readFile(path.join(outDir, "llms.txt"), "utf8"); | ||
| expect(llmsTxt).toContain("# Configured Product"); | ||
| expect(llmsTxt).toContain("> Configured product summary."); | ||
|
|
||
| const docsLlmsTxt = await readFile( | ||
| path.join(outDir, "docs", "llms.txt"), | ||
| "utf8" | ||
| ); | ||
| expect(docsLlmsTxt.indexOf("## Zeta First")).toBeLessThan( | ||
| docsLlmsTxt.indexOf("## Alpha Second") | ||
| ); | ||
| }); | ||
|
|
||
| it("lets --name and --summary override docs config product fields", async () => { | ||
| const srcDir = await createTempDir(); | ||
| const outDir = await createTempDir(); | ||
| const capture = createCapture(); | ||
|
|
||
| await mkdir(path.join(srcDir, "docs"), { recursive: true }); | ||
| await writeFile( | ||
| path.join(srcDir, "docs", "docs.config.ts"), | ||
| `export default { | ||
| product: { | ||
| name: "Configured Product", | ||
| summary: "Configured product summary.", | ||
| }, | ||
| groups: [{ slug: "guides", title: "Guides" }], | ||
| };` | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "quickstart.mdx", | ||
| 'title: "Quickstart"\ndescription: "Start here."\ngroup: guides' | ||
| ); | ||
|
|
||
| const code = await runCli( | ||
| [ | ||
| "generate", | ||
| "--src", | ||
| srcDir, | ||
| "--out", | ||
| outDir, | ||
| "--name", | ||
| "CLI Product", | ||
| "--summary", | ||
| "CLI summary.", | ||
| "--format", | ||
| "json", | ||
| ], | ||
| capture.io | ||
| ); | ||
|
|
||
| expect(code).toBe(0); | ||
| const result = JSON.parse(capture.stdout) as { | ||
| product: { name: string; summary: string }; | ||
| }; | ||
| expect(result.product).toEqual({ | ||
| name: "CLI Product", | ||
| summary: "CLI summary.", | ||
| }); | ||
| }); | ||
|
|
||
| it("infers groups when no docs config exists", async () => { | ||
| const srcDir = await createTempDir(); | ||
| const outDir = await createTempDir(); | ||
| const capture = createCapture(); | ||
|
|
||
| await writeFile( | ||
| path.join(srcDir, "package.json"), | ||
| JSON.stringify({ | ||
| description: "Fallback docs summary.", | ||
| name: "fallback-docs", | ||
| }) | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "quickstart.mdx", | ||
| 'title: "Quickstart"\ndescription: "Start here."\ngroup: getting-started' | ||
| ); | ||
|
|
||
| const code = await runCli( | ||
| ["generate", "--src", srcDir, "--out", outDir, "--format", "json"], | ||
| capture.io | ||
| ); | ||
|
|
||
| expect(code).toBe(0); | ||
| const result = JSON.parse(capture.stdout) as { | ||
| groups: Array<{ slug: string; title: string }>; | ||
| product: { name: string; summary: string }; | ||
| }; | ||
| expect(result.product).toEqual({ | ||
| name: "fallback-docs", | ||
| summary: "Fallback docs summary.", | ||
| }); | ||
| expect(result.groups).toEqual([ | ||
| { slug: "getting-started", title: "Getting Started" }, | ||
| ]); | ||
| }); | ||
|
|
||
| it("fails clearly when docs config is invalid", async () => { | ||
| const srcDir = await createTempDir(); | ||
| const outDir = await createTempDir(); | ||
| const capture = createCapture(); | ||
|
|
||
| await mkdir(path.join(srcDir, "docs"), { recursive: true }); | ||
| await writeFile( | ||
| path.join(srcDir, "docs", "docs.config.ts"), | ||
| "export default { product: { name: 'Broken' } };" | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "quickstart.mdx", | ||
| 'title: "Quickstart"\ndescription: "Start here."\ngroup: guides' | ||
| ); | ||
|
|
||
| const code = await runCli( | ||
| ["generate", "--src", srcDir, "--out", outDir, "--format", "json"], | ||
| capture.io | ||
| ); | ||
|
|
||
| expect(code).toBe(1); | ||
| const error = JSON.parse(capture.stderr) as { error: string }; | ||
| expect(error.error).toContain("failed to load docs config"); | ||
| expect(error.error).toContain("product.name and product.summary"); | ||
| }); | ||
|
|
||
| it("fails when a configured docs set references an unknown group", async () => { | ||
| const srcDir = await createTempDir(); | ||
| const outDir = await createTempDir(); | ||
| const capture = createCapture(); | ||
|
|
||
| await mkdir(path.join(srcDir, "docs"), { recursive: true }); | ||
| await writeFile( | ||
| path.join(srcDir, "docs", "docs.config.ts"), | ||
| `export default { | ||
| product: { | ||
| name: "Configured Product", | ||
| summary: "Configured product summary.", | ||
| }, | ||
| groups: [{ slug: "guides", title: "Guides" }], | ||
| };` | ||
| ); | ||
| await writeMdxPage( | ||
| srcDir, | ||
| "quickstart.mdx", | ||
| 'title: "Quickstart"\ndescription: "Start here."\ngroup: missing' | ||
| ); | ||
|
|
||
| const code = await runCli( | ||
| ["generate", "--src", srcDir, "--out", outDir, "--format", "json"], | ||
| capture.io | ||
| ); | ||
|
|
||
| expect(code).toBe(1); | ||
| const error = JSON.parse(capture.stderr) as { error: string }; | ||
| expect(error.error).toContain( | ||
| '/docs/quickstart declares unknown group "missing"' | ||
| ); | ||
| }); | ||
|
|
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial | ⚡ Quick win
Add extension-matrix tests for docs.config.js|mjs|cjs auto-discovery.
These new tests validate docs.config.ts well, but the shipped feature supports four extensions. A small parameterized case here would close the remaining regression gap.
🧪 Suggested test pattern
+ it.each(["ts", "js", "mjs", "cjs"])(
+ "loads docs.config.%s for product metadata and group order",
+ async (ext) => {
+ const srcDir = await createTempDir();
+ const outDir = await createTempDir();
+ const capture = createCapture();
+
+ await mkdir(path.join(srcDir, "docs"), { recursive: true });
+ await writeFile(
+ path.join(srcDir, "docs", `docs.config.${ext}`),
+ `export default {
+ product: { name: "Configured Product", summary: "Configured product summary." },
+ groups: [{ slug: "guides", title: "Guides" }],
+};`
+ );
+ await writeMdxPage(
+ srcDir,
+ "quickstart.mdx",
+ 'title: "Quickstart"\\ndescription: "Start here."\\ngroup: guides'
+ );
+
+ const code = await runCli(
+ ["generate", "--src", srcDir, "--out", outDir, "--format", "json"],
+ capture.io
+ );
+ expect(code).toBe(0);
+ }
+ );🤖 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 `@packages/leadtype/src/cli.test.ts` around lines 221 - 437, The test suite
only covers docs.config.ts but the feature auto-discovers docs.config.js|mjs|cjs
as well; add a parameterized test that iterates the four extensions (ts, js,
mjs, cjs) and for each creates docs/docs.config.<ext> with the same exported
default object, then repeat the assertions from the existing "loads
docs.config.ts for product metadata and group order" test (use the same helpers:
createTempDir, writeFile, writeMdxPage, runCli, createCapture) to verify product
fields, group order, and generated llms.txt output; locate and mirror the logic
in the existing test case in cli.test.ts to keep behavior identical and only
vary the filename extension.
loadDocsConfig() runs once per runGenerateCommand, but jiti's default module cache is process-global, so an edited docs.config.ts is not re-read across CLI invocations in tests or watch flows.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
packages/leadtype/src/cli/generate.ts (1)
267-315:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFully validate or sanitize the loaded config before returning typed objects.
validateProductInfo()andvalidateDocsGroups()only prove the minimum required keys, then return the original untrusted value viaas. That still lets malformed optional properties through, so invaliddocs.config.*can fail later during generation instead of at load time. Please either validate the optional fields too or construct freshProductInfo/DocsGroupobjects from the validated subset instead of casting the raw input. As per coding guidelines, "Leverage TypeScript's type narrowing instead of type assertions."#!/bin/bash set -euo pipefail printf '--- Type definitions ---\n' rg -n -C2 'export (type|interface) (DocsConfig|DocsGroup|ProductInfo)' packages/leadtype/src printf '\n--- Current validators in generate.ts ---\n' rg -n -C4 'function validateProductInfo|function validateDocsGroups|function validateDocsConfig|return value as ProductInfo|return value as DocsGroup\[\]' packages/leadtype/src/cli/generate.tsExpected result: the type definitions should show fields beyond the minimum keys checked here, while the validator output will show the raw-object casts that bypass full narrowing.
🤖 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 `@packages/leadtype/src/cli/generate.ts` around lines 267 - 315, The validators (validateProductInfo, validateDocsGroups) currently only check minimal keys then return the original untrusted input via "as", allowing malformed optional fields through; update these to fully validate/sanitize and return freshly constructed typed objects instead of casting: in validateProductInfo build and return a new ProductInfo object with validated optional fields (e.g., ensure optional descriptions, icons, URLs are the correct types or omitted), and in validateDocsGroups recursively construct and return DocsGroup objects (validate slug, title, and sanitize children by mapping each child through validateDocsGroups) so validateDocsConfig can safely return { product, groups } without using type assertions. Ensure no raw "as ProductInfo" / "as DocsGroup[]" casts remain and rely on narrowing/constructed objects for typing.
🤖 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.
Duplicate comments:
In `@packages/leadtype/src/cli/generate.ts`:
- Around line 267-315: The validators (validateProductInfo, validateDocsGroups)
currently only check minimal keys then return the original untrusted input via
"as", allowing malformed optional fields through; update these to fully
validate/sanitize and return freshly constructed typed objects instead of
casting: in validateProductInfo build and return a new ProductInfo object with
validated optional fields (e.g., ensure optional descriptions, icons, URLs are
the correct types or omitted), and in validateDocsGroups recursively construct
and return DocsGroup objects (validate slug, title, and sanitize children by
mapping each child through validateDocsGroups) so validateDocsConfig can safely
return { product, groups } without using type assertions. Ensure no raw "as
ProductInfo" / "as DocsGroup[]" casts remain and rely on narrowing/constructed
objects for typing.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: af5ec6cc-1168-43eb-acd6-ff62b77f8e8a
📒 Files selected for processing (1)
packages/leadtype/src/cli/generate.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Preferunknownoveranywhen the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions
Files:
packages/leadtype/src/cli/generate.ts
**/*.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,ts,jsx,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Preferfor...ofloops over.forEach()and indexedforloops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Useconstby default,letonly when reassignment is needed, nevervar
Alwaysawaitpromises in async functions - don't forget to use the return value
Useasync/awaitsyntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Removeconsole.log,debugger, andalertstatements from production code
ThrowErrorobjects with descriptive messages, not strings or other values
Usetry-catchblocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't useeval()or assign directly todocument.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types for meaningful naming
Add comments for complex logic, but prefer self-documenting code
Files:
packages/leadtype/src/cli/generate.ts
🔍 Remote MCP Context7
Summary of additional facts relevant to reviewing PR #28
-
jiti behavior and relevant options
- createJiti(import.meta.url, { fsCache, moduleCache, interopDefault, tryNative, extensions, ... }) controls filesystem caching (fsCache, default true) and runtime module caching (moduleCache, default true). Disabling fsCache/moduleCache is supported for development to avoid stale reads.
- jiti provides async jiti.import(id, { default, try, conditions, parentURL }) to load configs; the
tryoption returns undefined instead of throwing if module not found. Use parentURL for correct relative resolution.
-
TanStack Router file-route conventions that match repo changes
- createFileRoute(path)({...}) is the standard pattern: a route module exports const Route = createFileRoute('/path')({ component, loader, head, ... }). The path string should match the file location under src/routes; MDX components may be used as the component.
- The router bundler/CLI generates routeTree.typings (routeTree.gen.ts) from file-based routes; module augmentation / type registration (e.g., augmenting
@tanstack/react-routerFileRoutesByPath and FileRoutesByFullPath unions) is expected when new file routes are added/removed. Ensure added route modules export Route and that generated routeTree changes are consistent with file layout.
Tools/sources used
- Context7_resolve-library-id → /unjs/jiti, /tanstack/router
- Context7_query-docs → detailed docs for createJiti/jiti.import and createFileRoute/router generation,
Summary
leadtype generateloaddocs.config.{ts,js,mjs,cjs}automatically so CLI behavior matches the docs mental model.Impact
Docs authors can now rely on
docs.config.tsas the default source of truth for product metadata and group ordering. Repos without config still fall back to package metadata and inferred groups.Validation
bun run --filter leadtype lintbun run --filter leadtype testbun run --filter leadtype check-typesbun packages/leadtype/src/cli.ts lint docs --error-unknown --max-warnings 0bun run --filter leadtype buildnode packages/leadtype/dist/cli.js --help