Skip to content

Docs site: publish docs/ and the READMEs to GitHub Pages from main, with API pages #115

Closed

Description

@CaffeinatedCoder

Problem

The consumer docs can only be read as Markdown on GitHub, and that leaves a reader with no way in:

  • No navigation and no search. The 16 guides in docs/, the root README and the seven package READMEs run to about 7,700 lines. The only map is the root README's "Documentation" table, and nothing searches across the pages. The answer to "how does a value object reach a query" is spread over ef-core.md, the EF Core README and the Generators README.
  • No API reference. Every public member of the shipping projects has XML docs (the build fails on CS1591), but only an IDE shows them. The surface tables in option.md and result.md are the only member lists a reader can browse.

A GitHub wiki is ruled out, for the reasons CaffeinatedCoder/CodoMetis.ValueRanges#417 gives. A wiki is a separate repository whose edits bypass PRs, so ReadmeSampleTests couldn't compile its blocks and claims.json couldn't hold its sentences.

Unlike ValueRanges, TypeKit has one supported line, and main is its released state: topics merge into release/<version>, which merges into main when it is tagged. GitHub already shows the docs of the version dotnet add package installs, and the site must keep that.

Change

  • Build from the sources as they are. A workflow publishes docs/*.md, the root README, the package READMEs and CHANGELOG.md to GitHub Pages, without copying or transforming them, so ReadmeSampleTests and OracleCatalogueTests keep holding the same text. Navigation comes from the site's config. A page that has to change for the site changes in the same PR as its sample regions and claims.
  • Tool: DocFX, as ValueRanges decided in its spike (Docs site: publish docs/ to GitHub Pages, one build per line, the stable line by default CodoMetis.ValueRanges#417): it reads the API from published assemblies, and every page the guides link to becomes a site page, so their relative links resolve without rewriting. Pinned in .config/dotnet-tools.json, with site/docfx.json in the repository (DocFX refuses a content root outside its base directory).
  • Spike first, on what ValueRanges didn't have. src/ holds 35 C# 14 extension(...) blocks, which carry most of the Option and Result extensions, AsText and the IQueryable helpers. ValueRanges had none. Check whether DocFX lists their members, and on the type they extend. If it doesn't, the API pages leave out most of the surface a reader looks for. Ship the guides and READMEs without API pages, and record the gap in a comment with DocFX's version.
  • API pages for the run-time packages only. CodoMetis.TypeKit, .EntityFrameworkCore, .AspNetCore, .Serilog and .Testing, read from one dotnet publish output. The Generators' public surface is what they generate into a consumer (the aspects are internal), and the Analyzers' is their rules, so their READMEs stay the reference.
  • One build, from main. A push to main publishes the site, so it always serves the latest release. release/<version> is not published, because a docs page describing an unreleased version would be the wrong default. A second line under its own path (/2.x/, /3.x/, as ValueRanges does) waits until a 3.x line is supported beside 2.x.
  • Navigation. The guides in the order of the README's "Documentation" table, then the package READMEs as "Reference", then the changelog. Contributor material (CONTRIBUTING.md, AGENTS.md, design/) stays on GitHub.
  • Links. The guides link 43 times to package READMEs and twice to the changelog, which become pages. They also link 15 times into design/ (mostly comparison.md), and those links are rewritten at build time to a GitHub URL at the built commit, never by editing the sources. Analyzer help links and exception messages keep pointing at the README anchors on GitHub: they are public contract, and the site doesn't replace them.
  • Link check on every PR. The docs build runs with --warningsAsErrors on a PR that touches a published page, without deploying, so a broken link fails the PR rather than the deploy.
  • README. It links to the site and stays the GitHub and nuget.org landing page.
  • Needed from the maintainer: set Settings → Pages → Source to "GitHub Actions". The workflow can't do that itself.

Done when

  • The site serves the latest release from main and is rebuilt by CI on a push to main.
  • Every guide and package README can be reached from the navigation and is found by the site's search, and the API pages list the extension-block members, or the spike's comment records why there are none.
  • No link is broken: the check fails a PR with a seeded broken link, and passes without it.
  • CONTRIBUTING.md says how the docs are published, and how a second line would be added.

Activity

  1. added this to the 2.3.0 milestone on Oct 29, 2026
  2. added
    documentationImprovements or additions to documentation
    area/releaseVersioning, changelogs, packaging and release wiring
    on Oct 29, 2026
  3. CaffeinatedCoder commented on Oct 29, 2026

    @CaffeinatedCoder
    OwnerAuthor

    Spike result (DocFX 2.81.0, 2026-10-29): DocFX lists the members of C# 14 extension(...) blocks, so the API pages ship (#138, decision 0116).

    Measured with docfx metadata on the published assemblies of the five run-time packages:

    • Every instance member of a block is listed on its static class as the extension method the compiler lowers it to, with its XML docs. For example Option.FirstOrNone<T>(this IEnumerable<T> source) and StringTextExtensions.AsText(this string? text): 37 extension methods on Option and 52 on Result.
    • The type a block extends lists them under "Extension Methods". Option<T>'s page shows Select, SelectMany, Where, Zip, ToResult and Result.Traverse.

    Gaps, none of which blocks shipping the API pages:

    • Signatures are shown in their lowered form (this in Option<T> a), not as the extension(...) block they're declared in.
    • A member whose constraints the open type doesn't meet is left off that type's page, as for any extension method. OrDefault() (where T : struct) and OrNull() (where T : class) appear on Option's page only.
    • The one static block member, GuidValueExtensions.New(), appears as New<TSelf>() on GuidValueExtensions, not as OrderId.New().

    docs.yml fails if Option<T>'s or Result<T, TError>'s page stops listing its extension Select, so a DocFX update that loses them fails CI instead of reaching readers.

  4. CaffeinatedCoder commented on Oct 29, 2026

    @CaffeinatedCoder
    OwnerAuthor

    Done in #138, merged into release/2.3.0 (3b1c5ac). The API pages ship: DocFX 2.81.0 lists the extension-block members (decision 116). The first deploy runs when the release merges into main.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/releaseVersioning, changelogs, packaging and release wiringdocumentationImprovements or additions to documentation

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions