docs(api-reference): add v2 service landing pages - #2833
Open
aaronmichaelacosta wants to merge 8 commits into
Open
docs(api-reference): add v2 service landing pages#2833aaronmichaelacosta wants to merge 8 commits into
aaronmichaelacosta wants to merge 8 commits into
Conversation
aaronmichaelacosta
force-pushed
the
APPEX-1609/v2-service-pages
branch
2 times, most recently
from
September 4, 2026 22:26
94680be to
f7b4089
Compare
aaronmichaelacosta
force-pushed
the
APPEX-956/deprecation-policy
branch
from
September 4, 2026 22:33
0f6b32a to
9400249
Compare
aaronmichaelacosta
force-pushed
the
APPEX-1609/v2-service-pages
branch
from
September 4, 2026 22:33
f7b4089 to
1bb0023
Compare
2 tasks
Contributor
Author
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
1 task
aaronmichaelacosta
force-pushed
the
APPEX-956/deprecation-policy
branch
from
September 8, 2026 17:17
9400249 to
691f1ba
Compare
aaronmichaelacosta
force-pushed
the
APPEX-1609/v2-service-pages
branch
2 times, most recently
from
September 8, 2026 17:27
84d07fd to
310ed6d
Compare
aaronmichaelacosta
force-pushed
the
APPEX-956/deprecation-policy
branch
from
September 8, 2026 17:27
691f1ba to
547a2d0
Compare
aaronmichaelacosta
changed the base branch from
APPEX-956/deprecation-policy
to
graphite-base/2833
September 9, 2026 17:26
Twelve landing pages under the v2 dropdown, one per service in the Stable API proposal, in a new "Services" nav group above the generated Endpoints group. Each describes what the service covers and where its endpoints will appear. They stay in v2 rather than a new unversioned section: customers already know the v1/v2 split, so v1 drains and disappears instead of a third concept arriving. Every page is empty of endpoints today, by design. Endpoints arrive one at a time as each is defined in its new service, migrated, and promoted, so the pages fill up as the migration lands. The placeholder block is what a generated endpoint list will replace once there is real data to generate from -- building it now would duplicate the slug rules in generate_api_changelog.py before we know the shape of what it renders. Also drops the blanket-experimental framing, which the new services contradict: - the dropdown was labelled "v2 (Experimental)", which claims the whole API is experimental while the page inside it explains per-endpoint maturity badges and the deprecation policy promises per-endpoint notice - the Introduction opened with "The v2 API is under active development", same problem; the rest of that sentence is kept, since not deprecating v1 until v2 covers it is still true Not addressed here: the Introduction's maturity list still says stable endpoints get "no breaking changes", while the deprecation policy says they get six months' notice before one. Two different public promises on adjacent pages, and reconciling them is an editorial call, not a scaffolding change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The v2 Introduction told customers "No breaking changes will be made to this API" for stable endpoints. The deprecation policy on the next page over says stable endpoints get six months' notice *before a breaking change* -- which concedes they happen. Two different public promises, and the weaker one is the honest one. Point the bullet at the policy rather than restating it, so there is one customer-facing definition of what each maturity level owes you (which is what the policy was written to be). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Mintlify builds an endpoint's page URL from its first tag: /api-reference/v2/<tag-slug>/<summary-slug> So regrouping the public API into its new services moves every affected page, even though the path, request and response are untouched. Today's /api-reference/v2/miscservice/check-container-health becomes /api-reference/v2/deployments/... and the old URL 404s for anyone who bookmarked it, linked it, or reached it from search. Derive the redirects instead of hand-maintaining ~200 of them: diff the committed spec against the working tree, compute both URLs with the same slug rules the changelog already uses, and emit one redirect per difference. Runs in the spec-sync workflow, so a tag change and its redirect land in the same PR. docs.json joins add-paths, or the redirects would be generated and then left behind. Chains collapse rather than accumulate: an endpoint that moves A -> B and later B -> C leaves A -> C, not A -> B pointing at a page that no longer exists. docs.json is patched textually. A json round-trip is not byte-identical against the checked-in formatting, so it would bury a two-line change in a whole-file diff. Slug rules are imported from generate_api_changelog rather than copied -- they were reverse-engineered against the rendered site, and two independent copies would drift into broken links. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Services and endpoints were two separate things in the sidebar: a "Services" group of twelve descriptions, and an autogenerated "Endpoints" group of per-tag subgroups. Clicking a service in the second one opened whichever endpoint happened to sort first. Mintlify supports a `root` page on a nav group -- "clicking the group title in the sidebar navigation opens the root page" -- but only on an explicitly declared group, not an autogenerated one. So the endpoint list has to be enumerated, which is why this generates it rather than asking anyone to maintain 226 entries by hand. One group per tag now, each with its landing page as `root` and its endpoints as pages. The separate "Services" group is gone; its pages are the roots. A tag with no landing page still gets a working group, so this degrades gracefully for the services that do not have one yet. Landing pages bind by slugged display name, not by tag name, so they attach both before and after the endpoints are regrouped in semgrep-app. Today's spec still carries the old service tags and yields 48 groups, 7 of which already find their page; once the re-tagging deploys that collapses to twelve, all with pages, without touching this code. Runs in the spec-sync workflow after the sort step, whose ordering it inherits, so a newly published endpoint lands in the nav in the same PR that publishes it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The first version declared each service group at the dropdown's top level. Mintlify renders a top-level group as a flat section heading, so the services stopped being collapsible -- every endpoint of every service was expanded at once. The collapsibility came from the autogenerated `Endpoints` group nesting them one level down, and removing that group removed the nesting with it. Nest them inside a `Services` group instead. 27 other groups in this docs.json already nest this way, so this follows the file's own pattern rather than inventing one. Adds a regression test asserting the groups land nested rather than top-level, since the symptom is only visible in the rendered sidebar and `mintlify validate` passes either way. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The landing pages carried a hardcoded "This service has no published endpoints yet", which was wrong the moment the first endpoint was filed. Each page now imports a generated table of its endpoints: method badge, summary linked to the endpoint's reference page, and the lead sentence of its description. Generated per landing page rather than per spec tag, so a tag with no page produces nothing and a page whose service is still empty gets an accurate empty state -- generated, so it cannot go stale, which is what the hardcoded sentence could not manage. Prose on the page stays hand-written. Endpoint URLs come from generate_api_changelog's slug rules rather than a second copy: those were reverse-engineered against the rendered site, and two copies would drift into broken links. Also fixes a URL regression this work exposed. The previous commit replaced the autogenerated endpoint group, which carried `directory: api-reference/v2`, with explicit groups that did not -- so Mintlify served every endpoint from /api-reference/<tag>/ instead of /api-reference/<version>/<tag>/. That silently moved every existing endpoint URL and would have collided v1 with v2. `mintlify validate` passes either way; the only thing that caught it was fetching the URLs, where all 202 generated links 404'd. The nav generator now emits the object form of `openapi` with `directory`. Verified against the re-tagged spec from semgrep-app on a local dev server: all 202 links 200, every landing page renders, and the tables show linked summaries with descriptions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
38 of 43 entries under a service carry a maturity pill. In the narrow nav rail the pill wraps onto its own line, roughly doubling each entry's height and making a service look far larger than it is. Maturity is already stated on the endpoint page and defined in the deprecation policy, so hide it in the rail -- but keep `deprecated`, which is rare and worth interrupting for. Hides the pill's wrapper rather than the pill: the wrapper carries `h-[1lh]` inside a flex-wrap row, so hiding only the pill left a line-tall empty box that wrapped below any two-line title, showing up as a stray gap under exactly those entries. Also turns off Mintlify's `hyphens: auto` on nav titles, which was breaking words mid-syllable -- "Preview a detection poli-cy apply". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The step ran generate_api_nav.py over v1 as well as v2, which would have regrouped the v1 dropdown from its flat "Endpoints" list into per-service groups on the next sync. Nothing asked for that: v1 has no service landing pages, so the groups would open an arbitrary endpoint, and regrouping moves every v1 endpoint's page URL -- Mintlify builds it from the first tag. It also meant the committed docs.json did not match what the workflow produced, so the next run would have opened an unreviewed nav change. With the v1 call gone, running the step reproduces the committed file exactly. The redirect step still covers v1. It is a no-op while v1 keeps its flat group, and it is what would catch the URL moves if v1 is ever regrouped deliberately. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
aaronmichaelacosta
force-pushed
the
APPEX-1609/v2-service-pages
branch
from
September 9, 2026 17:27
d9aad15 to
4d634d9
Compare
aaronmichaelacosta
changed the base branch from
graphite-base/2833
to
APPEX-956/deprecation-policy
September 9, 2026 17:27
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.

What this adds
Twelve service landing pages under the v2 API — one per service in the Stable API proposal — in a new Services group above the generated Endpoints list.
Each page says what the service covers. None of them list endpoints yet, on purpose: endpoints move into these services one at a time, so the pages fill up as the migration lands. The placeholder block is what a generated endpoint list will replace later, once there's real data to generate from.
They live under v2 rather than in a new unversioned section, per the call in [this thread] — customers already know the v1/v2 split, so v1 drains and disappears instead of a third concept showing up.
Also drops the blanket "experimental" framing
The new services contradict it, in two places:
One thing left alone
The Introduction's maturity list still says stable endpoints get "no breaking changes", while the deprecation policy says they get six months' notice before one. Two different public promises on adjacent pages. Reconciling them is an editorial call rather than a scaffolding change, so I've left it — happy to fold it in if you'd rather.
Test plan
npx mintlify@latest validatepassesStacked on #2832. Pairs with the semgrep-app directory scaffolding (APPEX-1609).