Skip to content

feat(#2996): add SEO metadata to docs site - #6683

Merged
rh-hemartin merged 7 commits into
fullsend-ai:mainfrom
shairevivo:srevivo/2996-docs-seo-metadata
Aug 31, 2026
Merged

feat(#2996): add SEO metadata to docs site#6683
rh-hemartin merged 7 commits into
fullsend-ai:mainfrom
shairevivo:srevivo/2996-docs-seo-metadata

Conversation

@shairevivo

Copy link
Copy Markdown
Contributor

Summary

Closes #2996. Adds SEO metadata to the VitePress docs site so pages are indexed well by search engines and render rich previews when shared on Slack / LinkedIn / X.

  • Sitemapsitemap.xml is now generated at build time (190 URLs). Previously /sitemap.xml fell through to the landing-page HTML.
  • Canonical URLs — every page emits <link rel="canonical">.
  • Open Graph / Twitter Cards — global og:type/og:site_name/og:image + twitter:card/twitter:image, plus per-page og:url/og:title/og:description.
  • Per-page descriptions — unique description frontmatter on key landing pages (getting started, agents overview + each agent, architecture, vision); all other pages fall back to the site description.
  • robots.txt — advertises the sitemap.

The /docs/ base gotcha

The docs are served under base: "/docs/", so every live URL includes that segment (e.g. https://fullsend.sh/docs/agents/triage.html).

The example in the issue hardcoded https://fullsend.sh${relativePath}, which would have produced wrong URLs missing /docs/ in every canonical tag, OG tag, and sitemap entry. Confirmed against the VitePress 1.6.4 source: its sitemap builder emits base-less relative paths and resolves them against sitemap.hostname via new URL(path, hostname). So this PR:

  • sets the sitemap hostname to https://fullsend.sh/docs/ (trailing slash required for correct resolution), and
  • resolves per-page canonical/OG URLs against that same base.

The URL logic is isolated in a pure, unit-tested module (docs/.vitepress/seo.ts + seo.test.ts), mirroring the existing searchScopes.ts pattern. One test is a regression guard asserting every URL includes /docs/.

The 404 page is excluded from self-canonical/og:url so crawlers don't treat the not-found page as indexable.

Testing

  • npx vitest run docs/.vitepress/seo.test.ts — 13 tests pass.
  • Full vitepress build docs — succeeds; 190 sitemap entries, all under https://fullsend.sh/docs/; canonical/OG tags verified in the built HTML for a directory-index page, a content page, the root, and a page without frontmatter (falls back to the site description); 404.html has no self-canonical.

Follow-ups (out of scope)

  • Dedicated 1200×630 social image. og:image currently uses the square brand logo — functional but not ideal for large cards. A purpose-built asset is a one-line change in seo.ts.
  • JSON-LD structured data (nice-to-have in the issue) — omitted to keep this PR focused on the triage-recommended core.

🤖 Generated with Claude Code

Improve search indexing and social sharing for the VitePress docs site
by adding a sitemap, canonical URLs, and Open Graph / Twitter Card tags.

- docs/.vitepress/seo.ts: pure helpers for canonical/OG URLs and head
  tags, unit-tested in seo.test.ts. Docs are served under a /docs/ base,
  so all absolute URLs (canonical, og:url, sitemap) include that segment.
  The sitemap hostname carries the base with a trailing slash because
  VitePress resolves base-less page paths against it.
- config.ts: emit sitemap.xml, global og/twitter head tags, and per-page
  canonical + og tags via transformHead. The 404 page is excluded from
  self-canonical/og:url so crawlers do not treat it as indexable.
- robots.txt: advertise the sitemap location.
- Add unique description frontmatter to key landing pages (getting
  started, agents overview and each agent, architecture, vision); other
  pages fall back to the site description.

Verified with a full vitepress build: 190 sitemap entries, all under
https://fullsend.sh/docs/, with per-page canonical and og tags present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shai Revivo <srevivo@redhat.com>
@shairevivo
shairevivo requested a review from a team as a code owner August 27, 2026 15:09
@github-actions

Copy link
Copy Markdown

E2E tests did not run

E2E tests run automatically for org/repo members and collaborators on pull requests.

For other contributors, a maintainer must add the ok-to-test label after the latest push.

See E2E testing guide for details.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add SEO metadata and sitemap generation to the docs site

✨ Enhancement 📝 Documentation 🧪 Tests ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Generate canonical URLs, sitemap entries, and social metadata under the /docs/ base.
• Add focused descriptions to key documentation landing and agent pages.
• Advertise the sitemap and regression-test URL and metadata generation.
Diagram

graph TD
  Pages["Docs pages"] --> Config["VitePress build"] --> Helpers["SEO helpers"] --> Metadata["Page metadata"] --> Consumers["Search and social"]
  Config --> Sitemap["Sitemap XML"] --> Consumers
  Robots["robots.txt"] --> Sitemap
Loading
High-Level Assessment

The chosen approach is appropriate: centralizing base-aware URL generation in pure helpers keeps sitemap and page metadata consistent, while VitePress-native sitemap and transformHead hooks avoid custom post-build HTML processing. Focused tests provide a strong regression guard for the /docs/ deployment base and 404 behavior.

Files changed (14) +258 / -0

Enhancement (2) +112 / -0
config.tsWire SEO metadata into the VitePress build +15/-0

Wire SEO metadata into the VitePress build

• Registers global social tags, configures sitemap generation with the '/docs/' hostname, and emits per-page canonical and Open Graph tags. Excludes the 404 page from self-canonical metadata.

docs/.vitepress/config.ts

seo.tsAdd reusable VitePress SEO helpers +97/-0

Add reusable VitePress SEO helpers

• Introduces shared constants and pure functions for output paths, canonical URLs, indexability, per-page metadata, and global Open Graph and Twitter tags. Ensures all absolute URLs retain the deployed '/docs/' base.

docs/.vitepress/seo.ts

Tests (1) +107 / -0
seo.test.tsTest canonical URL and metadata generation +107/-0

Test canonical URL and metadata generation

• Covers root, nested index, content, and clean URL path mapping. Adds regression checks for the '/docs/' base, per-page metadata, global social tags, and 404 exclusion.

docs/.vitepress/seo.test.ts

Documentation (10) +37 / -0
README.mdDescribe the agents reference for search previews +4/-0

Describe the agents reference for search previews

• Adds frontmatter summarizing shipped agents and custom agent registration.

docs/agents/README.md

code.mdAdd Code Agent SEO description +4/-0

Add Code Agent SEO description

• Adds a focused description of issue implementation, repository conventions, validation, and branch commits.

docs/agents/code.md

fix.mdAdd Fix Agent SEO description +4/-0

Add Fix Agent SEO description

• Adds a focused description of review-feedback processing, targeted fixes, validation, and commits.

docs/agents/fix.md

prioritize.mdAdd Prioritize Agent SEO description +4/-0

Add Prioritize Agent SEO description

• Adds a focused description of RICE-based issue scoring and ranked prioritization.

docs/agents/prioritize.md

retro.mdAdd Retro Agent SEO description +4/-0

Add Retro Agent SEO description

• Adds a focused description of workflow retrospectives and structured improvement proposals.

docs/agents/retro.md

review.mdAdd Review Agent SEO description +4/-0

Add Review Agent SEO description

• Adds a focused description of pull request evaluation across correctness, security, intent, style, and documentation.

docs/agents/review.md

triage.mdAdd Triage Agent SEO description +4/-0

Add Triage Agent SEO description

• Adds a focused description of issue inspection, clarification, and structured triage decisions.

docs/agents/triage.md

architecture.mdAdd architecture page SEO description +4/-0

Add architecture page SEO description

• Adds frontmatter describing the agent execution stack and its relationship to accepted architectural decisions.

docs/architecture.md

README.mdAdd getting-started SEO description +1/-0

Add getting-started SEO description

• Adds frontmatter summarizing inference, runtime, and GitHub setup for autonomous agents.

docs/guides/getting-started/README.md

vision.mdAdd vision page SEO description +4/-0

Add vision page SEO description

• Adds frontmatter describing autonomous organization-wide development with human strategy and guardrails.

docs/vision.md

Other (1) +2 / -0
robots.txtAdvertise the documentation sitemap +2/-0

Advertise the documentation sitemap

• Adds the generated docs sitemap URL to crawler directives while preserving existing bot policies.

cloudflare_site/public/robots.txt

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

Site preview

Preview: https://fa1996c4-site.fullsend-ai.workers.dev

Commit: dfc872d0373b0f8fd9b12bcfe6bc44bd67022d92

@qodo-code-review

qodo-code-review Bot commented Aug 27, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. SEO description hardcodes agent inventory ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new description presents triage, code, review, fix, retro, and prioritize as the agents
Fullsend ships, creating a static authoritative inventory instead of directing readers to runtime
discovery. This inventory can become stale as agents are added or removed.
Code

docs/agents/README.md[2]

+description: Reference for the agents fullsend ships — triage, code, review, fix, retro, and prioritize — plus how to register custom agents via config.
Relevance

●●● Strong

The metadata explicitly claims a complete shipped inventory, directly violating the cited active
documentation rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2914750 prohibits documentation from presenting a complete static Fullsend agent
inventory. The added metadata explicitly says agents fullsend ships and enumerates all six agent
names.

Rule 2914750: Avoid hardcoded Fullsend agent and skill inventory in documentation
docs/agents/README.md[2-2]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The SEO description hardcodes the complete list of shipped Fullsend agents, contrary to the requirement that documentation use runtime discovery rather than maintain a static inventory.

## Issue Context
Keep the metadata concise without enumerating agent names, and direct the page content to the established discovery mechanism for the `fullsend-ai/agents` repository.

## Fix Focus Areas
- docs/agents/README.md[1-10]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Sitemap indexes ADR template ✓ Resolved 🐞 Bug ≡ Correctness
Description
Enabling the unfiltered sitemap includes ADRs/0000-adr-template.md, even though the existing
navigation logic explicitly classifies 0000-*-template files as non-content. Crawlers are
therefore advertised a placeholder page that also receives a self-canonical and Open Graph metadata.
Code

docs/.vitepress/config.ts[R168-170]

+  sitemap: {
+    hostname: DOCS_URL_BASE,
+  },
Relevance

●●● Strong

Recent accepted precedent excludes the exact ADR template from documentation discovery; sitemap
exposure is the same content-classification issue.

PR-#4020

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The config's isNonContent predicate proves these templates are not intended as content, but it is
used only by sidebar file discovery. The new sitemap has no filter, srcExclude omits templates,
and the SEO guard rejects only 404.md, so VitePress builds and advertises the placeholder ADR with
canonical metadata.

docs/.vitepress/config.ts[10-15]
docs/.vitepress/config.ts[21-45]
docs/.vitepress/config.ts[166-178]
docs/.vitepress/seo.ts[66-88]
docs/ADRs/0000-adr-template.md[1-16]
PR-#4020

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new sitemap publishes the placeholder ADR template as an indexable documentation URL. Excluding it only from sidebar discovery does not prevent VitePress from building it, listing it in `sitemap.xml`, or adding canonical/OG metadata.

## Issue Context
`isNonContent` already recognizes `0000-*-template` files, and `docs/ADRs/0000-adr-template.md` contains placeholder rather than user-facing content. Add an equivalent build-level exclusion so this and future matching templates do not become sitemap entries or SEO pages; retain the existing exclusions.

## Fix Focus Areas
- docs/.vitepress/config.ts[10-15]
- docs/.vitepress/config.ts[166-178]
- docs/ADRs/0000-adr-template.md[1-16]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Guide metadata introduces undefined jargon ✓ Resolved 📜 Skill insight ✧ Quality
Description
The added guide description uses inference, agent runtime, and SDLC agents before defining or
linking those terms. Readers and search-preview users therefore encounter domain-specific
terminology without the required first-use context.
Code

docs/guides/getting-started/README.md[3]

+description: Set up fullsend step by step — get inference, choose an agent runtime, and configure GitHub to start running autonomous SDLC agents on your repos.
Relevance

●●● Strong

Recent guide reviews accepted findings requiring first-use definitions or links for unexplained
domain jargon.

PR-#6455
PR-#5778

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 1062083 requires jargon in documentation guides to be defined inline or linked to
the glossary on first occurrence. The newly added description is now the first occurrence of three
unexplained domain-specific terms in this guide.

docs/guides/getting-started/README.md[3-3]
Skill: writing-user-docs

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The getting-started guide's new metadata introduces domain-specific terms without inline definitions or glossary links on first use.

## Issue Context
Rewrite the description in plain language, or provide appropriate first-use definitions and glossary links in the guide before using `inference`, `agent runtime`, and `SDLC agents`.

## Fix Focus Areas
- docs/guides/getting-started/README.md[1-9]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 62 rules
Review mode: ⚖️ Balanced: This changes build-time configuration and URL-generation logic across sitemap, canonical/OG metadata, robots, and page frontmatter; it has real deployment and indexing impact, but the core logic is sufficiently localized for one careful review.

Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread docs/agents/README.md Outdated
Comment thread docs/guides/getting-started/README.md Outdated
Comment thread docs/.vitepress/config.ts
@codecov

codecov Bot commented Aug 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

- config.ts: exclude template placeholders (0000-*-template.md) from the
  build via srcExclude, mirroring isNonContent's template rule, so they no
  longer appear in sitemap.xml or carry canonical/OG metadata. Previously
  ADRs/0000-adr-template.html was advertised to search engines.
- docs/agents/README.md: rewrite the description to point at runtime agent
  discovery (fullsend-ai/agents repo / config) instead of hardcoding the
  shipped agent names, per the project's discovery-over-inventory convention.
- docs/guides/getting-started/README.md: reword the description in plain
  language, avoiding undefined jargon (inference, agent runtime, SDLC agents).

Rebuilt: sitemap drops the template (190 -> 189 entries), all real pages
retained, new descriptions render correctly; 13 unit tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shai Revivo <srevivo@redhat.com>

@waynesun09 waynesun09 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review sweep on the SEO metadata change: 4 findings (1 high, 3 medium) posted as inline comments. The high one is a serving-layer mismatch — the canonical/og:url/sitemap URL shape this PR emits does not resolve on the host — verified against this PR's own preview deployment at 1bd286a.

Comment thread docs/.vitepress/config.ts Outdated
Comment thread docs/.vitepress/config.ts
Comment thread docs/.vitepress/seo.ts Outdated
Comment thread docs/.vitepress/config.ts Outdated
Signed-off-by: Shai Revivo <srevivo@redhat.com>
@shairevivo

Copy link
Copy Markdown
Contributor Author

Addressed all four review findings in 97e65ad:

  1. Enabled VitePress cleanUrls so canonical, og:url, and sitemap URLs match the 200-serving Cloudflare URL shape instead of redirecting .html URLs.
  2. Canonicalized the /docs/ meta-refresh stub to /docs/guides/getting-started/ and excluded the redirecting root from the sitemap.
  3. Corrected the 404 deployment explanation and added a robots noindex tag to the directly reachable 404 asset; the pre-existing SPA soft-404 behavior remains separate.
  4. Shared the non-content predicate across sidebar discovery, per-page SEO, and sitemap filtering. Template directories and ALL-CAPS metadata pages are excluded, while normal experiment pages remain intentionally public.

Verification: 19 focused tests pass, make lint passes, and a full docs build with the pinned experiments submodule produced 276 sitemap URLs with zero .html, redirect-root, template, or ALL-CAPS metadata entries.

@ralphbean

Copy link
Copy Markdown
Member

/fs-review

@fullsend-ai-review

fullsend-ai-review Bot commented Aug 27, 2026

Copy link
Copy Markdown

🤖 Finished Review · ✅ Success · Started 5:21 PM UTC · Completed 5:37 PM UTC

Commit: ba1656f · View workflow run →

Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.27

@fullsend-ai-review fullsend-ai-review Bot added the risk/moderate PR risk: moderate label Aug 27, 2026
@fullsend-ai-review

Copy link
Copy Markdown

Risk Assessment: moderate (2/5)

Details

Docs-focused SEO enhancement with 14 files (mostly 4-line frontmatter additions), no protected paths or security-sensitive files, linked to a well-scoped issue; moderate churn on some doc files but additive-only changes with comprehensive tests for the new production module.

@fullsend-ai-review

Copy link
Copy Markdown

Review

Findings

Low

  • [edge-case] docs/.vitepress/seo.ts:42 — The template-matching regex ^0000-.*-template$ adds a $ anchor absent in the original isNonContent. The new function strips extensions before testing, so a hypothetical file like 0000-foo-template-v2.md would differ in classification. In practice, only 0000-adr-template.md exists — no current behavior affected.

  • [scope-creep] docs/.vitepress/config.ts:140cleanUrls: true changes the URL structure of every page (.html suffix removed). While VitePress and Cloudflare Workers handle fallbacks transparently, this goes beyond the SEO metadata scope of issue Enhance VitePress docs with SEO metadata for better discoverability #2996. Trivially revertible if needed.

  • [commit-convention] — PR title uses feat(#2996) but SEO metadata is documentation infrastructure, not user-facing capability. Per COMMITS.md, docs(#2996) would be more accurate and would avoid inflating the Features section of release notes.

  • [incomplete-doc] docs/doc-site.md:25 — The "How it works" section describes config.ts as defining "sidebar navigation and markdown processing." This PR adds SEO, sitemap, and clean-URL configuration plus a new seo.ts module — the description is now incomplete.

Comment thread docs/.vitepress/seo.ts
Comment thread docs/.vitepress/config.ts
@fullsend-ai-review fullsend-ai-review Bot added the ready-for-merge All reviewers approved — ready to merge label Aug 27, 2026
- isNonContentPath: drop the trailing $ anchor so the template regex
  matches suffixed names, restoring the original isNonContent semantics.
- Document why cleanUrls is required (matches Cloudflare's 200-serving
  URL shape; canonicals must not point at redirecting .html URLs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Shai Revivo <srevivo@redhat.com>
@rh-hemartin
rh-hemartin added this pull request to the merge queue Aug 31, 2026
Merged via the queue into fullsend-ai:main with commit 92c1d64 Aug 31, 2026
32 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-merge All reviewers approved — ready to merge risk/moderate PR risk: moderate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance VitePress docs with SEO metadata for better discoverability

4 participants