Repository navigation
Description
Summary
After the Notion client loads, it rewrites <link rel="canonical"> and og:url to its own /<Title>-<page-id> path. This happens on every page, including the home page, and replaces the values the worker set. og:url becomes a relative path, which isn't valid for Open Graph (it must be an absolute URL).
The client script already keeps the configured title and description (applyMeta, #146), but not these two tags.
Observed (2026-10-28)
Render check page in wrangler dev, read in Chromium 10 s after load. The result was the same with the worker before and after #192:
| Path | Worker's canonical (server HTML) | After the client loads |
|---|---|---|
/ |
https://render-check.example.com |
canonical https://render-check.example.com/Worknot-Render-Check-3e6558d7de1781bb89a9fb6adc4012d6, og:url /Worknot-Render-Check-3e6558d7de1781bb89a9fb6adc4012d6 |
/3e6558d7de1781258e84de9616a91c0e (no slug) |
https://render-check.example.com/3e6558d7de1781258e84de9616a91c0e (#192) |
canonical https://render-check.example.com/Item-Beta-3e6558d7de1781258e84de9616a91c0e, og:url relative |
Impact
Since #191, crawlers that don't run JavaScript get the server-rendered page, so they see the worker's canonical URL. The client's values still reach:
- crawlers and tools that render JavaScript but don't match the worker's crawler pattern, such as
Google-InspectionTooland SEO auditors that use a Chrome user agent; - Googlebot and Bingbot, if they are ever excluded from the crawler pattern again (see the decision in Serve Notion's server-rendered pages to crawlers #191);
- anything that reads the tags from the live page, such as share buttons and browser extensions.
On the home page, the canonical URL then points to /Worknot-Render-Check-<id>, while the server HTML for that URL names / as canonical. These are conflicting signals for the same page.
Proposed Solution
- In the client script, keep
link[rel=canonical]href,og:urlandtwitter:urlon the worker's canonical URL. Compute it the same way as the server:https://<domain>/<slug>for mapped pages,https://<domain>/<page-id>for pages without a slug (Give pages without a slug their own canonical URL #192), and the bare domain for the home page. - Watch
hrefas well ascontentin the existing headMutationObserver(attributeFilter), and recompute on client-side navigation.
Activity