Skip to content

feat: open union branches in place and order operations with x-nimbus-order - #309

Draft
MohamedH1998 wants to merge 5 commits into
mainfrom
feat/api-operation-order
Draft

MohamedH1998 wants to merge 5 commits into
mainfrom
feat/api-operation-order

Conversation

@MohamedH1998

@MohamedH1998 MohamedH1998 commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

API pages stop hiding things. Union branches open where they are declared, field nesting follows the spec instead of stopping at six levels, and a spec can order a section's operations. A site that did nothing sees the same labels, URLs and Markdown twins as before; Stripe's public spec measures within noise of main.

Decisions for the reviewer

  1. One PR or two? x-nimbus-order is independent and could ship alone. Kept together here to ship less.
  2. The label of a union branch stays the schema key. The schema's title is a new sibling field, and the starter shows title ?? label. Making label the title would have changed Markdown twins and mapping labels for every site with titled schemas, so it was rejected. Consequence: the HTML shows the title and the Markdown twin shows the key. Say if you want the twin to print the title too.
  3. With schema pages off, the Markdown twin keeps a named branch as a label while the HTML previews its properties. The alternative grew Stripe's twins from 66 MB to 606 MB, so the twin is deliberately thinner than the page there.

Changes

Spec authors: x-nimbus-order

Sorts an operation within its section. Operations without it keep spec order after the ordered ones; sections keep their own order. No config.

paths:
  /zones/{zone_id}/dns_records:
    get:
      operationId: dns-records-list
      tags: [DNS Records]
      x-nimbus-order: 1
    post:
      operationId: dns-records-create
      tags: [DNS Records]
      x-nimbus-order: 3
  /zones/{zone_id}/dns_records/{id}:
    get:
      operationId: dns-records-get
      tags: [DNS Records]
      x-nimbus-order: 2
    delete:
      operationId: dns-records-delete
      tags: [DNS Records]

Section page, sidebar and home index all read: list, get, create, delete.

Page data: ApiVariant for anyone with their own API components

A union branch used to be a label and, when a schema page existed, a link. It now opens.

Before:

{ "label": "dns-records_dns-record-without-data" }

After, for a branch that is itself a union:

{
  "label": "dns-records_dns-record-without-data",
  "name": "dns-records_dns-record-without-data",
  "title": "Content records",
  "union": {
    "kind": "oneOf",
    "variants": [
      { "label": "dns-records_ARecord", "name": "dns-records_ARecord", "title": "A Record", "fields": [ … ] },
      { "label": "dns-records_AAAARecord", "name": "dns-records_AAAARecord", "title": "AAAA Record", "fields": [ … ] }
    ]
  }
}

After, for an inline object branch, minted at <base>.<position>:

{
  "label": "object",
  "fields": [
    { "coordinate": "create.source.2.iban", "name": "iban", "type": "string", "required": true }
  ]
}

The type, for reference:

interface ApiVariant {
  label: string;        // schema key, or a type label for an inline branch (unchanged)
  name?: string;        // schema key, only for a named branch (unchanged)
  title?: string;       // new: the schema's `title`, when it declares one
  href?: string;        // link to the schema page, when one exists (unchanged)
  fields?: ApiFieldView[]; // now present for an inline branch wherever it appears; anchored and citable there
  union?: ApiUnionView; // new: the branch's own oneOf/anyOf, as deep as the spec nests
}

A named branch's property preview opens one level: a union among its properties shows branches without their fields, so a shared-schema graph stays bounded.

Depth: no limit, one backstop

Before, nesting stopped at six levels and an inline branch at one. Now the walk follows the spec until a schema repeats on the current path. A 25,000-node ceiling per field list is the backstop for a wide, deep, shared graph; when it cuts, the build warns:

warning  Field list stopped at 25000 nodes: the schema has more fields along its paths than one list documents  (create)  [field-walk-ceiling]

No measured spec reaches it. Cloudflare's largest page is under 1,000 fields.

Starter: ApiUnionExplorer.astro

Opens a nested union, shows the schema's title in rows and the field tooltip, and anchors an inline branch's fields. Sites that copied the starter can take this diff or keep their copy; nothing breaks without it.

-<p class="fl-union-label">One of the following:</p>
+<p class="fl-union-label">{union.kind === "anyOf" ? "Any of the following:" : "One of the following:"}</p>
 …
-<div class="fl-name">{variant.label}</div>
+<div class="fl-name">{variant.title ?? variant.label}</div>
+<Astro.self union={variant.union} nested depth={depth + 1} />

Markdown twins

Nested branches print as a nested list and an inline branch prints its fields. A named branch stays a label or a link, as before, so twin sizes do not follow schemaPages.

Before:

Any of:

- `dns-records_dns-record-without-data`
- `dns-records_dns-record-with-data`

After:

Any of:

- `dns-records_dns-record-without-data`
  - one of:
    - `dns-records_ARecord`
    - `dns-records_AAAARecord`
- `dns-records_dns-record-with-data`
  - one of:
    - `dns-records_CAARecord`
    - `dns-records_CERTRecord`

An inline branch, which has no page anywhere, prints its fields:

- `source` (`create.source`; one of, required)
  - one of:
    - `Card`
    - `object`
      - `iban` (`create.source.2.iban`; string, required)

Stranger test on the preview release

A fresh scaffold on create-nimbus-docs@309 and nimbus-docs@309 with a spec exercising every claim: nested unions, an inline branch, titles, nine levels, a self-reference, a discriminator, x-nimbus-order, both schemaPages settings. Every rendering claim held. Fixed from its findings: inline-branch field coordinates printed in the twin now resolve (anchored, indexed, citable); the field tooltip used the key while the row used the title; the docs sentence about unions among an inline branch's properties was wrong; the feature now has its own "Unions" section in routes.mdx naming the position coordinates, the stop rule, the ceiling and its code.

An upgrade test on the same preview: an existing 0.19.1 site (hand-written union spec plus Stripe, 613 pages, schema pages off, starter untouched) with only the framework upgraded. No regressions: the old explorer renders the new data without errors or blank regions, public types are additive only, every Markdown twin change is one the changeset announces, no field-walk-ceiling warning fired. It also found that the preview's coordinate registry lacked inline-branch coordinates; the stranger fix above covers it, and on Stripe at this head every twin coordinate (219,370) is a target.

A second stranger pass on the re-cut preview: every documented claim held and the four fixes above passed. It found one rule applied inconsistently: a named schema's content belongs to its own page, yet an inline branch nested inside a named branch's preview was anchored on the operation page (duplicate ids when the schema appeared twice) and claimed by the citation walk. Fixed: the explorer takes an anchored prop and passes it down, the citation walk stops at a named branch, and the Markdown twin keeps a named branch as a label even when it is itself a union, so page anchors, the coordinate manifest and the twin agree. Docs say so in one sentence, and that equal x-nimbus-order values keep path order.

A third pass on the re-cut preview, pinned to the commit: ship. No duplicate id on any page, page anchors, manifest and twins agree for schema pages on and off, the same named union twice on one page is clean, dev and build output identical. It corrected two docs claims (a named branch's preview opens nested objects, not "one level"; positions renumber when a branch is inserted) and surfaced two behaviours that predate this PR, listed below.

Follow-ups, not in this PR:

  • A property typed as a named union schema (group: $ref Group) shows the branches but never the schema's name or link, and its inline branches are minted under the property path as well as under the schema. Same on main for any $ref property; the union case makes it visible.
  • A union schema's own page keeps named branches as links without a preview, while an operation page previews them. Same line on main; aligning them needs a measurement with schema pages on.
  • The tooltip for untitled inline branches reads object or object.
  • A non-numeric x-nimbus-order, or one on a tag, is ignored silently; one lint note for an unknown or invalid x-nimbus-* value would cover both.
  • A nested union branch with no title is labelled any of/one of, so a tooltip reads L1 leaf or any of and the twin prints the label above the same words.
  • The per-prefix llms.txt lists operations by route, not by section order, and omits a section's operations under other prefixes (ticket 154 territory).
  • Two ceiling cuts in one build fold into one console line with ×2, so the reader cannot tell which lists were cut.
  • Installing …@309 from pkg.pr.new served a stale commit from pnpm's cache on one machine; preview instructions should pin the sha.
  • Build cost on Stripe: parse and projection are flat against main (page data 1,257 MB → 1,297 MB), while Astro's HTML render grew because named-branch fields now inline at every depth on 530 pages (HTML +0.56%). Worth a proper render-phase measurement before the next release.
  • nimbus-docs outdated on a release-scaffolded site running a preview package compares the starter with the last published templates tag and reports "up to date", so a preview user is not told the explorer is behind. It self-corrects once the templates tag ships; a preview-aware note is a small CLI follow-up.
  • A self-referential schema stops at its first repeat with a plain object and no marker or link back to the schema.
  • A ceiling cut leaves no marker on the page or in the twin; the console line does not print the diagnostic code.
  • Inline scalar branches print as string/object and drop enum values.
  • The starter opens one level by default, so a union-bodied request takes several clicks to the first field.
  • create-nimbus-docs README says every version downloads templates-v<version>; preview releases bundle templates instead.
  • With schema pages off, a named branch's fields render in the explorer but stay unanchored and uncitable, as on main; the citation index reports them as unpublished.

Validation

  • pnpm --filter nimbus-docs typecheck; full suite 3,235 pass. One failure is the dev-server catalog test, which times out under full-suite load and passes in isolation.
  • New tests: nested and inline unions in the view model and Markdown; branch labels and titles; a shared-schema union DAG stays under 100 KB of page data; a plain property DAG is cut at the ceiling with a warning; equal x-nimbus-order values keep path order.
  • Stripe's public spec, 613 pages, schema pages off: build 4.7 s vs 4.1 s on main, page data 1.30 GB vs 1.26 GB, Markdown 66.7 MB vs 66.1 MB, largest page 3.4 MB vs 3.3 MB.
  • Cloudflare's spec, 2,976 operations: named dead ends 277 → 5, all true cycles; largest page 1.0 MB.
  • pnpm --filter nimbus-starter-source build and pnpm templates:check pass. The consuming site's end-to-end suite passes against the packed build.
  • Adversarial review, two rounds to consensus. Round one caught that opening previews recursively is exponential on shared schemas (Stripe ran out of a 12 GB heap) and that Markdown twins grew nine times; both fixed and pinned by the tests above.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://feat-api-operation-order.nimbus-docs.com (commit f67b943)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://7bf9caa9.nimbus-docs.com f67b943 2026-10-28T13:59:07.866Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://fa3d1aed.nimbus-docs.com 1ef2962 2026-10-28T12:25:09.945Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://27cf5d4e.nimbus-docs.com bacef5d 2026-10-28T11:41:44.003Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://e90c55be.nimbus-docs.com 6c20aff 2026-10-28T08:20:19.167Z Visit the dashboard ↗

@MohamedH1998 MohamedH1998 added the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026
@github-actions github-actions Bot removed the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026
@pkg-pr-new

pkg-pr-new Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
pnpm add https://pkg.pr.new/@cloudflare/create-nimbus-docs@309
pnpm add https://pkg.pr.new/@cloudflare/nimbus-docs@309

commit: 1ef2962

@MohamedH1998 MohamedH1998 added the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026
@github-actions github-actions Bot removed the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026
@MohamedH1998 MohamedH1998 added the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026
@github-actions github-actions Bot removed the pr preview Publish a pkg.pr.new preview for this PR label Oct 28, 2026

This branch has not been deployed

No deployments
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