[SEO] /resources/ template fixes — 4 defects multiplying across ~117 live + ~165 planned pages
Repo cible : kestra-io/docs (issue) · Label suggéré : seo, website
Audit source : /resources/data/change-data-capture (live), 2026-07-06 — every finding verified against the rendered HTML and the generated JSON-LD. All four defects are template-level: fixing them once fixes every existing /resources/ page and every page of the upcoming programmatic batch (~165 pages starting W2, 6+/week cadence).
Context
The SEO programmatic pipeline is about to scale /resources/ from ~117 to ~280 pages. Four defects live in the shared template/components, so their cost multiplies with every page shipped. Fixing them before the batch starts is 4 PRs; fixing them after is 4 PRs + nothing, actually — that's the point: zero per-page rework, which is why this is worth prioritizing now.
1. Article JSON-LD is incomplete (E-E-A-T)
Current output (verified on change-data-capture):
{ "@type": "Article", "@context": "...", "headline": "...", "description": "...",
"datePublished": "2026-05-02T00:00:00.000Z", "publisher": {...}, "mainEntityOfPage": {...} }
Missing: author, dateModified, image.
Fix:
author: default to the Kestra Organization node (already emitted on the page — reference it by @id); support an optional author front-matter field for a Person later.
dateModified: derive from git last-modified of the source file (or a front-matter lastUpdated), fall back to datePublished.
image: reference the OG image (see item 3).
- Bonus: a visible byline/updated-date on the page would reinforce the same E-E-A-T signal for humans and LLMs.
Acceptance: Article JSON-LD on any /resources/ page contains the 3 fields; Google Rich Results Test shows no missing-field warnings.
2. <title> suffix has two owners → duplication OR overflow
Current behavior: the template unconditionally appends | Kestra to metaTitle. Result, verified live:
- Pages whose
metaTitle already includes the suffix (house convention in the content pipeline) render … | Kestra | Kestra (e.g. change-data-capture live today).
- Pages whose
metaTitle omits it can overflow: the pending rewrite (docs#5070) renders at 76 chars — truncated in SERP (~60).
- Side effect:
twitter:image:alt / og:image:alt inherit the doubled title.
Fix (decision needed, then 1 line): pick ONE owner of the suffix. Recommendation: the template appends it (guarantees consistency), front-matter metaTitle must never include it, and the content pipeline enforces ≤ 51 chars for the front-matter value (51 + 9 = 60). We will align the pipeline's INSTRUCTIONS.md on whichever decision is made.
Acceptance: exactly one | Kestra on every page; <title> ≤ 60 chars on pages meeting the 51-char content rule.
3. og:image is site-generic (+ type mismatch)
Current output:
<meta property="og:image" content="https://kestra.io/og-image.png">
<meta property="og:image:type" content="image/svg+xml"> <!-- mismatch: file is .png -->
Fix:
- Support an optional front-matter field (e.g.
ogImage) with per-page image, falling back to the site default.
- Fix
og:image:type to match the actual served file.
- (Content side: we'll generate per-page OG images for the priority pages once the field exists — the field is the blocker.)
Acceptance: a page with ogImage set serves it in og:image + twitter:image; type matches; fallback unchanged elsewhere.
4. FAQ accordion renders questions as H2 → broken heading hierarchy
Current output (component accordion-header, verified: 6 occurrences on the audited page):
<h2 data-usal="fade-r">Frequently asked questions</h2>
...
<h2 class="accordion-header"><button class="accordion-button" ...>What is the difference between ETL and CDC?</button></h2>
Every FAQ question sits at the same level as the section heading itself — on every /resources/ page with a faq: front-matter.
Fix: in the accordion component, render question headers as <h3> — or as a non-heading element (<div role="heading" aria-level="3"> or plain <div>): the FAQPage JSON-LD already carries the Q&A semantics, the visual style is class-driven anyway.
Acceptance: one H2 per FAQ section ("Frequently asked questions"), questions below it in the hierarchy; no other heading-order regression (checkable with any a11y/SEO crawler).
Related (already reported, for grouping if convenient)
- Sitemap
stories section: ~26 duplicated-slug URLs returning 404.
/vs/* pages absent from the sitemap.
- (Item 2 above supersedes the earlier "double | Kestra" report — same root cause, now fully characterized.)
Suggested order
2 (one-liner + decision) → 4 (component, small) → 1 (schema, small-medium) → 3 (new front-matter field, medium). Items 1+3 share the image plumbing — can be one PR.
[SEO] /resources/ template fixes — 4 defects multiplying across ~117 live + ~165 planned pages
Repo cible :
kestra-io/docs(issue) · Label suggéré : seo, websiteAudit source :
/resources/data/change-data-capture(live), 2026-07-06 — every finding verified against the rendered HTML and the generated JSON-LD. All four defects are template-level: fixing them once fixes every existing /resources/ page and every page of the upcoming programmatic batch (~165 pages starting W2, 6+/week cadence).Context
The SEO programmatic pipeline is about to scale /resources/ from ~117 to ~280 pages. Four defects live in the shared template/components, so their cost multiplies with every page shipped. Fixing them before the batch starts is 4 PRs; fixing them after is 4 PRs + nothing, actually — that's the point: zero per-page rework, which is why this is worth prioritizing now.
1. Article JSON-LD is incomplete (E-E-A-T)
Current output (verified on change-data-capture):
{ "@type": "Article", "@context": "...", "headline": "...", "description": "...", "datePublished": "2026-05-02T00:00:00.000Z", "publisher": {...}, "mainEntityOfPage": {...} }Missing:
author,dateModified,image.Fix:
author: default to the KestraOrganizationnode (already emitted on the page — reference it by@id); support an optionalauthorfront-matter field for aPersonlater.dateModified: derive from git last-modified of the source file (or a front-matterlastUpdated), fall back todatePublished.image: reference the OG image (see item 3).Acceptance: Article JSON-LD on any /resources/ page contains the 3 fields; Google Rich Results Test shows no missing-field warnings.
2.
<title>suffix has two owners → duplication OR overflowCurrent behavior: the template unconditionally appends
| KestratometaTitle. Result, verified live:metaTitlealready includes the suffix (house convention in the content pipeline) render… | Kestra | Kestra(e.g. change-data-capture live today).metaTitleomits it can overflow: the pending rewrite (docs#5070) renders at 76 chars — truncated in SERP (~60).twitter:image:alt/og:image:altinherit the doubled title.Fix (decision needed, then 1 line): pick ONE owner of the suffix. Recommendation: the template appends it (guarantees consistency), front-matter
metaTitlemust never include it, and the content pipeline enforces ≤ 51 chars for the front-matter value (51 + 9 = 60). We will align the pipeline's INSTRUCTIONS.md on whichever decision is made.Acceptance: exactly one
| Kestraon every page;<title>≤ 60 chars on pages meeting the 51-char content rule.3. og:image is site-generic (+ type mismatch)
Current output:
Fix:
ogImage) with per-page image, falling back to the site default.og:image:typeto match the actual served file.Acceptance: a page with
ogImageset serves it in og:image + twitter:image; type matches; fallback unchanged elsewhere.4. FAQ accordion renders questions as H2 → broken heading hierarchy
Current output (component
accordion-header, verified: 6 occurrences on the audited page):Every FAQ question sits at the same level as the section heading itself — on every /resources/ page with a
faq:front-matter.Fix: in the accordion component, render question headers as
<h3>— or as a non-heading element (<div role="heading" aria-level="3">or plain<div>): the FAQPage JSON-LD already carries the Q&A semantics, the visual style is class-driven anyway.Acceptance: one H2 per FAQ section ("Frequently asked questions"), questions below it in the hierarchy; no other heading-order regression (checkable with any a11y/SEO crawler).
Related (already reported, for grouping if convenient)
storiessection: ~26 duplicated-slug URLs returning 404./vs/*pages absent from the sitemap.Suggested order
2 (one-liner + decision) → 4 (component, small) → 1 (schema, small-medium) → 3 (new front-matter field, medium). Items 1+3 share the image plumbing — can be one PR.