Skip to content

Tell one canonical wiring story across the docs - #183

Open
KayleeWilliams wants to merge 4 commits into
dx/base-url-configfrom
dx/docs-happy-path
Open

Tell one canonical wiring story across the docs#183
KayleeWilliams wants to merge 4 commits into
dx/base-url-configfrom
dx/docs-happy-path

Conversation

@KayleeWilliams

@KayleeWilliams KayleeWilliams commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #182#167. The docs consistency pass from the roadmap audit (#157, Principle 2): existing configs keep working, and one canonical format is the documented path everywhere.

The contradiction

The quickstart's step 2 taught the manual source as createDocsSource({ contentDir: "./docs", baseUrl: "https://example.com" }) — while claiming the manual steps show "the same wiring" init generated. But init scaffolds lib/source.ts as a zero-arg createDocsProject() that reads content root, navigation, and (since #182) baseUrl from the config. A reader following the manual path built a different, drift-prone integration from the one the scaffold gives them, on the page whose whole point is that they are the same thing.

The same drift ran wider: the build-a-docs-site path picker labelled raw createDocsSource() "Most cases" and never mentioned createDocsProject or the adapters; the source reference led with legacy groups:; several pages restated --base-url/contentDir in snippets the config now owns; and a few root leadtype.config.ts examples used defineDocsConfig where the config-model ownership table says defineLeadtypeConfig.

Page by page

  • docs/quickstart.mdx — step 1's config now carries baseUrl (the same two fields init writes); step 2 is the exact scaffolded zero-arg createDocsProject() with the jiti note; step 3 uses the leadtype/next adapter helpers init wires; steps 4–5 drop the restated --base-url. The manual path now genuinely is the wiring init generates.
  • docs/pipeline/build-a-docs-site.mdx — table and mermaid diagram flipped project-first: the config feeds both createDocsProject() and leadtype generate; createDocsSource() is the labelled escape hatch. Root config example switched to defineLeadtypeConfig with a site-owned baseUrl; the docs:generate script drops --base-url.
  • docs/reference/project.mdx (new) — reference for createDocsProject() and resolveProject(): zero-arg discovery rule (root leadtype.config.*, else docs.config.* inside the docs dir, and the project-root-from-basename rule), the options tables, baseUrl precedence (argument > config > deployment-URL env fallbacks), the diagnostics-vs-throws contract, the ProjectDiagnostic shape with the stable ids, cache-only remote collections naming leadtype sync, and navigationOrigin. Every claim checked against config/project.ts / project/index.ts on this branch — one correction from the audit note: there is no "mixed" origin value in the code; the type is explicit | inherited | groups | inferred, and that is what the page documents. Registered in the reference nav in docs/docs.config.ts.
  • docs/reference/source.mdx — top-of-page callout pointing most apps at createDocsProject(); lead example now uses canonical nav; groups moved under an explicit Legacy callout; nav added to the options table.
  • docs/pipeline/configure-sources.mdx — new multi-repo section showing the gitSource() + sparse + nested collections shape (mirroring apps/c15t-example/leadtype.config.ts); the "multiple local folders" answer is now config collections, with repeated --docs-dir flags kept as a labelled legacy callout; root config examples switched to defineLeadtypeConfig; generate commands stop restating --base-url.
  • docs/pipeline/use-the-source-primitive.mdx — TL;DR reordered: zero-arg createDocsProject() first, primitive as the fallback for content no config describes. The recently-added jiti note and all framework recipes kept.
  • docs/concepts/architecture.mdx + docs/how-it-works.mdx — package map and vocabulary now name createDocsProject/resolveProject as the primary runtime entry; "source primitive" redefined as the lower-level function the project is built on.
  • skills/setup-agent-ready-docs.md — two-line touch-up: init offered up front as the scaffold for steps 2–4, doctor added to the verify step; the config gains baseUrl and the generate command stops restating it.
  • Sweep stragglers — index.mdx pipeline card, agent-setup-prompts (both prompts now scaffold createDocsProject()/defineLeadtypeConfig, canonical routePrefix instead of legacy prefix), localize-docs (per-locale sources via createDocsProject({ locale }) instead of re-handing the config back), sync-docs-across-repos and reference/markdown root configs to defineLeadtypeConfig, collections.mdx lead example likewise.

What stayed documented as legacy, and why

Per Principle 2, nothing was deleted — legacy shapes are confined, not erased. groups keeps a full explanation under an explicit Legacy callout in the source reference (and its rename story stays in the config-model table); repeated --docs-dir flags keep a labelled legacy callout in configure-sources with their exact semantics; deprecated-name behavior (prefix, sourceConfig, schema) remains documented in concepts/config-model, untouched here. They just no longer appear anywhere as the recommended path.

Deliberately untouched for conflict avoidance: docs/reference/doctor.mdx (#181) and docs/concepts/config-model.mdx / the CLI flag rows of docs/reference/cli.mdx (#182, in this base).

Verification

  • bun x leadtype lint docs --format github --error-unknown --max-warnings 0 (the exact CI invocation): 54 files scanned, 0 errors, 0 warnings — including snippet typechecking against the built dist/.
  • bun x leadtype doctor --src . --docs-dir docs: exit 0.
  • bun run --filter leadtype test: 843 pass (56 files); bun run --filter leadtype-evals test: 46 pass. The pre-commit hook re-ran the full suite: 889 pass.
  • docs/paths.lock.json regenerated. Entries updated for every page this PR edits, plus integrate-with-fumadocs: its entry was one of the three stale-at-Resolve the project once instead of in every command #167 hashes Make baseUrl a config field instead of a repeated knob #182 left alone, and the package test suite regenerates the lockfile against the current tree, so its refreshed hash is committed here — the other two stale entries (collections, use-the-source-primitive) belong to pages this PR edits anyway. The lockfile is now fully consistent with the tree.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

The quickstart taught createDocsSource({ contentDir, baseUrl }) while
claiming to show the same wiring init generates — but init scaffolds a
zero-arg createDocsProject() reading everything from the config. The
same drift ran through the path-picker table (raw createDocsSource
labelled "most cases", the project never mentioned), the source
reference leading with legacy groups, and snippets restating baseUrl,
contentDir, or defineDocsConfig in root leadtype.config contexts.

Now every page tells the init story: config owns identity, baseUrl,
and structure; createDocsProject() is the documented runtime entry
(with a new reference page covering discovery, baseUrl precedence,
the diagnostics-vs-throws contract, ProjectDiagnostic, and
navigationOrigin); createDocsSource() is the labelled escape hatch;
and gitSource() collections replace repeated --docs-dir flags as the
multi-folder answer. Legacy shapes stay documented — groups under an
explicit legacy callout, --docs-dir as a labelled legacy note — they
just stop appearing as the recommended path.
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 143703fe-30f7-4f30-815d-60a02bd1f9d0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@KayleeWilliams

Copy link
Copy Markdown
Collaborator Author

Coordination note: #179 (sibling branch) adds "mixed" as a project-level navigation origin (DoctorReport.navigation.origin becomes NavigationOrigin | "mixed"). This page's navigationOrigin section documents the four per-collection values, which stays correct — but once #179 merges, add the project-level mixed value here (one line) so the reference matches doctor's report.

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

Copy link
Copy Markdown

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: 4deb76db1b

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

Comment thread docs/pipeline/localize-docs.mdx
Comment thread docs/reference/project.mdx Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The jiti claim is wrong in two places: leadtype init never installs it, and a scaffold without it throws on first render. A reader who trusts the docs over the adjacent bun add jiti gets a broken app.

Reviewed changes — full read of the 17-file docs diff, with every API claim on the new reference page traced back to packages/leadtype/src.

  • New docs/reference/project.mdx — canonical reference for createDocsProject() / resolveProject(): discovery order, options tables, baseUrl precedence, the diagnostics-vs-throws split, ProjectDiagnostic ids, and navigationOrigin. Registered in the reference nav and present in paths.lock.json.
  • Canonical entry point flipped — quickstart step 2, build-a-docs-site, use-the-source-primitive, architecture, how-it-works and index now lead with zero-arg createDocsProject(); createDocsSource() is relabelled an escape hatch rather than "most cases".
  • --base-url dropped from documented commands — every leadtype generate invocation now relies on the config's baseUrl, which #182 put in place.
  • Legacy shapes confined, not deletedgroups moved under a Legacy callout in the source reference, repeated --docs-dir flags kept in a labelled callout in configure-sources.
  • Naming sweep — root-config examples switched to defineLeadtypeConfig, prefixroutePrefix, plus a new gitSource() multi-repo section.

I verified the load-bearing accuracy claims rather than assuming them. All of the following check out against this branch: every createDocsProject/resolveProject option name, type and default (project/index.ts:88-130); all seven diagnostic ids verbatim; the explicit | inherited | groups | inferred union; baseUrl precedence arg > config > env (generate.ts:1796, internal/docs-url.ts:179-207), so dropping --base-url is safe; --name/--summary falling back to config product (generate.ts:580-589); the inheritConfig whitelist excluding baseUrl (config/inherit.ts:44-56), making the "never inherited from the source" comment true; and every rewritten snippet's imports and call shapes, including createLoadPageData's internal slug ?? [] which makes dropping the old ?? [] correct. The three new internal anchors all resolve.

ℹ️ Nitpicks

  • docs/quickstart.mdx:118 — "the exact lib/source.ts that init scaffolds" holds for Next only. Nuxt scaffolds a lazily-memoized getSource() (init-templates.ts:338-350), and Astro/SvelteKit write to src/lib/source.ts. Since step 3 is framed as "the only step that varies by framework", a Nuxt reader hits a contradiction one step early.
  • docs/reference/project.mdx:62 — the env fallback list skips two real steps: PORTLESS_URL and the browser's location.origin both sit ahead of http://localhost:<PORT> (internal/docs-url.ts:179-207).

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread docs/quickstart.mdx Outdated
Comment thread docs/reference/project.mdx Outdated
Comment thread docs/pipeline/configure-sources.mdx

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

Copy link
Copy Markdown

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: 14b6ed0288

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

Comment thread docs/reference/project.mdx Outdated
Comment thread docs/reference/project.mdx Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ℹ️ No blocking issues in the new commit — all three prior threads are genuinely fixed. One inline correction and one sweep straggler below.

Reviewed changes — the delta since the prior pullfrog review at 4deb76db, i.e. commit 14b6ed02.

  • Corrected the jiti ownership claim in both placesdocs/quickstart.mdx:120 and docs/reference/project.mdx:26 now say init reminds you to install it rather than installs it. This matches the code: jiti is in deps for every framework plan (init-templates.ts:145/244/334/439), so init.ts:342-344 does print "Ensure these are installed: … jiti", while init.ts:321-326 still patches only scripts["docs:generate"].
  • Added the missing typeTableBasePath to the c15t gitSource() snippetdocs/pipeline/configure-sources.mdx:289 now carries the top-level typeTableBasePath: "content-fixtures/c15t" with its clone-root comment, matching apps/c15t-example/leadtype.config.ts:69 field-for-field. Copied as written, the type tables the sparse: ["docs", "packages"] comment promises now actually resolve.
  • Extended the baseUrl sweep to localize-docs — the defineDocsConfig example gained baseUrl, and its leadtype generate command dropped --base-url, bringing the page in line with quickstart and configure-sources.
  • Reworded the resolveProject() scope claim — no longer asserts flatly that it is "the one pipeline behind generate"; see the inline note, the replacement overshoots in the other direction.

ℹ️ The --base-url sweep stops short of a page this PR edits

docs/pipeline/sync-docs-across-repos.mdx:86 still reads "docs:generate": "leadtype generate --src . --out public --base-url https://docs.example.com --sync" — the same docs:generate script that build-a-docs-site.mdx:81 just had --base-url removed from, describing the same pinned-source production shape. Nothing breaks (the flag is still a valid override), but two pages this PR touches now tell different stories about where the base URL lives, which is the exact drift the PR exists to close.

Technical details
# `--base-url` still restated in a `docs:generate` script on a page this PR edits

## Affected sites
- `docs/pipeline/sync-docs-across-repos.mdx:86``docs:generate` script keeps `--base-url https://docs.example.com`, while the parallel script at `docs/pipeline/build-a-docs-site.mdx:81` was changed to `leadtype generate --src . --out public --sync` in this PR. Both pages document the pinned remote-collection shape.

## Required outcome
Every `leadtype generate` invocation on a page this PR touches reads its base URL from the config, matching the story quickstart, configure-sources, localize-docs and build-a-docs-site now tell.

## Open questions for the human
The same straggler exists on pages outside this PR's stated scope — `deploy-generated-artifacts.mdx:36`, `generate-static-artifacts.mdx:51/91/104/148/158`, `search/add-search.mdx:21`, `reference/openapi.mdx:52`, `generate-rss-atom-feeds.mdx:51`, `aeo/optimize-docs-for-agents.mdx:41`. Worth deciding whether they are a follow-up PR or belong here, since a reader who lands on any of them gets the pre-#182 story.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread docs/reference/project.mdx Outdated

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

Copy link
Copy Markdown

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: 29ca04e111

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

Comment thread docs/pipeline/configure-sources.mdx
Comment thread docs/reference/project.mdx Outdated
Comment thread docs/reference/project.mdx

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The new multi-collection generateStaticParams snippet emits params that include the route prefix, so under the catch-all location every other Next example in these docs uses it renders /docs/docs/quickstart. The paragraph's diagnosis is right; the one-liner it prescribes is not usable as written.

Reviewed changes — the delta since the prior pullfrog review at 14b6ed02, i.e. commit 29ca04e1, which touches docs/reference/project.mdx and its paths.lock.json hash only.

  • Narrowed the resolveProject() / generate claim — the sentence now says generate "performs the same resolution steps" and the unlanded sync-consolidation reference is gone. That matches the branch: generate.ts composes config/load + inherit + normalize + infer from the same modules without importing resolveProject. This retires the one open thread from the last review.
  • Rewrote the configPath / configDir option rows — now documents that the two are alternatives and that configDir wins as the project root when both are passed. Traced and accurate: createDocsProject maps configDir onto resolveProject's cwd (project/index.ts:243), cwd beats the config-path-derived root (config/project.ts:309-311), and the fallback content root becomes <configDir>/docs (config/project.ts:316,457-461) — while normalizeDocsConfig still receives configDir: path.dirname(options.configPath) (config/project.ts:325-327), so relative paths do stay anchored to configPath's directory.
  • Added multi-collection static-params guidance to "What it returns" — a new paragraph plus snippet steering readers away from createGenerateStaticParams for projects with several route prefixes. See the inline comment.

The facts behind the new paragraph all check out: createGenerateStaticParams maps page.slug verbatim (next/index.ts:321), listPages() spreads each source's page through unchanged (project/index.ts:376), and slug is derived from the relative path with no mount applied while urlPath is mount-aware (source/index.ts:300-309) — so two collection index pages really do both yield { slug: [] }. It is only the prescribed replacement that doesn't land.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread docs/reference/project.mdx Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Important

The prior thread is genuinely fixed — both layouts are now correct and the route topology is stated. But the "single-collection projects are fine" carve-out that frames them is still too broad: a single collection with mounts fails identically, and that is the shape this repo's own docs/docs.config.ts uses.

Reviewed changes — the delta since the prior pullfrog review at 29ca04e1, i.e. commit 7456896f, which touches docs/reference/project.mdx, docs/pipeline/use-the-source-primitive.mdx, docs/pipeline/configure-sources.mdx, and the paths.lock.json hashes.

  • Replaced the multi-collection static-params snippet with two named layouts — a per-collection catch-all fed by project.getSource(key), and a merged site-root catch-all derived from urlPath, each with its route location stated in the fence comment. The follow-up paragraph now spells out the prefixed-route misrouting (/docs/changelog/1-0) and the optional-catch-all collision with a static app/page.tsx. This resolves the thread from the last review.
  • Widened the adapter enumeration — the paragraph now names all five static-params helpers rather than Next's alone. Verified: createGenerateStaticParams (next/index.ts:316-323) maps page.slug directly, and createGetStaticPaths, createPrerenderRoutes, createEntries, createStaticParams all route through listJoinedSlugs (internal/framework.ts:77-82), which does the same. leadtype/fumadocs builds a synchronous files list rather than a route-enumeration helper, so its absence from the list is correct.
  • Documented resolveInclude as the exception to the merged view — accurate: project/index.ts:489-500 binds it to getSource(project.collections[0]?.key), and source/index.ts:798-809 defaults fromDir to that collection's own content root. config/project.ts:371 iterates Object.entries(declared), so "first-declared" holds.
  • Qualified the adapter claim in use-the-source-primitive.mdx and pointed it at the reference — the second site the last review asked to reach.
  • Pinned baseUrl ownership to the docs UI repo in configure-sources.mdx — the ownership bullet now names it and the multi-repo example carries baseUrl: "https://acme.dev". Both claims check out: config/inherit.ts:44-57 has no baseUrl in the inherit whitelist (and SourceOwnedConfigFields doesn't declare one), and the fallback chain in internal/docs-url.ts:179-207 really does terminate at http://localhost:<PORT> after the deployment-URL env vars.

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread docs/pipeline/use-the-source-primitive.mdx
Comment thread docs/reference/project.mdx
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