Skip to content

fix(docs): give each page its own description and canonical URL, and stop layout shifts - #443

Merged
erkamyaman merged 1 commit into
mainfrom
claude/blissful-shannon-m0cnu9
Nov 5, 2026
Merged

erkamyaman merged 1 commit into
mainfrom
claude/blissful-shannon-m0cnu9

Conversation

@erkamyaman

@erkamyaman erkamyaman commented Nov 2, 2026 •

Copy link
Copy Markdown
Member

What and why

An SEO audit of the docs site (57 prerendered pages) found four problems:

Problem Before After
Meta description All 57 pages had the homepage description (also in og:description and twitter:description); Analog's markdown routes drop the frontmatter description Each docs page has its own; only the homepage, sponsors and 404 use the site's
Canonical URL No page had one, and og:url was the homepage on every page Every page has <link rel="canonical"> and a matching og:url, without a trailing slash, as the sitemap lists them
Redirects The live site answers every link and sitemap URL with a 307 to the trailing-slash form, where the client briefly renders the homepage before the page Workers serve /guide from guide/index.html (html_handling: "drop-trailing-slash"); /guide/ redirects to it
Layout shift Screenshots were an empty placeholder filled in by the browser, so they pushed the page down: desktop CLS about 0.2 <ngmd-image> renders its <figure><img> at build time with the image's width and height; CLS 0.04 to 0.08

Also: kitchen-sink (frontmatter noIndex) was already out of the sitemap but had no noindex tag, so it now gets robots: noindex.

How:

  • page-meta.plugin.ts adds each markdown page's frontmatter description and noIndex to the virtual:ngmd/page-meta map.
  • A new PageMetaService, called from the title strategy on every navigation, sets the description, canonical link, og:url, og:title, twitter:title and robots.
  • image-sizes.ts reads PNG and JPEG sizes from public/ during the build. The image extension writes them on the <img>. MediaEnhancer no longer builds images, only video iframes.

Already fine, no change: unique titles, one <h1> per page, robots.txt with the sitemap, alt text on every content image (the logos are alt="" and aria-hidden), no broken links (the build's link guards), no orphan pages.

How it was verified

  • pnpm commit:check
  • pnpm format:check
  • pnpm typecheck
  • pnpm docs:test: 110 passed, with new specs for PageMetaService, the image size reader and the image extension
  • pnpm docs:build, then an audit script over the 57 built pages: unique titles and descriptions (except the three pages above), a canonical link on every page, one <h1> each, noindex only on kitchen-sink
  • Core Web Vitals in Chromium on the built site, served like Workers will serve it (no trailing slash):
Page Mobile CLS Desktop CLS LCP
/ 0 0 < 0.5 s
/inspectors/router 0.069 0.044 to 0.053 < 0.9 s
/inspectors/components 0.083 0.051 < 0.6 s
/getting-started/quick-start 0.073 0.056 < 0.7 s

Before, the desktop CLS on pages with a screenshot was 0.17 to 0.22.

Notes for reviewers

  • html_handling only takes effect on the next pnpm docs:deploy.
  • The remaining shift (about 0.05) is <ngmd-hero>, a custom element that renders in the browser and pushes the <h1> down. Prerendering the custom elements would remove it; that's a bigger change and is left out.
  • After the deploy, resubmitting the sitemap in Search Console would get the canonical, redirect-free URLs recrawled sooner.

Generated by Claude Code

Summary by CodeRabbit

  • New Features
    • Documentation pages now include canonical URLs, social sharing metadata, descriptions, and search-engine indexing controls.
    • Images render directly in prerendered pages, with available dimensions, captions, and improved loading behavior.
    • Documentation URLs now use consistent trailing-slash handling.
  • Bug Fixes
    • Canonical URLs omit query strings and fragments, and repeated page updates avoid duplicate canonical links.
    • Unsupported image formats are excluded from image dimension data.

@github-actions github-actions Bot added the area: docs The documentation site label Nov 2, 2026
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: b6bfeb2d-cf8a-4721-92f6-61797137621e
Commits

Reviewing files that changed from the base of the PR and between e173327 and e37306b.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
Walkthrough

The docs changes add dimension-aware image rendering and page-specific metadata. Build-time Markdown extensions receive public image dimensions. Page metadata now supports descriptions and no-index directives, and navigation updates social tags and canonical links.

Changes: Image rendering

Layer / File(s) Summary
Read image dimensions
apps/docs/image-sizes.ts, apps/docs/image-sizes.spec.ts
The new utilities read PNG and JPEG dimensions and map them to slash-normalized public URL paths. Tests cover both formats, unsupported SVG input, and directory scanning.
Render images with dimensions
apps/docs/src/marked-extensions/ngmd-image.ts, apps/docs/src/marked-extensions/runtime.ts, apps/docs/src/marked-extensions/index.ts, apps/docs/src/app/components/media-enhancer.ts, apps/docs/src/marked-extensions/marked-extensions.spec.ts
The image extension now renders a figure and image, with optional dimensions, lazy loading, decoding, and an escaped caption. Build-time extensions receive sizes read from the public directory. Image hydration was removed; video enhancement remains.

Page metadata

Layer / File(s) Summary
Read page metadata
apps/docs/page-meta.plugin.ts, apps/docs/src/vite-env.d.ts
Page metadata now includes optional descriptions and no-index values read from Markdown frontmatter.
Update document metadata
apps/docs/src/app/services/page-meta/page-meta.service.ts, apps/docs/src/app/services/page-meta/page-meta.service.spec.ts
PageMetaService updates social tags, descriptions, robots directives, and canonical links. Tests cover metadata values, fallback descriptions, URL normalization, and canonical-link reuse.
Connect metadata to page navigation
apps/docs/src/app/title-strategy.ts, apps/docs/wrangler.jsonc
The title strategy sends page URLs and titles to PageMetaService. Wrangler asset handling now drops trailing slashes.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant NgmdTitleStrategy
  participant PageMetaService
  participant document
  NgmdTitleStrategy->>PageMetaService: setPage(url, title)
  PageMetaService->>document: update social, description, robots, and canonical metadata
Loading

Suggested labels: area: docs

Suggested reviewers: santoshyadavdev

Merge Risk: Low · previous review e1733

Some builds or image URLs can still produce avoidable layout shifts. These are bounded issues that can be addressed before or shortly after merging.

Pre-merge checks: Passed 5

Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title names the two main changes, per-page description and canonical URL, plus stopping layout shifts. The changeset covers all three: PageMetaService and page-meta.plugin.ts for description and c…
Docstring Coverage Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentati…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title names the two main changes, per-page description and canonical URL, plus stopping layout shifts. The changeset covers all three: PageMetaService and page-meta.plugin.ts for description and canonical URL, and image-sizes/ngmd-image for layout shifts. The title is specific, but it is long at 87 characters and bundles three themes, so it is not a perfect single-focus title. It still clearly reflects the main changes.

Full details: Docstring Coverage

Explanation

Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 6 functions across 12 files. (1 skipped: 1 unsupported.)

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

Recent review info

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 555bf3ea-fb77-4448-aaab-38b3ff8a746e
Commits

Reviewing files that changed from the base of the PR and between e4ff5c8 and e173327.

Files selected for processing: 13

  • apps/docs/image-sizes.spec.ts
  • apps/docs/image-sizes.ts
  • apps/docs/page-meta.plugin.ts
  • apps/docs/src/app/components/media-enhancer.ts
  • apps/docs/src/app/services/page-meta/page-meta.service.spec.ts
  • apps/docs/src/app/services/page-meta/page-meta.service.ts
  • apps/docs/src/app/title-strategy.ts
  • apps/docs/src/marked-extensions/index.ts
  • apps/docs/src/marked-extensions/marked-extensions.spec.ts
  • apps/docs/src/marked-extensions/ngmd-image.ts
  • apps/docs/src/marked-extensions/runtime.ts
  • apps/docs/src/vite-env.d.ts
  • apps/docs/wrangler.jsonc

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

@nx-cloud

nx-cloud Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit e37306b

Command Status Duration Result
nx affected -t test build ✅ Succeeded 1m 46s View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-11-05 10:28:08 UTC

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Failed ❌

View logs ↗
e37306b 2026-11-05T10:26:34.132Z View logs ↗
  • Build: Failed ❌

View logs ↗
e173327 2026-11-02T14:56:13.953Z View logs ↗

@coderabbitai coderabbitai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • Fix comments: Fix CodeRabbit comments on this PR

Comment thread apps/docs/image-sizes.ts Resolved
…stop layout shifts

Every page shipped the homepage description, og:description and og:url,
and none had a canonical link, because Analog's markdown routes drop the
frontmatter description. The page-meta map now carries each page's
description and noIndex, and the title strategy sets the description,
canonical link, og:url and social titles on every navigation. Pages with
`noIndex` get `robots: noindex`, so the kitchen sink stays out of search.

The live site answered every link and sitemap URL with a 307 to its
trailing-slash form, where the client briefly rendered the homepage
before the page. Workers now serve `/guide` from `guide/index.html`
(`html_handling: drop-trailing-slash`).

`<ngmd-image>` rendered an empty placeholder that the browser filled in
later, so screenshots pushed the page down (desktop CLS about 0.2). It
now renders its figure at build time, with the image's width and height
read from public/, so the image is in the prerendered HTML and its space
is reserved.
@erkamyaman
erkamyaman force-pushed the claude/blissful-shannon-m0cnu9 branch from e173327 to e37306b Compare November 5, 2026 10:24
@erkamyaman

Copy link
Copy Markdown
Member Author

@all-contributors please add @michael-small for bug

@erkamyaman
erkamyaman merged commit afbc3b3 into main Nov 5, 2026
11 of 12 checks passed
@erkamyaman
erkamyaman deleted the claude/blissful-shannon-m0cnu9 branch November 5, 2026 11:43
@allcontributors

Copy link
Copy Markdown
Contributor

@erkamyaman

I've put up a pull request to add @michael-small! 🎉

erkamyaman added a commit that referenced this pull request Nov 5, 2026
…d errors (#456)

Three gaps in the image sizes from #443, found in its review:

- A src with a query or fragment (`/a.png?v=2`) missed its size; the
  lookup now uses the path.
- The public directory came from `URL.pathname`, which keeps `%20` for a
  space, so a checkout path with a space found no images. It now comes
  from `import.meta.dirname`.
- Any error while reading the images was swallowed, so the build could
  emit images without sizes. Only a missing directory is skipped now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: docs The documentation site

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant