Skip to content

SEO foundations, plus surface the AI story on the home page - #889

Merged
wu-sheng merged 5 commits into
masterfrom
seo-foundations
Jul 31, 2026
Merged

SEO foundations, plus surface the AI story on the home page#889
wu-sheng merged 5 commits into
masterfrom
seo-foundations

Conversation

@wu-sheng

Copy link
Copy Markdown
Member

Why

The site emitted no rel=canonical anywhere, and baseURL was "/". Hugo derives sitemap <loc>, og:url and canonical from baseURL, so the live sitemap contained relative locations:

<loc>/tags/ai/</loc>
<loc>/blog/2026-07-06-horizon-ui-ai-assistant/</loc>

The sitemaps.org spec requires an absolute URL there, which made all 4,704 entries unusable for discovery, and robots.txt (a bare User-agent: *) never advertised the sitemap anyway. Separately, GenAI/LLM monitoring shipped in 10.4 and the Horizon UI AI Assistant landed, but neither appeared on the home page.

SEO

  • baseURLhttps://skywalking.apache.org/. canonifyURLs is off and templates use relURL, so internal links are unchanged; only sitemap/og:url/canonical/RSS gain absolute URLs.
  • layouts/robots.txt — new, advertises the sitemap.
  • layouts/partials/seo/ — canonical, <meta name="description">, en↔zh hreflang, and JSON-LD (Organization, SoftwareApplication, BlogPosting, TechArticle, BreadcrumbList) replacing the internal template's bare itemprop microdata. Wired in through the existing hooks/head-end.html, so the theme stays unforked.
  • Versioned docs. docs.js renders Latest and the newest tag from the same commitId, so e.g. /docs/main/latest/ and /docs/main/v10.4.0/ are the same document at two URLs with nothing saying which is authoritative. The tagged one now canonicalises to /latest/. Keyed on commitId, so it self-corrects at each release. Every version URL stays live and served; older versions self-canonicalise and remain independently indexable.
  • <html lang>. content/zh holds Chinese blog posts but the site is a single Hugo language, so all 113 of them declared lang="en". Derived from the URL instead.
  • Duplicate <title>. Every page but the home page had two — head.html emitted one and all 21 baseof.html templates repeated it. head.html is now the sole owner.
  • data/docs.yml — BanyanDB Latest pointed at dda5b5ed, which is the v0.10.1 tag commit, so /docs/skywalking-banyandb/latest/ served v0.10.1 docs through both the v0.10.2 and v0.10.3 releases. Realigned to v0.10.3.

Home page

  • Hero: "Observability for cloud-native and AI", and a lead that says what the platform does now rather than "collects, analyzes, aggregates and visualizes".
  • New GenAI capability card — latency, traffic, success rate, input/output tokens and estimated cost per provider and model, from SkyWalking, OTLP or Zipkin traces. The grid becomes 3×2: five pillars plus a "See all capabilities" tile, so no card is stranded.
  • "plain language" → "natural language" throughout. Peer products (Dynatrace, Grafana, New Relic, OpenObserve, Arize) all use the latter; "plain language" names a different thing and is not what anyone searches for. Also fixes "Ask your observability", which had no object.
  • Deliberately not branded "AI-native" — SkyWalking is a mature APM that gained AI capabilities, and none of the comparable products make that claim either.
  • The agents card listed ten languages under a "14 language agents" link; now lists eleven (Ruby was missing) and says eleven, which is what data/docs.yml supports.
  • The AI card linked to /blog/ rather than /tags/ai/.

Navigation

  • The 中文资料 dropdown mixed one on-site destination with links to B站 and 掘金. Those platforms are ICP-filed and China-hosted, which this domain is not, so pointing at them from every page worked against the site's own Chinese content. 中文博客 is now a direct link to /zh/; the two accounts moved to the footer. Applied to the navbar and the mobile sidebar, which carried a second copy.
  • The docs section was called four different things — "Projects and Docs" (navbar), "Projects and Documentation" (sidebar), "Documentation" (<title>), "Projects & documentation" (H1). Both nav labels are now "Documentation".
  • /zh/ gains a definitional block above the article list; the site had no Chinese page saying what SkyWalking is. The article list is unchanged.

Fixes

  • The Slack card and footer icon both pointed at http://s.apache.org/slack-invite, which redirects to infra.apache.org/slack.html and only offers self-signup to @apache.org addresses. Both now use the same mailto: to the dev list.
  • .cap-tag declared display:inline-block inside a column flexbox, so every pill stretched to the full card width. Pre-existing.
  • footer.html rendered an empty <i> for links with no iconfont glyph.

Verification

Full local build, hugo exit 0:

check result
pages with rel=canonical 4551 / 4552
<loc> absolute / relative in sitemap 4475 / 0
zh pages reporting zh-CN 113 / 113
English pages wrongly marked zh 0
pages with reciprocal hreflang 106
pages with JSON-LD 4426
JSON-LD parse failures (250-page sample) 0
pages with more than one <title> 0

The one page without a canonical is public/3d-map-app/index.html, the Vite SPA shell, which bypasses Hugo layouts.

Version-canonical spot check:

docs/skywalking-java/v9.6.0/  ->  canonical: .../skywalking-java/latest/   (same commitId)
docs/skywalking-java/v9.5.0/  ->  canonical: .../skywalking-java/v9.5.0/   (self)

200 sampled version-canonical targets all resolve to real built pages.

Notes for reviewers

  • og:locale still reports en on Chinese pages. It comes from Hugo's _internal/opengraph.html, which cannot be overridden; a second tag would only be a conflicting duplicate. Fixing it means replacing that template call with a local partial — deliberately out of scope here.
  • Two home-page links resolve only after docs.js runs in CI: virtual-genai/ (present in skywalking v10.4.0) and horizon-ui/next/operate/ai-assistant/ (present on skywalking-horizon-ui main, and a pre-existing link). Worth a glance on the preview build.
  • CLAUDE.md documents that Latest and the newest version entry must share a commitId — it is now load-bearing, not cosmetic.

wu-sheng added 5 commits July 30, 2026 23:34
The site emitted no rel=canonical anywhere and baseURL was "/", so Hugo
generated relative <loc> values in sitemap.xml. The sitemaps.org spec requires
an absolute URL there, which made all 4704 entries unusable for discovery, and
og:url resolved to "/" on the home page.

- config.toml: baseURL -> https://skywalking.apache.org/. canonifyURLs stays
  off, so internal links are unchanged; only sitemap/og:url/canonical/RSS gain
  absolute URLs.
- layouts/robots.txt: new, advertises the sitemap. Hugo's built-in default
  emitted a bare "User-agent: *" with no Sitemap: directive.
- layouts/partials/seo/meta.html: rel=canonical on every page, a
  <meta name="description"> where the page has real prose, and reciprocal
  en/zh-CN hreflang on the 53 blog posts that exist in both languages.
- layouts/partials/seo/doc-canonical-map.html: docs.js renders `Latest` and the
  newest tag from the same commitId, so e.g. /docs/main/latest/ and
  /docs/main/v10.4.0/ are identical documents at two URLs. The tagged one now
  canonicalises to /latest/. Keyed on commitId equality, so it self-corrects at
  each release. Every version URL stays live and served; older versions
  self-canonicalise and remain independently indexable.
- layouts/partials/seo/lang.html + all baseof templates: content/zh holds
  Chinese blog posts but the site is a single Hugo language, so all 113 of them
  declared lang="en". Derive the tag from the URL instead.
- layouts/partials/seo/schema.html: JSON-LD replacing the internal template's
  bare itemprop microdata - Organization and SoftwareApplication on the home
  page, BlogPosting on posts, TechArticle plus BreadcrumbList on docs.
- content/_index.html: add a description. Without one, Hugo's internal
  opengraph template fell back to .Summary, which scraped the hero SVG
  ("- APACHE SOFTWARE FOUNDATION - OPEN SOURCE - ...") into every social card.
- data/docs.yml: BanyanDB `Latest` pointed at dda5b5ed, which is the v0.10.1 tag
  commit, so /docs/skywalking-banyandb/latest/ served v0.10.1 docs through both
  the v0.10.2 and v0.10.3 releases. Realigned to v0.10.3.

Verified against a full local build: 4551/4552 pages carry a canonical (the
only page without is the Vite 3d-map SPA shell, which bypasses Hugo layouts),
200 sampled version-canonical targets all resolve, 113/113 zh pages and 30
zh_tags pages report zh-CN with no English page mislabelled, and JSON-LD parses
on 391/391 of a random 400-page sample with no dangling @id references.
The site shipped GenAI/LLM monitoring in 10.4 and the Horizon UI AI Assistant,
but neither appeared on the home page, and the Chinese blog was reachable only
from a dropdown it shared with two third-party accounts.

Positioning
- Hero: "the observability platform for cloud-native and AI". The lead drops the
  four-verb opener ("collects, analyzes, aggregates and visualizes") for what the
  platform actually does now, including the GenAI models services call.
- New GenAI capability card: latency, traffic, success rate, input/output tokens
  and estimated cost per provider and model, from SkyWalking, OTLP or Zipkin
  traces (docs/en/setup/service-agent/virtual-genai.md, shipped in v10.4.0).
- The capability grid becomes 3x2: five pillars plus a "See all capabilities"
  tile, so the fifth card is not stranded on a row of its own and the spare slot
  earns an internal link to /docs/.
- "plain language" -> "natural language" throughout. Peer products (Dynatrace,
  Grafana, New Relic, OpenObserve, Arize) all use the latter; "plain language"
  names a different thing (the plain-language writing movement) and is not what
  anyone searches for. Also fixes "Ask your observability", which had no object.
- Deliberately not branded "AI-native": SkyWalking is a mature APM that gained AI
  capabilities, and none of the comparable products make that claim either.
- "A modern APM" -> "An observability platform", so the page stops describing
  itself as two different categories.
- The agents card listed ten languages under a "14 language agents" link. It now
  lists eleven (Ruby was missing) and says eleven, which is what data/docs.yml
  supports.

Navigation
- The 中文资料 dropdown mixed one on-site destination with links to B站 and 掘金.
  Since those platforms outrank skywalking.apache.org on Baidu by construction
  (ICP-filed and China-hosted, which this domain is not), pointing at them from
  every page worked against the site's own Chinese content. 中文博客 is now a
  direct link to /zh/, and the two accounts moved to the footer next to Twitter
  and Slack. Applied to both the navbar and the mobile sidebar, which carried a
  second copy of the same dropdown.
- The docs section was called four different things: "Projects and Docs" in the
  navbar, "Projects and Documentation" in the sidebar, "Documentation" in the
  <title>, and "Projects & documentation" in the H1. Both nav labels are now
  "Documentation", matching the title that search engines index.
- /zh/ gains a definitional block above the article list. The site had no Chinese
  page saying what SkyWalking is, so Chinese search and Chinese AI assistants had
  nothing on this domain to quote. The article list is unchanged.

Fixes
- The Slack card and footer icon both pointed at http://s.apache.org/slack-invite,
  which redirects to infra.apache.org/slack.html and only offers self-signup to
  @apache.org addresses. Both now use the same mailto: to the dev list, which is
  the only route that actually produces an invite.
- The "AI-assisted analysis" card linked to /blog/ rather than /tags/ai/, and
  undersold the feature; retitled to troubleshooting and pointed at the tag page
  the blog's own topic filter uses.
- .cap-tag declared display:inline-block inside a column flexbox, so every pill
  stretched to the full card width. Pre-existing; more visible now that the cards
  are wider.
- footer.html rendered an empty <i> for links with no iconfont glyph, so B站 and
  掘金 fall back to their name as text.

Verified on a full build: 4551/4552 pages carry a canonical, 113/113 zh pages and
30 zh_tags pages report zh-CN, 106 pages carry reciprocal hreflang, JSON-LD parses
across the sample, and every internal link on the home page resolves except the
two docs paths that exist only in versions this working copy has not fetched
(verified present in skywalking v10.4.0 and horizon-ui origin/main).
At 46px in the hero's ~530px text column, "The observability platform for
cloud-native and AI" wrapped to three lines with the last two words alone on the
third, reading as though they had drifted off the heading.

text-wrap: balance is the usual fix but is wrong here — it breaks at the hyphen
in "cloud-native", which is worse. Instead the .accent span is nowrap, so
"cloud-native and AI" stays one unit and the break lands at the phrase boundary
after "for".

Checked for the obvious side effect: at 320/375/390/414/768/1024px the accent
measures 277-403px and document.scrollWidth never exceeds the viewport, so the
nowrap introduces no horizontal scrolling.
Every page but the home page carried two <title> tags: partials/head.html emitted
one and all 21 baseof templates repeated the identical expression. Removed from
the baseofs so head.html is the sole owner.

The home page's <title> was "Apache SkyWalking", which wins brand queries and
nothing else, and could not be changed because the IsHome branch printed
.Site.Title unconditionally. It now honours an optional `seo_title` front-matter
key, set only on content/_index.html; every other page keeps
"Page | Apache SkyWalking".

Also:
- The docs BreadcrumbList still named the section "Projects and Docs" after the
  nav was renamed to "Documentation".
- Trimmed the comments added across this branch down to the constraints a reader
  cannot infer from the code, dropping the narrative ones.
- CLAUDE.md: documented that `Latest` and the newest version entry must share a
  commitId (the canonical rule reads it, and BanyanDB drifted for two releases),
  plus a section on what layouts/partials/seo/ owns and the rules that are easy
  to break — absolute baseURL, single <title>, and content/zh being blog posts
  rather than a translated site.
"The observability platform for cloud-native and AI" needed 610px for its
lead-in against a 530px text column, so between 1024px and 1600px — most desktop
widths — it broke into three lines with a stubby "platform for" in the middle.
Dropping to "Observability for" gives two clean lines at every width measured
(1920 down to 375; a single line at 820px), keeps the 46px size, and matches the
<title> set in the previous commit.

"Apache SkyWalking" opened the lead paragraph in the same grey as the rest of the
sentence; it is now bold in the heading colour.
@netlify

netlify Bot commented Jul 31, 2026

Copy link
Copy Markdown

Deploy Preview for skywalking-website-preview ready!

Name Link
🔨 Latest commit 5fbfbda
🔍 Latest deploy log https://app.netlify.com/projects/skywalking-website-preview/deploys/6a6beafd972b6100081c08e6
😎 Deploy Preview https://deploy-preview-889--skywalking-website-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@wu-sheng
wu-sheng merged commit bfbb98d into master Jul 31, 2026
5 checks passed
@wu-sheng
wu-sheng deleted the seo-foundations branch July 31, 2026 00:31
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.

1 participant