Repository navigation
Mount a declared API without a toc entry - #4738
Merged
Merged
Conversation
A toc entry such as `api: elasticsearch` now mounts a floating section: a set of pages that owns its URL root and sidebar and is not made of Markdown files. A provider resolves the section before navigation is built, and it renders as an island. `CreateLinkReference()` skips these nodes instead of casting them to `MarkdownFile`. No provider is registered yet, so a build that uses the entry reports an error. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…entries The site assembler dropped every root child of a mounted docset and warned that it was undeclared, so an `api:` entry vanished from the assembled navigation. Floating section roots now carry a marker interface and the assembler keeps them. An `api:` entry that also sets `children:`, `file:` or other keys now reports an error instead of silently dropping them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A floating section root now exists as soon as the toc mounts it, with its landing URL and title, so layout code can link to it. The children come later from `ResolveAsync`, which `DocumentationSet.ResolveFloatingSectionsAsync` runs before generation. The children keep their own numbering, so filling them never renumbers the surrounding navigation. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The narrative root copied only leaf items into the site tree, so an `- api: <key>` entry in its toc resolved and then vanished. The root now keeps floating section roots next to its leaves. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
ResolveDirectoryTree now fills floating sections, so DocumentationGenerator, the assembler and the codex build see their pages without a separate call. The test goes through ResolveDirectoryTree and checks resolution runs once. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An `api: <key>` toc entry now resolves to an API section. Its root exists when the toc is read, and `ResolveAsync` fills it with the version trees before generation. The generator builds each API's trees once and renders from them, so mounting a section adds no second fetch or build. Only the current version is visible. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The docset now fills floating sections itself, so a build run with `--skip-api` resolves an `api:` entry without a generator. The section stays empty and hidden instead of failing. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ip-api A spec that fails to build no longer stops the Markdown build: the section reports the error and hides. The section also hides when no main version resolved, and a hidden API no longer appears in the section dropdown. The generation state records --skip-api, so toggling it triggers a full build. The docs now say that only the isolated build accepts api: entries. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The floating section no longer emits its own error when tree building fails, because the generator awaits the same cached task and already reports it with the stack trace. The no-main test now makes main unreadable without throwing, so it proves released versions loaded. A new build-twice test covers toggling --skip-api over unchanged pages. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A mounted API now publishes its pages in `links.json` under `floating`, one entry per page path with a bit mask of the versions that contain it. A cross-link such as `elasticsearch://api/elasticsearch/v8/operation/operation-search` resolves through hash lookups and a bit test, and a page missing in that version is an error. The resolver builds the final URL from the site root, because API pages sit outside every repository path prefix. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An alias now belongs to the versions that list it, so a link to an alias in a version without it fails, and an alias can name different pages in different versions. A cross-link to an API page keeps its #fragment. CodexAwareUriResolver sends API pages to the published site instead of a repository path. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A fragment stays on the resolved URL and the build does not check the anchor. Aliases of a collapsed operation resolve only in the versions that list them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A floating link section no longer assumes how a kind routes its URLs. Each version names its root, and whether it is hidden or current, so a reader joins a root and a page path and never adds a `v` segment. A cross-link picks a version by its name, and aliases are listed under their canonical path, which writes that path once however many aliases it has. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
An API page called `main` or `8` was read as a version, so the link reached the landing page. A page of the current version now takes precedence, so adding a version never changes where an existing link points. The current version's bit is cached instead of scanned for on every unversioned link. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The lookups of a section are built on first use. The copy that a `with` expression makes carried them over, so replacing the versions or the aliases kept answering from the old data, and a test failed only when another test had used the shared fixture first. A copy now keeps the data and none of the lookups. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A `section: APIs` with `floating: api` in navigation.yml now mounts every declared API under a hub, so the sitemap walk and the llms.txt listing read the APIs from the tree like any other page. The roots exist when the navigation is built and the OpenAPI step fills them from the trees it renders from. GenerateApiSection and its catalog side door are gone, and the walk skips links to a heading inside a page. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ML exports The hub URL has no trailing slash, so the sitemap filter now matches it exactly. The top navigation tab for a floating section without external: links the hub instead of the first child. API sections are only mounted when the HTML export, and with it the API build step, runs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The exporter guard sat inline in the build service, so no test reached it. It now lives in AssemblerApiSections.For, and a test checks that an LLM-only build gets no API sections while an HTML build keeps them. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A docset that declares an API in its api: block now has that API in its navigation tree, in isolated and assembler builds, hidden in the docset sidebar. The explicit api: toc entry is gone, so its links.json lists the API without anyone editing a toc. Each assembler docset resolves its sections from generators that the build creates first, and the site APIs section lists the same APIs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
AssembleAsync resolves every docset tree before the API generators exist, so the API sections stayed empty and links.json had no floating entries. The build now resolves the floating sections again once the generators are attached, and a section starts from how its root was created. The section dropdown no longer lists hidden top-level roots, such as implicitly mounted APIs. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…erators The build resolves the docset trees before any generator exists, then attaches the generators and resolves the floating sections again. The new test follows that order. It checks that the root fills, stays hidden and publishes its pages in links.json. Without the second resolution the test fails. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The APIs hub and the root of each API take a place in the global navigation order, so the pager walked into them. In the preview navigation the Reference page had the Logstash API as its previous page, and the last page of the docs had the APIs as its next page. The previous and next links now skip the hub and every floating root. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Nov 5, 2026
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Contributor
Docs preview (local build)Handbook preview: https://docs-v3-preview.elastic.dev/elastic/docs-builder/pull/4738/ Sample changed pages: |
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A docset that declares an API in its
api:block now has that API in its navigation tree, in isolated and assembler builds, with no toc entry. Itslinks.jsonlists the API, so cross-links to it can resolve. The explicit- api: <key>toc entry is removed.Affects: Navigation, Links & redirects, Assembler builds
Prompt summary: Make API pages part of the navigation tree in isolated and assembler builds, so the sitemap,
links.jsonandllms.txtcan see them. A docset that defines an API section has it implicitly, with no toc entry, and the way an isolated build shows it in its sidebar is decided later. This is the fifth step of the design in RFC: Floating sections in the navigation tree.Why
The earlier steps mount an API only where a toc says
- api: <key>, and only the isolated build can. No docset has such an entry, so nolinks.jsonhas afloatingsection and no cross-link to an API can resolve. Theapi:block already declares everything the build needs.What
Implicit mount
A provider can opt in with
MountsImplicitly.DocumentationSetNavigationthen mounts every section the provider offers, as an island after the toc entries. The API provider opts in, so each declared API is in the tree. The mounted roots are hidden in the sidebar of the docset, so no sidebar changes. How an isolated build shows its APIs is a later decision.The toc entry is gone
FloatingSectionRef, its parser and its resolution are removed, along with the lookup of a section by key. A toc with- api: <key>now reportsUnknown key 'api'.Assembler docsets
Each assembler docset gets its own API provider when the build renders the API Explorer.
AssemblerApiSectionsnow creates the generators before the docsets resolve their trees, so each docset fills its sections from the same trees the OpenAPI step renders from, and nothing is fetched twice. TheAPIssection of the site navigation lists the same APIs and keeps its visible roots.Docs
docs/data/openapi/api-explorer.mddescribes the implicit mount, anddocs/documentation/assembler/navigation.mdsays the docset needs no entry.Stack: 5, on top of #4737.
Out of scope: showing an API in the sidebar of an isolated build, the
serveand Codex builds, and replacing the link check in #4653. Theapi:toc entry had no users and is not kept as an override.Verify
The integration test needs network access to CloudFront. It checks that an assembled docset publishes its API in
links.jsonwith no toc entry.To see it in an isolated build, build this repository's docs and read
links.json:It lists all ten declared APIs under
floating, and the docs sidebar does not change.🤖 Generated with Claude Code