Skip to content

Improve Leadtype docs pipeline readability#28

Merged
KayleeWilliams merged 3 commits into
mainfrom
KayleeWilliams/remake-docs
May 11, 2026
Merged

Improve Leadtype docs pipeline readability#28
KayleeWilliams merged 3 commits into
mainfrom
KayleeWilliams/remake-docs

Conversation

@KayleeWilliams
Copy link
Copy Markdown
Collaborator

Summary

  • Make leadtype generate load docs.config.{ts,js,mjs,cjs} automatically so CLI behavior matches the docs mental model.
  • Refresh the docs path for quickstart, docs-site setup, agent-readability middleware, search, and MDX/TOC rendering.
  • Add regression coverage for config loading, product overrides, fallback group inference, invalid config, and unknown group failures.

Impact

Docs authors can now rely on docs.config.ts as 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 lint
  • bun run --filter leadtype test
  • bun run --filter leadtype check-types
  • bun packages/leadtype/src/cli.ts lint docs --error-unknown --max-warnings 0
  • bun run --filter leadtype build
  • node packages/leadtype/dist/cli.js --help
  • commit hook full test suite: 163 pass, 0 fail

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added docs and app routes for "Add search" and a "Render MDX & TOC" example pages.
  • Documentation

    • Reorganized docs into "docs-site" and "package-docs" sections; updated quickstart, build, and bundle guidance.
    • Clarified hosted output paths (root llms-full.txt) and bundle behavior (version-matched AGENTS.md + per-topic markdown).
  • Chores

    • CLI now respects a docs config file for product/groups with CLI overrides for name/summary.

Walkthrough

PR 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.

Changes

Config-Driven Docs Pipeline & Documentation Restructuring

Layer / File(s) Summary
Runtime Dependencies
packages/leadtype/package.json
Adds jiti (^2.7.0) to enable dynamic config file loading.
Config Loading & Validation
packages/leadtype/src/cli/generate.ts
Implements optional docs.config.* discovery via jiti, runtime validation of product and groups schemas, CLI flag (--name/--summary) overrides, resolves generation metadata before mirroring sources, and fails early on unknown group references.
Configuration Tests
packages/leadtype/src/cli.test.ts
Adds writeMdxPage fixture helper and end-to-end generate --format json tests covering config loading, CLI overrides, inference from package.json/MDX when no config exists, and error cases for invalid/missing configs or unknown groups.
Documentation Configuration
docs/docs.config.ts
Adds /docs/build/add-search, replaces /docs/build/bundle-package-docs with /docs/package-docs/bundle, and restructures groups by introducing docs-site and package-docs.
New Example Routes
apps/example/src/routes/docs/build/add-search.tsx, apps/example/src/routes/docs/build/render-mdx-and-toc.tsx
Adds two client-side routes that render corresponding MDX pages and set route-specific head metadata via createDocsHead.
Generated Route Tree
apps/example/src/routeTree.gen.ts
Updates imports, route definitions, FileRoutesByFullPath/ByTo/ById maps, FileRouteTypes unions, @tanstack/react-router augmentations, and runtime children registration to include new search/MDX routes and the migrated package-docs/bundle route.
Route Migration
apps/example/src/routes/docs/build/bundle-package-docs.tsx (removed), apps/example/src/routes/docs/package-docs/bundle.tsx (added)
Migrates the bundle docs route from /docs/build/bundle-package-docs to /docs/package-docs/bundle.
Search Documentation
docs/build/add-search.mdx
New page detailing static search artifact generation (search-index.json, search-content.json), runtime searchDocs usage, synonyms, optional streamDocsAnswer for source-grounded AI answers, endpoint protection recommendations, and verification checklist.
MDX & TOC Rendering
docs/build/render-mdx-and-toc.mdx
New guide showing runtime MDX component registration, stable heading ID generation (slugifyDocsHeading), navigation generation with resolveDocsNavigation, sidebar integration, and troubleshooting TOC/sidebar mismatches.
Docs Site Connection Guide
docs/build/connect-docs-site.mdx
Comprehensive rewrite describing shared docs app CI flow (checkout → lint → generate with --base-url), files written into public/, wiring into app build, config ownership, custom API pipelines, runtime integration options, and verification steps.
Agent Middleware Documentation
docs/build/optimize-docs-for-agents.mdx
Replaces previous serve guidance with an exported handleDocsRequest middleware example that routes discovery artifacts and delegates markdown responses to createAgentMarkdownResponse, plus readMarkdownFile helper and sitemap/robots regeneration rationale.
Authoring & Reference Documentation
docs/authoring/*.mdx, docs/reference/*.mdx
Removes runtime mdxComponents example, updates frontmatter examples to new groups, documents CLI config-loading and fallback behavior, introduces ProductInfo schema docs, and updates references/links to new build pages.
Existing Docs Migration
docs/package-docs/bundle.mdx, docs/build/validate-in-ci.mdx, etc.
Updates frontmatter groups and rewrites bundle page to emphasize version-matched AGENTS.md plus per-topic markdown in node_modules/<your-package>/ with relative links for offline consumption.
User Journey & Quickstart
docs/index.mdx, docs/quickstart.mdx
Rewrites landing and quickstart to list generated artifacts, streamline CLI-first quickstart, add npx leadtype generate --base-url example, update inspection steps, and present updated next-step navigation.
Package & Artifact Descriptions
README.md, packages/leadtype/README.md, docs/methodology.mdx, docs/how-it-works.mdx
Updates wording to describe root llms-full.txt fallback (top-level public/), AGENTS.md package bundles as version-matched offline entry points, and clarify hosted vs. package-bundled outputs and consumption patterns.
Evaluation Fixtures
evals/lib/llms-variants.ts, evals/llms/cross-group-agent-flows/expected.json, evals/evals/bundle-own-docs/EVAL.ts
Adds package-docs group, moves bundle page to docs/package-docs/bundle.md, and adjusts expected eval fixtures and tests accordingly.
Cleanup
packages/leadtype/src/cli.ts
Removes #!/usr/bin/env node shebang and updates inline comments where applicable.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • inthhq/leadtype#13: Related PR implementing docs IA rework, AGENTS.md bundling, and route restructuring.
  • inthhq/leadtype#25: Related edits to methodology and artifact wording.
  • inthhq/docs#11: Related docs workspace changes that mirror route/file migrations and package-docs bundling adjustments.

Poem

🐰 Jiti hops in, configs spring to life,
Docs split their paths—site and package in stride.
Search finds the pages, headings keep their ID,
Agents read AGENTS.md from node_modules wide.
One pipeline hums; many paths now guide.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Improve Leadtype docs pipeline readability' accurately reflects the main objective of the PR, which focuses on improving the docs generation pipeline by adding automatic config loading and refreshing documentation paths.
Description check ✅ Passed The description clearly relates to the changeset, explaining the key improvements (automatic config loading, path refreshes, test coverage) and providing validation evidence.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

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

@KayleeWilliams KayleeWilliams marked this pull request as ready for review May 11, 2026 17:04
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 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),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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

📥 Commits

Reviewing files that changed from the base of the PR and between c3d6186 and 104f79f.

⛔ Files ignored due to path filters (5)
  • apps/example/src/generated/agent-readability.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-nav.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-search-content.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-search-index.json is excluded by !**/generated/**
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (26)
  • README.md
  • apps/example/src/routeTree.gen.ts
  • apps/example/src/routes/docs/build/add-search.tsx
  • apps/example/src/routes/docs/build/render-mdx-and-toc.tsx
  • docs/authoring/components.mdx
  • docs/authoring/frontmatter.mdx
  • docs/build/add-search.mdx
  • docs/build/bundle-package-docs.mdx
  • docs/build/connect-docs-site.mdx
  • docs/build/optimize-docs-for-agents.mdx
  • docs/build/render-mdx-and-toc.mdx
  • docs/build/validate-in-ci.mdx
  • docs/docs.config.ts
  • docs/how-it-works.mdx
  • docs/index.mdx
  • docs/methodology.mdx
  • docs/quickstart.mdx
  • docs/reference/cli.mdx
  • docs/reference/llm.mdx
  • packages/leadtype/README.md
  • packages/leadtype/package.json
  • packages/leadtype/scripts/generate-docs.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli.ts
  • packages/leadtype/src/cli/generate.ts
  • packages/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
Prefer unknown over any when 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.ts
  • apps/example/src/routes/docs/build/add-search.tsx
  • apps/example/src/routes/docs/build/render-mdx-and-toc.tsx
  • docs/docs.config.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
  • apps/example/src/routeTree.gen.ts
  • packages/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
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax 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
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks 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 use eval() or assign directly to document.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.ts
  • apps/example/src/routes/docs/build/add-search.tsx
  • apps/example/src/routes/docs/build/render-mdx-and-toc.tsx
  • docs/docs.config.ts
  • packages/leadtype/src/cli.test.ts
  • packages/leadtype/src/cli/generate.ts
  • apps/example/src/routeTree.gen.ts
  • packages/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 the key prop 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
Avoid dangerouslySetInnerHTML unless absolutely necessary
Use proper image components (e.g., Next.js <Image>) over <img> tags
Use Next.js <Image> component for images
Use next/head or 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 of React.forwardRef in React 19+

Files:

  • apps/example/src/routes/docs/build/add-search.tsx
  • apps/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
Add rel="noopener" when using target="_blank" on links

Files:

  • apps/example/src/routes/docs/build/add-search.tsx
  • apps/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 inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

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 jiti here 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.txt fallback + optional bundled AGENTS.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 generateAgentsMd description 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.txt fallback, 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.md links 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-site here aligns this page with the updated build-docs grouping.

docs/build/connect-docs-site.mdx (1)

167-171: ⚡ Quick win

No issues found. The baseUrl parameter is optional (baseUrl?: string) in the ResolveDocsNavigationConfig type definition, so the documentation example is correct and will type-check. Both passing baseUrl (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 /docs child 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

Comment on lines +7 to +14
export const Route = createFileRoute("/docs/build/add-search")({
component: AddSearchRoute,
head: () => createDocsHead("/docs/build/add-search"),
});

function AddSearchRoute() {
return <AddSearchDoc />;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 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.

Comment on lines +7 to +14
export const Route = createFileRoute("/docs/build/render-mdx-and-toc")({
component: RenderMdxAndTocRoute,
head: () => createDocsHead("/docs/build/render-mdx-and-toc"),
});

function RenderMdxAndTocRoute() {
return <RenderMdxAndTocDoc />;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 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.

Suggested change
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.

Comment on lines +267 to +315
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 };
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

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."

Comment thread packages/leadtype/src/cli/generate.ts Outdated
- 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
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 win

Broaden custom-script guidance to all supported config extensions.

Line 108 currently implies TS-only (docs.config.ts), but this page documents support for docs.config.js|mjs|cjs too. 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

📥 Commits

Reviewing files that changed from the base of the PR and between 104f79f and d64b62d.

⛔ Files ignored due to path filters (4)
  • apps/example/src/generated/agent-readability.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-nav.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-search-content.json is excluded by !**/generated/**
  • apps/example/src/generated/docs-search-index.json is excluded by !**/generated/**
📒 Files selected for processing (17)
  • README.md
  • apps/example/src/routeTree.gen.ts
  • apps/example/src/routes/docs/build/bundle-package-docs.tsx
  • apps/example/src/routes/docs/package-docs/bundle.tsx
  • docs/build/optimize-docs-for-agents.mdx
  • docs/docs.config.ts
  • docs/index.mdx
  • docs/package-docs/bundle.mdx
  • docs/quickstart.mdx
  • docs/reference/cli.mdx
  • docs/reference/evals.mdx
  • docs/reference/llm.mdx
  • evals/evals/bundle-own-docs/EVAL.ts
  • evals/lib/llms-variants.ts
  • evals/llms/cross-group-agent-flows/expected.json
  • packages/leadtype/README.md
  • packages/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
Prefer unknown over any when 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.tsx
  • evals/evals/bundle-own-docs/EVAL.ts
  • evals/lib/llms-variants.ts
  • docs/docs.config.ts
  • packages/leadtype/src/cli.test.ts
  • apps/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
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax 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
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks 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 use eval() or assign directly to document.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.tsx
  • evals/evals/bundle-own-docs/EVAL.ts
  • evals/lib/llms-variants.ts
  • docs/docs.config.ts
  • packages/leadtype/src/cli.test.ts
  • apps/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 the key prop 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
Avoid dangerouslySetInnerHTML unless absolutely necessary
Use proper image components (e.g., Next.js <Image>) over <img> tags
Use Next.js <Image> component for images
Use next/head or 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 of React.forwardRef in 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
Add rel="noopener" when using target="_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 inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

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 ProductInfo section clearly documents the shared product object 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.txt at 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.txt at 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/bundle and clearer link titles for discoverability.

packages/leadtype/README.md (6)

6-6: LGTM!

The updated description accurately characterizes llms-full.txt as 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.txt at 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.md as 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 value

This "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 build to package-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-docs migration 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.md consumption 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

Comment on lines +221 to +437
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"'
);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 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.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/leadtype/src/cli/generate.ts (1)

267-315: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fully validate or sanitize the loaded config before returning typed objects.

validateProductInfo() and validateDocsGroups() only prove the minimum required keys, then return the original untrusted value via as. That still lets malformed optional properties through, so invalid docs.config.* can fail later during generation instead of at load time. Please either validate the optional fields too or construct fresh ProductInfo / DocsGroup objects 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.ts

Expected 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

📥 Commits

Reviewing files that changed from the base of the PR and between d64b62d and 507f21c.

📒 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
Prefer unknown over any when 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
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax 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
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks 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 use eval() or assign directly to document.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 try option 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-router FileRoutesByPath 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,

@KayleeWilliams KayleeWilliams merged commit a2b4a56 into main May 11, 2026
3 checks passed
@KayleeWilliams KayleeWilliams deleted the KayleeWilliams/remake-docs branch May 11, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant