Migrate API reference docs to Hugo-native for improved site integration#6622
Migrate API reference docs to Hugo-native for improved site integration#6622jstirnaman merged 243 commits intomasterfrom
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
3c7ad96 to
4fccddc
Compare
|
|
Works with Core and Enterprise, currently. Deployed to staging. |
This comment was marked as outdated.
This comment was marked as outdated.
✅ |
Replace legacy API documentation approach with modern Scalar-based rendering:
## Architecture Changes
- Add renderer abstraction (`layouts/partials/api/`) supporting Scalar and RapiDoc
- Create `api` layout type for API reference pages (single.html, list.html)
- Configure renderer via `site.Params.apiRenderer` (default: scalar)
## OpenAPI Processing Pipeline (TypeScript)
- `api-docs/scripts/generate-openapi-articles.ts` - Main generation script
- `api-docs/scripts/openapi-paths-to-hugo-data/` - OpenAPI to Hugo data converter
- Generates per-endpoint path fragments for AI agent access
- Creates Hugo content pages with `type: api` frontmatter
## AI Agent Accessibility
- Full specs at `/openapi/influxdb-{product}.yml` and `.json`
- Per-endpoint fragments at `/openapi/influxdb-{product}/paths/`
- `<link rel="alternate">` tags in HTML for machine discovery
## Scalar Features
- Dark/light theme support synchronized with site theme
- InfluxData brand colors
- Responsive layout
- Download link for OpenAPI spec
## Products Supported
- cloud-v2, oss-v2
- influxdb3-core, influxdb3-enterprise
- cloud-dedicated, cloud-serverless, clustered
Usage: node api-docs/scripts/dist/generate-openapi-articles.js [product]
- latest-patch.html: Replace deprecated .Store with local variable assignment. The .Store method was removed from shortcode context in newer Hugo versions. - api-endpoint.html: Add nil check for productRef lookup to prevent index errors when productKey is not in productAliases dictionary. Falls back to "influxdb" as default product reference.
- yarn build:api-docs: Generate API docs for all products - yarn build:api-docs cloud-v2: Generate for specific product - yarn build:api-docs:compile: Recompile TypeScript if modified
…. Split ui-dev subagent into hugo-, ts-, and testing-specific agents.
- Add CSS for operations list cards with method badges, paths, and summaries - Remove duplicate Overview section from list.html (was duplicating summary) - Split "Data Operations" into separate nav groups: Write data, Query data, Cache data
- Add support for tag-based article generation with operations metadata - Generate articles.yml data files with tag, menuName, and isConceptual fields - Include operations array in frontmatter for tag pages
- Rewrite single.html for operation pages with RapiDoc integration - Simplify rapidoc.html partial for tag-based rendering - Add sidebar-nav include to sidebar.html for API navigation - Add tab-panels.html and tabs.html for content organization
- Add api-nav.ts for sidebar navigation collapse/expand - Add api-scalar.ts for Scalar API renderer integration - Add api-tabs.ts for tab switching functionality - Add api-toc.ts for table of contents generation - Register components in main.js
- Add YAML article data files for all InfluxDB products - Add sidebar-nav.html partial for API navigation rendering - Rename data directory from article-data to article_data for Hugo compatibility - Remove obsolete JSON articles file
- Update hugo.yml config for API docs settings - Simplify _api-overrides.scss (removed hardcoded content styles) - Import _api-layout.scss in styles-default.scss - Update API landing pages for Core and Enterprise with redirects - Update OpenAPI spec files - Update dependencies
- Update tests for new tag-based API page structure - Add tests for operations list rendering - Add tests for sidebar navigation groups
…tion - Header summary now shows only the first sentence from description using regex extraction with fallback to first line for descriptions without sentence-ending punctuation - Added Overview section with full description after endpoints list
- Sidebar nav now shows operations with method badges and paths instead of duplicating tag names when groups are expanded - Added background color to nav group items to match sidebar - Increased max-height for expanded groups to accommodate all operations - Added styles for operation items in sidebar nav (.api-nav-operation) - Fixed summary paragraph width by setting flex-basis to 100%
- Changed operation link font-size from 0.85rem to 0.95rem to match sidebar - Changed path code font-size from 0.75rem to 0.85rem for consistency - Adjusted method badge font-size from 0.55rem to 0.6rem for readability
…idebar
The base .api-method rule in _api-operations.scss already defines
--head (teal #00897B), but the three nested scopes that override it
for different contexts only covered GET/POST/PUT/PATCH/DELETE:
- .api-operation-card .api-method (all-endpoints card rows)
- .api-toc .api-method (on-this-page operation list)
- .sidebar .api-method (left-nav operation entries)
In those scopes the base rule is shadowed, so HEAD badges rendered with
no fill/border and default text color — effectively invisible on the
card/nav background. Surfaces first on the Enterprise v1 all-endpoints
page (`HEAD /ping`).
Add --head { ... } at each scope using the same #00897B teal so HEAD
badges match everywhere the method appears.
`.api-code-sample` used `overflow: hidden` to clip the inner header and `<pre>` against its rounded corners. That same clip cut off the absolutely-positioned `.code-controls` dropdown (Copy / Ask AI / Fill window) appended into `.codeblock` by `code-controls.js`. Drop `overflow: hidden` and apply matching `border-radius` directly to the inner header (top corners) and `<pre>` (bottom corners) so corners still look right without a clip rect that traps the dropdown.
The Write tag's "Enterprise cluster parameters" section was a single bullet describing a parameter readers couldn't act on without reading the full clustering reference. Replace with an "Enterprise write consistency" subsection that: - Names the `consistency` query parameter and links to the concept page - Tabulates the four values (any/one/quorum/all) with one-line semantics - Marks the default explicitly - Trails with a link to the deeper page for replication-factor and hinted-handoff details Heading drops from h2 to h3 so it doesn't compete with the tag's own h2 page title.
…eration The `consistency` query parameter only applies to the v1 `POST /write` endpoint — `POST /api/v2/write` doesn't accept it. Moving the section out of the Write tag description (which preceded both operations) and into `PostWrite.description` so readers don't see "Enterprise write consistency" guidance immediately above an operation that ignores it. Tag description reduces back to its single-sentence intro. PostApiV2Write keeps its dual `[v2 Compatibility, Write]` tag — a separate cleanup if we ever want to enforce one-tag-per-operation.
api-docs/enterprise_influxdb/v1/v1/ contained an older copy of the
Enterprise v1 spec (version 1.11.6) plus content overlays that the
build pipeline never reads:
- getswagger.sh enterprise-v1 only post-processes the parent-level
influxdb-enterprise-v1-openapi.yaml (currently 1.12.2)
- .config.yml apis.v1@1.root points at the parent-level spec
- post-process-specs resolves overlays under {productDir}/content/,
not the nested v1/v1/content/
Removing prevents anyone (or a future agent) from editing the wrong
file and wondering why their changes don't render. Spec content is
otherwise unchanged.
| ### Enterprise write consistency | ||
|
|
||
| In a cluster, the [`consistency`](/enterprise_influxdb/v1/concepts/clustering/#write-consistency) query parameter controls when `/write` returns success based on how many data nodes have acknowledged a write. | ||
|
|
||
| | Value | Returns success when… | | ||
| | :---------------- | :---------------------------------------------------------------------------------------------------------- | | ||
| | `any` | Any node acknowledges the write, **or** the receiving node queues it for [hinted handoff](/enterprise_influxdb/v1/concepts/clustering/#hinted-handoff). | | ||
| | `one` *(default)* | Any node acknowledges the write (hinted handoff alone does not count). | | ||
| | `quorum` | A majority of replicas acknowledge the write. Equivalent to `all` when replication factor ≤ 2. | | ||
| | `all` | All replicas acknowledge the write. | | ||
|
|
||
| For replication-factor interactions and recovery semantics, see [Write consistency](/enterprise_influxdb/v1/concepts/clustering/#write-consistency). |
There was a problem hiding this comment.
@davidby-influx @influxdata/edge Please verify the values in this table are correct and that the write consistency param is only for v1 /write.
Same vestige pattern as enterprise_v1 (commit c531032): - api-docs/influxdb/v1/v1/ref.yml: not pointed at by .config.yml or getswagger.sh; the active source is the parent-level influxdb-oss-v1-openapi.yaml. - v1/v1/content/info.yml: getswagger.sh's docs-content.cjs::getVersioned reads it during bundling, but post-process-specs.ts then overlays v1/content/info.yml on top — net effect: the versioned copy is invisible. getVersioned has a built-in fallback to the parent content/ dir, so removal is safe. - v1/v1/content/servers.yml: identical to v1/content/servers.yml — pure duplicate.
Three things, one commit because they're tightly coupled:
1. Drop redundant `set-info` / `set-servers` Redocly decorators.
`getswagger.sh` ran them during bundling, then post-process-specs.ts
ran applyInfoOverlay / applyServersOverlay and overwrote whatever the
plugins set. Net behavior was identical but with two sources of truth
for info.yml / servers.yml lookup. Post-process-specs.ts is the only
path now.
2. Remove dead `remove-internal-operations` decorator. The function body
was a no-op (just an `if (x-internal === true) { /* comment */ }`).
The behavior the comment described — "Redoc hides x-internal
operations automatically" — applied to the old Redoc-based render
path, which the Hugo-native templates replaced.
3. Fix `strip-trailing-slash.cjs` exporting a function literally named
`StripVersionPrefix` (copy-paste artifact). Renamed to
`StripTrailingSlash`. Cosmetic — registration uses the `id` string,
so the function name was never observed.
Removed files (now orphaned):
- decorators/set-info.cjs
- decorators/servers/set-servers.cjs
- decorators/operations/remove-internal-operations.cjs
- docs-content.cjs (only consumer was set-info / set-servers)
- helpers/content-helper.cjs (only consumer was docs-content.cjs)
Verified: redocly bundle dry-run against influxdb3-core-openapi.yaml
succeeds; post-process-specs runs clean; 25 Cypress API tests pass.
Two bugs surfaced on the InfluxDB Enterprise v1 Write tag page, both
from uncoordinated ordering logic:
1. Body rendered /api/v2/write (v2-compat) before /write (native v1).
tag-renderer.html had a v3-centric sort that ranked paths by prefix:
/api/v3 = 0, /api/v2 = 1, other = 2. For v1 products where native is
unversioned, native ended up ranked last.
2. On-this-page TOC iterated .Params.operations directly (no sort) so
it showed /write first — mismatching the body.
Extract the sort into a new partial used by both the body and TOC, so
they can never disagree again. Ranking:
- 0 native
- 1 v2 compat
- 2 v1 compat
- 3 unknown compat version
Signal priority: operation.compatVersion (from x-compatibility-version
in the spec — v1 product specs carry these) first, path prefix
(/api/v3/, /api/v2/, /api/v1/) when marker is absent (v3 product specs
typically don't mark). Unversioned paths are ambiguous without product
context — resolved per-tag: if any sibling operation carries a
compatVersion marker, the spec is marker-aware (v1 style) so
unversioned counts as native; otherwise (v3 style) unversioned counts
as v1-compat.
Verified orderings (also locked in as Cypress tests):
- Enterprise v1 Write: PostWrite (/write), PostApiV2Write (/api/v2/write)
- Core Write data: PostWriteLP (/api/v3/write_lp), PostV2Write
(/api/v2/write), PostV1Write (/write)
Also asserts body and TOC operation sequences are identical.
Add x-compatibility-version markers to the 4 operations in each of Core and Enterprise that are already labeled as compatibility shims in their `summary` and `tags` (tag "Compatibility endpoints"): - POST /api/v2/write (PostV2Write) → v2 - GET /query (GetV1ExecuteQuery) → v1 - POST /query (PostExecuteV1Query) → v1 - POST /write (PostV1Write) → v1 This lets the tag-page sort (layouts/partials/api/sort-operations.html) rank operations purely by marker, without relying on the path-prefix heuristic for these tags. The heuristic stays as the fallback for specs that still lack markers (Cloud Dedicated, Cloud Serverless, Clustered, OSS v2, Cloud TSM). Scope limited to ops that already carry a compat label in their summary and tags — avoids characterizing unlabeled ops (/health, /metrics, /ping, /api/v1/health) as compat without the source spec asserting it. Followup: influxdata/docs-tooling#55 tracks moving this marking into the upstream spec generator so docs-v2 doesn't have to maintain it.
Matches the InfluxData docs style convention.
…sections
The "Choose the write endpoint for your workload" callout linked to
Redoc-style anchors that no longer exist after the Hugo-native API
reference migration:
- /influxdb3/core/api/v3/#post-/write (also hardcoded `core` in a
shared file)
- /influxdb3/version/api/v3/#post-/api/v2/write
Rewrote CTAs to point to the existing in-page sections on the same
page (#influxdb-v1-compatibility, #influxdb-v2-compatibility) and
replaced the {{% product-name %}} HTTP API /path phrasing with the
"v1-compatible" / "v2-compatible" descriptors the callout reader
actually needs to recognize. Works across all 5 consumers of this
shared file (core, enterprise, cloud-dedicated, cloud-serverless,
clustered).
75 references across 54 files used the old Redoc `#<method>-/<path>`
anchor format that no longer resolves after the Hugo-native API
reference migration. Swept the tree with a scripted rewrite against the
per-product operation map in data/article_data/*/articles.yml:
/influxdb3/<product>/api/v3/#post-/api/v3/configure/database
→ /influxdb3/<product>/api/database/#operation/PostConfigureDatabase
Script: scripts/fix-redoc-anchors.mjs.
Shared files under /version/ placeholder: rewritten to the same
operation URL when every product that consumes the file has a matching
operationId + tagSlug + subKey. When those diverge (e.g. Core's
PostV1Write vs Cloud-Dedicated's PostLegacyWrite for the same /write
endpoint), the script falls back to linking the tag page without an
operation anchor so the rendered link works across every consumer.
Manual fixes for anchors the script couldn't auto-resolve:
- `/reference/api/v3/#post-...` legacy URL variant in data-retention.md.
- Typo in tokens/resource/create.md pointing at
`/api/v3/configure/enterprise/token` (should be
`/api/v3/enterprise/configure/token` → PostCreateResourceToken).
- Two refs to `PATCH /api/v3/configure/database/{db}` updated to
`PUT /api/v3/configure/database` → `update_database` (the actual
operation in the spec).
- 2 cross-version shared files (api-guide/api_intro.md,
get-started/query.md) pointed at unique v2+cloud operations.
Net: content now has 0 legacy Redoc-style anchors. 27 Cypress tests
still pass.
Every doc page's footer contains template-generated "Edit this page" and "Submit issue" links pointing at github.com/influxdata/docs-v2. Checking those across 6000+ pages only surfaces GitHub rate-limit noise (~30k warnings per full run of production config), so exclude the whole influxdata/ org from link validation. Trade-off: a hand-authored broken link to an influxdata/ repo won't be caught. Considered acceptable because any such breakage in a template-generated URL would affect every page simultaneously — an obvious failure mode that a link checker isn't uniquely positioned to surface.
The upstream OSS v2 spec ships with `servers: [{url: "/"}]` — intended
as a Swagger UI "origin of this API" placeholder, not a literal URL.
Every other product has a content/servers.yml overlay that
post-process-specs.ts merges in to replace it. v2 was the only product
missing the overlay, so the literal "/" leaked into rendered curl
samples as "//api/v2/...".
Add http://localhost:8086 — the same convention used by the v1 spec
overlay and by every v2 hand-authored example in the docs.
Development Plan (preserved by cleanup workflow)Full plan details from branch: feat-api-uplift
|
| Product | URL | Status |
|---|---|---|
| InfluxDB 3 Core | /influxdb3/core/api/ |
Complete |
| InfluxDB 3 Enterprise | /influxdb3/enterprise/api/ |
Complete |
| Cloud Dedicated | /influxdb3/cloud-dedicated/api/ |
Complete |
| Clustered | /influxdb3/clustered/api/ |
Complete |
| Cloud Serverless | /influxdb3/cloud-serverless/api/ |
Complete |
| InfluxDB Cloud (v2) | /influxdb/cloud/api/ |
Complete |
| InfluxDB OSS v2 | /influxdb/v2/api/ |
Complete |
| InfluxDB OSS v1 | /influxdb/v1/api/ |
Complete |
| Enterprise v1 | /enterprise_influxdb/v1/api/ |
Complete |
What shipped
Infrastructure
- Hugo templates in
layouts/api/render operations, parameters, schemas, responses, and code samples post-process-specs.tstag config features:rename— rename tags across spec and all operationsreassign— split one tag into multiple by API path prefixdrop— remove tags and exclusively-owned operations from the spec
generate-openapi-articles.tscontent generation:- Tag-based pages with frontmatter from article data
subSectionsupport for multi-spec productspage.ymloverlay for per-product landing page content- Explicit
specDownloadPathpassed from call site (fixes single-spec products withdisplayName)
- Data paths mirror content paths (
data/article_data/{family}/{product}/api/) - Templates derive sidebar data lookup from page URL segments (3-segment and 4-segment)
- Response descriptions render markdown via
markdownify - HEAD method badge color (
#00897Bteal)
Per-product
- Core + Enterprise: 13 aligned tags. Enterprise uses
rename(Token → Auth token),reassign(Cache data → distinct/last value), and adds Migrate trait tag. - Cloud Dedicated + Clustered: Nested Data API / Management API sidebar sections with per-spec downloads and all-endpoints pages. Enriched traitTag descriptions (quick starts, parameter tables, status codes).
- Cloud Serverless: 29 TSM-era tags dropped via
drop: true. Note callout on landing page directs to Cloud (TSM) reference. Bucket Schemas dropped. Terminology corrected to "databases (buckets), organizations, and tokens." - Cloud v2 + OSS v2: Tag-based rendering with full operation details.
- OSS v1 + Enterprise v1: Tag-based rendering from v1 OpenAPI specs.
Testing
- 25 Cypress e2e tests (all passing):
- Data-driven sidebar nav (reads tags from
articles.yml) - Data-driven conceptual page content (50+ char threshold)
- Multi-spec sidebar structure (Cloud Dedicated, Clustered)
- Tag pages, section pages, all-endpoints pages
- Data-driven sidebar nav (reads tags from
readArticleDataandreadConceptualTagsCypress tasks- Hugo test server uses
--disableFastRenderto avoid Hugo 0.157.0 rebuild panic
Post-release issues
- #7008 — Extract
#### Related Guidesfrom operation descriptions into structuredx-relatedfields (~190 instances across 5 specs) - #7009 — Consolidate legacy hand-written v1/Enterprise v1 API pages with the new spec-based reference
Related Files
- Branch:
feat-api-uplift - PR: #6622, #7006
- Scripts:
api-docs/scripts/generate-openapi-articles.ts,api-docs/scripts/post-process-specs.ts - Templates:
layouts/api/,layouts/partials/api/,layouts/partials/sidebar/ - Tests:
cypress/e2e/content/api-reference.cy.js,cypress/support/hugo-server.js - Tag configs:
api-docs/{product}/tags.yml - Page overlays:
api-docs/{product}/content/page.yml - Article data:
data/article_data/ - Static specs:
static/openapi/

API reference uplift
Replace Redoc with Hugo-native templates for API reference documentation. Operations render as standard HTML — no shadow DOM, no client-side rendering.
Hugo-native layout
layouts/partials/api/)/influxdb3/core/api/database/)Inline curl examples
{baseurl}→ default fromspec.servers[0].variables)$refresolution for parameters, request bodies, and schemasexample→default→enum[0]→ type placeholder)text/plaincontent typesinfluxdb-url.jsautomatically personalizes placeholder hostsAsk AI integration
ask-ai-openclass +data-queryattribute)ask-ai-trigger.jsRelated links
x-influxdata-relatedfrontmatterVisual improvements
#D63031) vs 4xx errors (warm orange#E17055)2pxborder, increased padding)Build and generation
yarn build:api-docsparses OpenAPI specs into Hugo data and generates content pages--cleanflag (default) removes stale files when tags are renamed or removed--dry-runflag previews what would be deleted