fix: every page claimed to be the homepage, and two WCAG Level A failures - #121
Merged
Merged
Conversation
**211 of 213 pages emitted an identical og:url pointing at the homepage, and none carried rel="canonical".** `hostname` was passed to the standalone sitemapPlugin but never to `defaultTheme()`, and the theme gates BOTH its bundled SEO and sitemap plugins on exactly that value — so the SEO plugin never registered and the only OG tags were a hand-written site-wide block. Two things the audit had wrong, found by reading the installed packages: - `hostname` alone gives per-page `og:*` but **zero** canonicals. `canonical` is a separate option (`getCanonicalLink` returns null without it). - `hostname` must be the bare ORIGIN. All three call sites concatenate `hostname + base`, which is what produced the doubled `/forge_docs/forge_docs/sitemap.xml` in robots.txt. The `<loc>` entries were never affected, because they are written root-relative and the URL resolver discards the hostname's path — verified by diffing all 212 before and after. The manual sitemapPlugin registration is dropped: the theme registers it with the same single option, and running both meant two competing `onGenerated` hooks rewriting robots.txt. | | before | after | |---|---|---| | pages with `rel="canonical"` | 0 | 213 | | distinct `og:url` values | 1 | 213 | | robots.txt sitemap | 404 | resolves | **Skip link**, WCAG 2.4.1 Level A: 324 focusable stops preceded `<main>`, because the whole sidebar renders on every interior page. The pill is hidden by translation rather than `display:none` so it stays in the tab order, and the handler focuses the target explicitly so it works after router hydration and not only on a cold fragment navigation. **Brand link accessible name**, WCAG 4.1.2. The theme hides the `.vp-site-name` span whenever `logoAlt` resolves equal to the title — which is what `logoAlt ?? title` gives when no logo is configured, and this site deliberately configures none. The anchor therefore had no unhidden child and an empty accessible name on every page. An explicit `logoAlt` breaks that equality. This one fell between two agents' ownership: the accessibility work correctly identified it as a config.ts change and reported the exact diff, and the config owner never applied it. Caught by checking the built HTML rather than the reports. **Contrast**: `--vp-c-text-subtle` on `--vp-c-bg-alt` was 4.25:1 in light mode, below the 4.50 AA floor and the only sub-AA pair on the site. Now 4.77:1. **Favicon**: 69,734 bytes at 256x139, fetched on every page load, now 2,181 bytes at 32x32. The first regeneration preserved the logo's aspect ratio and produced a 32x17 icon — square now, caught by checking the file rather than the byte count. **Search index**: the main JS chunk drops from 128K to 79K gzipped. Monaco's CSS is NOT addressed here and the mechanism is worth recording: `@vuepress/bundler-vite` hard-sets `cssCodeSplit: false`, so Vite merges styles reachable only through an async-only chunk into the one render-blocking stylesheet. Monaco is ~162 KB of it, 65.9%. The fix is either overriding that Vite option — which VuePress disables deliberately for SSG style ordering — or loading Monaco's CSS at runtime. Both are larger than this change should carry.
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
211 of 213 pages emitted an identical
og:urlpointing at the homepage, and none carriedrel="canonical".hostnamereached the standalonesitemapPluginbut neverdefaultTheme()— and the theme gates both its bundled SEO and sitemap plugins on exactly that value, so the SEO plugin never registered and the only OG tags were a hand-written site-wide block.rel="canonical"og:urlvalues<loc>entriesTwo things the audit had wrong
Found by reading the installed packages rather than trusting the finding:
hostnamealone gives per-pageog:*but zero canonicals.canonicalis a separate option —getCanonicalLinkreturnsnullwithout it.hostnamemust be the bare origin. All three call sites concatenatehostname + base, which is what produced/forge_docs/forge_docs/sitemap.xml. The<loc>entries were never affected, because they're written root-relative and the URL resolver discards the hostname's path — verified by diffing all 212 before and after.The manual
sitemapPluginregistration is dropped: the theme registers it with the same single option, and running both meant two competingonGeneratedhooks rewritingrobots.txt.Skip link — WCAG 2.4.1, Level A
324 focusable stops preceded
<main>, because the entire sidebar renders on every interior page. The pill is hidden by translation rather thandisplay:noneso it stays in the tab order, and the handler focuses the target explicitly so it works after router hydration, not only on a cold fragment navigation.Brand link accessible name — WCAG 4.1.2
The theme hides
.vp-site-namewheneverlogoAltresolves equal to the title — which is whatlogoAlt ?? titlegives when no logo is configured, and this site deliberately configures none (the PNG has a baked-in white background that reads as a bright box in dark mode). The anchor therefore had no unhidden child and an empty accessible name on every page. An explicitlogoAltbreaks that equality.Worth noting how this nearly shipped: the accessibility work correctly identified it as a
config.tschange and reported the exact diff, the config owner didn't apply it, and both reported success. Caught by checking the built HTML.Contrast, favicon, weight
--vp-c-text-subtleon--vp-c-bg-altwas 4.25:1 in light mode, below the 4.50 AA floor and the only sub-AA pair on the site. Now 4.77:1.Deliberately not fixed
Monaco's CSS. The mechanism is worth recording:
@vuepress/bundler-vitehard-setscssCodeSplit: false, so Vite merges styles reachable only through an async-only chunk into the single render-blocking stylesheet. Monaco is ~162 KB of it — 65.9%, not the 58.6% first reported. The fix is either overriding that Vite option (which VuePress disables deliberately for SSG style ordering) or loading Monaco's CSS at runtime. Both are larger than this change should carry.