influxdata / influxdata/docs-v2
Redesign article feedback section for product-aware routing and labels
- Dominant language
- JavaScript
- Stars
- 82
- Forks
- 326
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 82
Description
## Context
#7090 fixed #7089 (wrong feedback button target for InfluxDB 3 Enterprise) with a minimal, behavior-preserving refactor: extract product issue URLs into `data/products.yml` (`product_issue_url` field) so `layouts/partials/article/feedback.html` reads from config instead of computing URLs with conditional logic.
That fix is ready to merge, but subsequent discussion on the PR surfaced a more nuanced routing policy than the original template expressed. The current `product_issue_url` field is too coarse for what real user needs look like, and the hardcoded `Submit issue` button label doesn't fit every destination.
## Correct per-product routing
Per product characteristics (has-public-repo × support-contract-required), feedback button destinations should be:
| Product | Repo? | Contract? | Destination | State after #7090 |
|---|---|---|---|---|
| InfluxDB 3 Core | ✅ `influxdb` | free | GitHub `influxdata/influxdb` | ✅ correct |
| InfluxDB 3 Enterprise | ❌ | optional | **Discord** (preferred channel per feedback template) | Support ❌ |
| InfluxDB 3 Explorer | ❌ | optional | **Discord** (preferred channel) | GitHub `influxdata/influxdb` ❌ |
| InfluxDB 3 Cloud Serverless | ❌ | optional | **Slack** (preferred channel for non-v3-monolith) | Support ❌ |
| InfluxDB 3 Cloud Dedicated | ❌ | **required** | Support site | ✅ correct |
| InfluxDB 3 Clustered | ❌ | **required** | Support site | ✅ correct |
| InfluxDB OSS v1/v2 | ✅ `influxdb` | free | GitHub `influxdata/influxdb` | ✅ correct |
| InfluxDB Cloud (TSM) | ❌ | optional | **Slack** (preferred channel) | Support ❌ |
| Telegraf | ✅ `telegraf` | optional | GitHub `influxdata/telegraf` | ✅ correct |
| Chronograf | ✅ `chronograf` | free | GitHub `influxdata/chronograf` | ✅ correct |
| Kapacitor | ✅ `kapacitor` | free | GitHub `influxdata/kapacitor` | ✅ correct |
| InfluxDB Enterprise v1 | ❌ | **required** | Support site | ✅ correct |
| Flux | ✅ `flux` | free | GitHub `influxdata/flux` | ✅ correct |
**Incorrect after #7090:** v3 Enterprise, v3 Explorer, Cloud Serverless, Cloud (TSM) — 4 products.
"Preferred channel" refers to the existing conditional in `layouts/partials/article/feedback.html`:
```hugo
{{ if and (eq $product "influxdb3") (or (eq $version "core") (eq $version "enterprise") (eq $version "explorer")) }}
Discord (Preferred)
{{ else }}
Slack (Preferred)
{{ end }}
```
So for v3 monolith products (Enterprise, Explorer) Discord is preferred; for v3 distributed + Cloud (TSM), Slack is preferred.
## Button label mismatch
The third feedback button hardcodes `Submit {{ $productName }} issue`. This label fits GitHub and Support destinations, but not Discord, Slack, or Community forum — users don't "submit issues" on Discord, they ask questions. #7090 preserves this label and only changes the URL.
## Product identification bug — `.RelPermalink` vs `.File.Path`
Added during PR review of #7090: the Enterprise "Submit issue" button on the PR preview was observed to link to the preview page URL itself instead of the Support site.
### Root cause
The feedback template identifies the current product by parsing `.RelPermalink`:
```hugo
{{ $productPathData := findRE "[^/]+.*?" .RelPermalink }}
{{ $product := index $productPathData 0 }}
{{ $version := index $productPathData 1 }}
```
Hugo's `.RelPermalink` returns the page URL path **relative to the baseURL's host**, so it **includes any path prefix from `baseURL`**. The PR preview builds with:
```
--baseURL https://influxdata.github.io/docs-v2/pr-preview/pr-7090/
```
For `content/influxdb3/enterprise/get-started/_index.md`, this makes `.RelPermalink = /docs-v2/pr-preview/pr-7090/influxdb3/enterprise/get-started/`. The `findRE` then assigns:
- `$product = "docs-v2"` (wrong)
- `$version = "pr-preview"` (wrong)
- `$productKey = "docs-v2"` → lookup in `data/products.yml` returns nil
- `$productIssueUrl = ""` → empty `href=""` → browser resolves to current page URL
### This is pre-existing, not a regression from #7090
The pre-#7090 template used the same `findRE "[^/]+.*?" .RelPermalink` pattern. In the pre-refactor code, `$product = "docs-v2"` flowed into `$productNamespace` and produced `https://github.com/influxdata/docs-v2/issues/new/choose/` — a wrong-but-existing URL. The refactor didn't introduce the parsing bug; it changed the failure mode from "wrong URL that happens to resolve" to "empty href that falls back to current page", making the latent bug visibly manifest.
### Why the CI check didn't catch it
`.github/workflows/pr-feedback-links.yml` builds Hugo with the default baseURL (no subpath), so Layer 2 correctly identifies products and verifies hrefs. It never exercises the preview-baseURL code path.
### Is there a reason to keep `.RelPermalink`?
**Arguments for:**
1. **Pages without `.File`** — taxonomy/term pages, paginator pages, pages generated from data files. `.File` is nil on those; `.File.Path` errors. `.RelPermalink` always exists.
2. **Permalink/url frontmatter overrides** — `.RelPermalink` reflects the custom URL.
3. **Shared content via `source:` frontmatter** — does `.File.Path` point to the consumer or the source? Answer: consumer. `.File.Path` = path of the `.md` file that declared `source:`. So shared content works identically with either approach.
**Arguments against:**
1. **Breaks on any non-root baseURL** — observed on PR preview; would fire on any GH Pages subpath deployment, any branch-preview infrastructure, any tunnel that rewrites paths.
2. **Brittle regex.** `findRE "[^/]+.*?"` is hard to reason about. The `.*?` is lazy and effectively matches empty — a single anchor is doing no real work. `findRE "[^/]+"` would be clearer with either path source.
3. **Inconsistent with the rest of the template.** The `pageGithubLink` already uses `.File.Path`. Product detection should use the same signal.
4. **Harder to test.** Layer 2 of the CI check runs Hugo with default baseURL and passes — the bug is invisible to the test unless we deliberately build with a subpath baseURL.
**Verdict: no strong reason to keep `.RelPermalink` as primary source.** The one concern (virtual pages without `.File`) is addressable with a guarded fallback:
```hugo
{{ $path := "" }}
{{ if .File }}
{{ $path = path.Dir .File.Path | string }}
{{ else }}
{{ $path = strings.TrimPrefix site.BaseURL.Path .RelPermalink }}
{{ end }}
{{ $productPathData := findRE "[^/]+" $path }}
{{ $product := index $productPathData 0 }}
{{ $version := index $productPathData 1 }}
```
This:
- Fixes the preview-baseURL bug class
- Preserves behavior on virtual pages via baseURL-stripped `.RelPermalink` fallback
- Uses `.File.Path` consistently with the edit-link logic elsewhere in the same partial
- Replaces the brittle `[^/]+.*?` regex with a clean `[^/]+`
If investigation confirms the feedback partial is only rendered on content pages with `.File`, the fallback could be dropped entirely.
### CI test gap
The current `pr-feedback-links.yml` only runs Hugo with default baseURL. To catch this bug class, the workflow should either:
- Run Layer 2 a second time with `--baseURL https://example.com/subpath/` and verify hrefs still resolve to the expected values; or
- Add a dedicated smoke test that confirms every feedback button on a preview-style build has a non-empty `href` that doesn't end with the current page path.
## Proposed redesign options
### Option A — Add `product_issue_label` field to `products.yml`
```yaml
influxdb3_enterprise:
product_issue_url: https://discord.gg/9zaNCW2PRT
product_issue_label: Ask on Discord
influxdb3_cloud_dedicated:
product_issue_url: https://support.influxdata.com/s/
product_issue_label: Contact InfluxData Support
influxdb3_core:
product_issue_url: https://github.com/influxdata/influxdb/issues/new/choose/
product_issue_label: Submit InfluxDB 3 Core issue
```
Template reads `{{ $productData.product_issue_label }}` with a fallback to `Submit {{ $productName }} issue`.
### Option B — Hide the third button entirely for non-repo products
The community links (Discord, Slack, Community, Reddit) are already rendered in the support section above the button row. Duplicating them as a button adds no value. Products without a repo-or-Support destination would show only `Edit this page` + `Submit docs issue`, which is cleaner.
### Option C — Collapse into `product_help` object with type discrimination
```yaml
product_help:
type: github # or: support | discord | slack | community | hidden
url: https://github.com/influxdata/influxdb/issues/new/choose/
```
Template branches on `type` for label, icon, and aria-label. Most structured but adds complexity.
**Recommendation:** Option A. Lowest churn, composable with existing `product_issue_url`, extends the data-driven pattern from #7090 without reintroducing conditional logic in the template.
## Related cleanup worth bundling
- **Simplify the whole feedback section.** The current block contains: a Yes/No helpfulness widget, a support-resource list (Discord/Slack/Community/Reddit/Support/trial email), and three action buttons (Edit / Submit docs issue / Submit product issue). That's at least 9 distinct CTAs. Most pages probably only need 2–3.
- **Switch product identification from `.RelPermalink` to `.File.Path`** with a baseURL-stripped fallback (see the root-cause section above).
- **Remove the `$supportBlacklist` hardcoded slice** (`chronograf`, `kapacitor`) — data-drivable via a `show_support_contact: false` field per product.
- **Data-drive the preferred-community-channel conditional** — move to `products.yml` as `preferred_community_channel: discord | slack` instead of the inline template check.
- **Extend `check-feedback-links.js` Layer 2** to assert rendered button labels match `product_issue_label` once that field lands, and to run a second pass with a subpath baseURL to catch preview-style regressions.
## Acceptance criteria
- [ ] Every product with a `content_path` in `data/products.yml` routes to the correct destination per the table above
- [ ] Button label matches destination type (no "Submit issue" on Discord/Slack/Community links)
- [ ] `layouts/partials/article/feedback.html` contains no conditional URL or label logic (fully data-driven)
- [ ] Product identification in `feedback.html` uses `.File.Path` (or equivalent baseURL-independent source) so preview-baseURL builds resolve correctly
- [ ] `.ci/scripts/check-feedback-links.js` Layer 2 verifies button labels against `product_issue_label`
- [ ] CI runs Layer 2 a second time with a subpath baseURL to catch `.RelPermalink`-style regressions
- [ ] Feedback section reviewed for CTA overload — drop or consolidate redundant links
- [ ] Visual regression check across one representative page per product, on production AND preview baseURLs
## Related
- #7089 — original bug
- #7090 — partial fix; addresses #7089 and 5 review comments on paid products, but 4 products (v3 Enterprise, v3 Explorer, Cloud Serverless, Cloud TSM) still route incorrectly after merge, and the preview-baseURL parsing bug remains unfixed
- #7094 — agent CI-first verification skill (the decision-tree work would benefit from the preview-baseURL bug and the `findRE "[^/]+.*?"` regex as worked examples of "brittle test passes locally, fails on infrastructure the dev environment doesn't exercise")
Contributor guide
No contributing guide indexed for this repository
Research direction
Read layouts/partials/article/feedback.html and data/products.yml first, then inspect .ci/scripts/check-feedback-links.js and .github/workflows/pr-feedback-links.yml to understand current routing and Layer 2 checks. Done means the accepted routing and labels work for every listed product, product detection survives a subpath baseURL, CI verifies labels and preview-style links, and the feedback section is reviewed for redundant CTAs.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, yaml
- Domain
- ci-cd, documentation
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100