Enable page:metadata hooks for anonymous visitors on public pages#169
Enable page:metadata hooks for anonymous visitors on public pages#169jdevalk wants to merge 1 commit intoemdash-cms:mainfrom
Conversation
The middleware previously skipped runtime initialization entirely for anonymous visitors on public pages, which meant page:metadata plugin hooks never fired for the audience that matters most — search engine crawlers and regular visitors. The runtime is a cached singleton (created once, reused across all requests), so the per-request cost of calling getRuntime() is just a null-check. This change attaches only the two page contribution methods (collectPageMetadata and collectPageFragments) to locals.emdash for anonymous visitors, keeping the optimization of not constructing the full admin locals object. This enables SEO plugins using the page:metadata hook to contribute meta tags, canonical URLs, robots directives, and JSON-LD schema markup for all visitors. Fixes emdash-cms#166 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
|
All contributors have signed the CLA ✍️ ✅ |
|
I have read the CLA Document and I hereby sign the CLA |
|
Hey @jdevalk! Just a heads up — I have an open PR (#119) that fixes the same issue (#118, which is a duplicate of #166). My PR takes a slightly different approach by restructuring the middleware to run the full runtime init for anonymous visitors (skipping only the manifest query), and includes tests and a changeset. @ascorbic — two independent PRs for the same bug here. Would be great if you could take a look and decide which approach you'd prefer, or if there's a combination of both that works best. Happy to adjust ours either way! |
Rework the middleware approach based on CI feedback and PR emdash-cms#169's strategy: keep the anonymous fast-path (avoiding D1 session handling for public pages) but initialize the runtime inside it for page hooks. Changes: - Restore the anonymous fast-path from main (fixes Cloudflare Workers cross-request promise issue that caused smoke test failure) - Initialize runtime inside the fast-path with try-catch for graceful degradation — EmDashHead falls back to base SEO if init fails - Only bind collectPageMetadata/collectPageFragments for anonymous requests (not the full admin handler object) - Add page contribution methods to doInit() path for admin/editor routes too - Fix test DB handle leak (close better-sqlite3 handle in afterEach) - Pass { db } consistently to HookPipeline in all test cases Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
page:metadataandpage:fragmentsplugin hooks fire for all visitorslocals.emdash(not the full admin object), preserving the existing performance optimizationgetRuntime()is just a null-check, so the per-request cost is negligibleProblem
The middleware skips runtime initialization for anonymous visitors on public pages (lines 200–228). This means
EmDashHead'sgetPageRuntime()returnsundefined, and it falls back to base-only SEO contributions. Pluginpage:metadatahooks never fire for search engine crawlers or regular visitors.Fix
After the existing setup check, initialize the cached runtime and attach just
collectPageMetadataandcollectPageFragmentstolocals.emdash. This satisfies the structural check ingetPageRuntime()soEmDashHeadruns plugin hooks for all visitors.Test plan
<head>EmDashBodyStart/EmDashBodyEndwork correctly with the minimal locals objectFixes #166
🤖 Generated with Claude Code