Skip to content

refactor(layouts): resolve products from data, not hardcoded lists - #7573

Merged
jstirnaman merged 8 commits into
masterfrom
refactor-layouts-product-data
Aug 19, 2026
Merged

refactor(layouts): resolve products from data, not hardcoded lists#7573
jstirnaman merged 8 commits into
masterfrom
refactor-layouts-product-data

Conversation

@jstirnaman

Copy link
Copy Markdown
Contributor

Stacked on #7571, which is stacked on #7569. Review those first; this PR's
base is refactor-search-labels-from-products.

What changed

Five templates stopped inferring the product from the URL path and stopped
branching on hardcoded lists of product names.

  • Added layouts/partials/product/get-context.html. It resolves the product
    from the page's cascade product param, with a path fallback for product
    hub pages, which sit above the versioned sections that carry the cascade.

  • Added layouts/partials/product/is-latest.html. One rule for "does this
    page document the current version", shared by both search systems.

  • Moved the branching facts into data/products.yml:

    Field Set on
    supports_flux influxdb, influxdb_cloud, enterprise_influxdb
    search_includes_resources false on the six InfluxDB 3 products
    has_support_contract false on chronograf, kapacitor
  • Set latest on telegraf_controller and telegraf_enterprise to their
    version path segment.

  • Second commit: documented the rule in .agents/instructions/layouts.md,
    the hugo-template-dev skill, and AGENTS.md.

No product names remain in the touched templates.

Why

header/coveo-meta-data.html and header/search-attributes.html both
answered the same question, each with its own hardcoded list, and the lists
drifted:

                     coveo   algolia
/influxdb3/explorer/  false    true
/telegraf/controller/ false    true

Two search systems disagreeing about whether the same page is current.

The lists existed to paper over a broken lookup. Both templates did
index .Site.Data.products $product where $product is the first path
segment. Under /influxdb3/ that segment is influxdb3, which is not a
products.yml key — the keys are influxdb3_core, influxdb3_cloud. The
lookup always missed, so the real comparison never fired and someone listed
the version segments by hand instead.

The data already answered it. influxdb3_core has latest: core,
influxdb3_explorer has latest: explorer. Every product section already
declares its products.yml key through cascade, and
layouts/partials/product/get-data.html already resolved it.

Impact

Coveo and Algolia now agree on every product. Search tags are unchanged, so
the Algolia index is untouched:

/influxdb3/core/         tag=influxdb3-core         res=false  flux=false
/influxdb3/cloud/        tag=influxdb3-cloud        res=true   flux=false
/influxdb/v2/            tag=influxdb-v2            res=true   flux=true
/telegraf/controller/    tag=telegraf-controller    res=true   flux=false
/enterprise_influxdb/v1/ tag=enterprise_influxdb-v1 res=true   flux=true

The flux and resources flags reproduce the deleted lists exactly.

Two behavior changes need a second opinion:

  1. telegraf_controller and telegraf_enterprise had latest: 1.0
    unquoted. YAML parses that as a float, and Hugo renders it as "1" — the
    .0 is gone before any regex runs, and eq against a string is always
    false. Verified with a Hugo probe:

    PROBE latest=1 type=float64 | latest_patch=1.0.1 type=string
          | replaceRE="1" | eqString=false
    

    They are the only two products whose version field is not a string. The
    value was dead — no template read .latest for either product — but the
    currency rule needs it, so both are now controller and enterprise,
    matching the convention every other product follows: latest is the URL
    version segment, latest_patch is the release. latest_patch: 1.0.1 is
    unchanged. If release tooling outside this repo reads
    telegraf_controller.latest expecting 1.0, say so and I will find
    another way.

  2. /platform/ and /resources/ now mark as current for both systems.
    Replacing the hardcoded eq $product "platform" clause with a rule means
    stating one: a page outside any versioned product has no older
    counterpart. Previously Coveo said stale for both and Algolia said current
    for platform only.

Verification

npx hugo --quiet                                    # exit 0
node .ci/scripts/check-feedback-links.js            # all checks passed
node --test 'assets/js/__tests__/*.test.mjs'        # 13 pass, 0 fail
run-e2e-specs --spec cypress/e2e/content/article-feedback.cy.js   # 16/16
run-e2e-specs --spec cypress/e2e/content/page-context.cy.js       # 13/13
yarn validate:agent-instructions                    # valid

Checked the rendered public/ output for all 16 product sections plus
/platform/ and /resources/, comparing the latest, docsearch:latest,
docsearch:searchTag, data-search-tag, data-include-flux, and
data-include-resources values against the pre-refactor build.

Note for anyone diffing rendered HTML here: Hugo minifies in production and
drops quotes around attribute names, so grep '<meta name="latest"' finds
nothing. Match name="?latest"? instead.

One exception, deliberate

The Algolia search tag in header/search-attributes.html stays path-derived
and is commented as such. It is the key Algolia indexed all 53,135 records
under, and content_path does not reproduce it for the five products whose
content path omits the version segment (telegraf, chronograf, kapacitor,
flux, enterprise_influxdb). The documented rule carries this exception so a
later cleanup does not orphan those records.

@jstirnaman
jstirnaman requested a review from a team as a code owner July 27, 2026 22:16
@jstirnaman
jstirnaman requested review from sanderson and removed request for a team July 27, 2026 22:16
@github-actions

Copy link
Copy Markdown
Contributor

Vale Style Check Results

Metric Count
Errors 0
Warnings 0

Check passed

@github-actions

Copy link
Copy Markdown
Contributor

Release version check

No release-notes pages with a tracked version changed in this PR.

💡 Badge new features with the version

Documenting a new feature? Add a version badge in the page frontmatter — the
same mechanism used elsewhere in the docs:

  • metadata: [InfluxDB 3 Core v3.11+] — badge list under the page title
  • updated_in: v3.11 — an "Updated in v3.11" badge
  • introduced: v3.11 — a "‹Product› v3.11+" badge
  • menu.params.state: new — a "NEW" pill on the sidebar nav item

For inline version text, use {{< latest-patch >}} / {{< current-version >}},
which read the value from data/products.yml so it stays correct automatically.

feedback.html derives the product key from the URL path, with special
cases for InfluxDB 3 and Cloud (TSM). /telegraf/controller/ and
/telegraf/enterprise/ hit no special case, so both resolved to the
`telegraf` entry and rendered its name and its public issue-tracker
button.

Telegraf Controller and Telegraf Enterprise are licensed products. Like
every other licensed product, they should point customers to support
rather than a public tracker. Resolve them to their own products.yml
entries, which declare no product_issue_url, so the button does not
render.

The pages now also name the product they document in the feedback text.
Add both URLs to the licensed list in article-feedback.cy.js, along with
/influxdb3/cloud/, which was missing from it.
Search result labels were built by concatenating the product and version
URL segments through two hardcoded maps. The URL segment is not the
product name: /influxdb3/cloud-dedicated/, /influxdb3/cloud-serverless/,
and /influxdb3/clustered/ rendered as "InfluxDB 3 Cloud Dedicated",
"InfluxDB 3 Cloud Serverless", and "InfluxDB 3 Clustered". Their names
are "InfluxDB Cloud Dedicated", "InfluxDB Cloud Serverless", and
"InfluxDB Clustered".

Hugo already passes data/products.yml into the browser bundle as a
js.Build param, so take the names from there. Add
utils/product-labels.js, which maps a URL path to a product by matching
whole content_path segments, longest path first. Whole-segment matching
keeps /influxdb3/cloud/ from matching /influxdb3/cloud-dedicated/, and
longest-first keeps /telegraf/ from matching /telegraf/controller/.

Add the missing content_path for telegraf_controller and
telegraf_enterprise. Both publish content and both are in the search
index. getProductLabelMap() in .github/scripts/workflow-utils.js also
reads content_path but requires label_group, which neither product has,
so GitHub labeling is unchanged.

Replaces the product-scoped override map added for /influxdb3/cloud/,
which products.yml now covers.
@jstirnaman
jstirnaman force-pushed the refactor-search-labels-from-products branch from 0500a53 to 1dd0903 Compare July 28, 2026 13:57
@jstirnaman
jstirnaman force-pushed the refactor-layouts-product-data branch 2 times, most recently from 0bdeeb8 to bef595a Compare July 28, 2026 14:06
@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

🔗 Link Check Results — Link Check Bot

All links are valid

Metric Value
Files Checked 8
Total Links 3108
Errors 0
Warnings 12
Success Rate 99.16345%
⚠️ 12 warning(s) (do not fail CI)
Source File URL Issue
content/enterprise_influxdb/v1/introduction/installation/single-server/_index.md https://support.influxdata.com/ Network error: SSL certificate not trusted. Use --insecure if site is trusted (e…
content/influxdb/v1/introduction/install/_index.md https://reddit.com/r/influxdb Error (cached)
content/influxdb/v1/introduction/install/_index.md https://support.influxdata.com/ Error (cached): Error (cached)
content/influxdb/v2/install/_index.md https://support.influxdata.com/ Network error: SSL certificate not trusted. Use --insecure if site is trusted (e…
content/influxdb/v2/install/_index.md https://docs.docker.com/engine/reference/run/#detached-vs-foreground Cannot find fragment: Cannot find fragment
content/influxdb3/core/install/_index.md https://support.influxdata.com/ Error (cached): Error (cached)
content/influxdb3/core/install/_index.md https://reddit.com/r/influxdb Error (cached)
content/influxdb3/enterprise/install/_index.md https://support.influxdata.com/ Network error: SSL certificate not trusted. Use --insecure if site is trusted (e…
content/influxdb3/explorer/install/_index.md https://support.influxdata.com/ Network error: SSL certificate not trusted. Use --insecure if site is trusted (e…
content/telegraf/v1/install/_index.md https://reddit.com/r/influxdb Error (cached)
content/telegraf/v1/install/_index.md https://support.influxdata.com/ Network error: SSL certificate not trusted. Use --insecure if site is trusted (e…
content/telegraf/v1/install/_index.md https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/starting-windows-powershell… Cannot find fragment: Cannot find fragment

Full details: workflow run summary and artifact. Last updated: 2026-08-19 17:49:18 UTC

Five templates inferred a product by parsing the URL path, then branched
on hardcoded lists of product and version names. The inference is wrong
under /influxdb3/, where the path segment is `influxdb3` but the
products.yml keys are `influxdb3_core`, `influxdb3_cloud`, and so on, so
the lookup always missed and each template papered over it with its own
list.

The lists drifted. `header/coveo-meta-data.html` and
`header/search-attributes.html` both decided "is this page current", with
different lists. InfluxDB 3 Explorer and Telegraf Controller were current
for Algolia and stale for Coveo.

Resolve the product from the cascade `product` param instead, which every
product section already declares. Add product/get-context.html for the
lookup and product/is-latest.html for the shared currency rule, so the two
search systems cannot disagree again.

Move the branching facts into data/products.yml:

  supports_flux              influxdb, influxdb_cloud, enterprise_influxdb
  search_includes_resources  false for the six InfluxDB 3 products
  has_support_contract       false for chronograf, kapacitor

Set `latest` on telegraf_controller and telegraf_enterprise to their
version path segment, matching every other product. Both had `latest: 1.0`
unquoted, which YAML parses as a float and Hugo renders as "1", so the
currency check could never match. `latest_patch: 1.0.1` still carries the
release version.

The search tag stays path-derived. It is the key Algolia indexed every
record under, and content_path does not reproduce it for the five products
whose content path omits the version segment.

No product names remain in the touched templates.
Templates operate on data and stay ignorant of the values in that data.
A product name, version segment, or products.yml key must never appear as
a string literal in template logic, so renaming or adding a product never
requires a template edit.

Document the banned shapes, the three replacements (a per-product field in
data/products.yml, product/get-data.html or product/get-context.html for
resolution, one shared partial for a decision two templates make), and the
incident that motivated it: coveo-meta-data.html and search-attributes.html
each kept their own list for the same question, the lists drifted, and
InfluxDB 3 Explorer and Telegraf Controller were current for one search
system and stale for the other.

Carve out one exception. A value that must match an external system rather
than a product fact stays as it is, with a comment saying why. The Algolia
search tag is path-derived because Algolia indexed every record under the
crawled URL, and a well-meaning cleanup would orphan those records.

Rule lives in .agents/instructions/layouts.md, how-to in the
hugo-template-dev skill, one-line constraint in AGENTS.md. The three
adapters are regenerated by yarn build:agent:instructions.
@jstirnaman
jstirnaman force-pushed the refactor-layouts-product-data branch from bef595a to 175a434 Compare August 19, 2026 17:15
What changed:
Represent Telegraf Controller and Enterprise paths explicitly and preserve singleton path mappings across search labels and Hugo rendering.
Add regression coverage for the generated corpus paths and labels.

Why:
The AI artifact build appended /v1 to unversioned Telegraf routes and failed when writing llms-full.txt.

Impact:
AI artifact generation now publishes Controller and Enterprise corpora at their real URL roots without changing their search labels.

Verification:
Ran focused Node tests, ESLint, Prettier, TypeScript build, Hugo build and server checks, the complete AI artifact pipeline with coherence validation, feedback-link validation, and the article-feedback Cypress spec.
@jstirnaman
jstirnaman changed the base branch from refactor-search-labels-from-products to master August 19, 2026 17:58
@jstirnaman
jstirnaman merged commit 25218e9 into master Aug 19, 2026
30 checks passed
@jstirnaman
jstirnaman deleted the refactor-layouts-product-data branch August 19, 2026 18:03
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.

2 participants