From fccc0115c46fb9d174ef9f892a375c97179d43d8 Mon Sep 17 00:00:00 2001 From: platform-mcp Date: Fri, 26 Jun 2026 00:29:32 +0530 Subject: [PATCH] feat: render WRNexus bot widget globally via shared layout Inject the WRNexus bot widget loader (bots/widget.js) once into BaseLayout.astro's so the chat widget appears on every route (pages + blog posts) without per-page duplication. Uses is:inline so Astro does not bundle/transform the external script, preserving the data-bot-id and async attributes. Update CSP in middleware.ts to permit the widget: script-src and connect-src already allowed https://api.wrnexus.com (web-push SDK); added it to frame-src for the widget's iframe. No other directives weakened. Verified: build is clean, widget tag served on /, /about, /contact, and a blog post; widget.js loads 200; zero console CSP violations. Co-Authored-By: Claude Opus 4.8 --- src/layouts/BaseLayout.astro | 6 ++++++ src/middleware.ts | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index f6908d8..30fab04 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -186,6 +186,12 @@ const fullTitle = title === 'Home' ? homeTitle : `${title} | ${brand}`; from rewriting the external src and preserves data-site-id / defer. --> + + + diff --git a/src/middleware.ts b/src/middleware.ts index 3e8649e..812c39a 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -155,7 +155,8 @@ export const onRequest = defineMiddleware(async (context, next) => { // - inline scripts/styles: Required for Astro framework // - https://www.googletagmanager.com & https://www.google-analytics.com: GA4 // - https://plausible.io: Plausible Analytics - // - https://api.wrnexus.com: WRNexus web-push SDK (sdk.js) + runtime config + // - https://api.wrnexus.com: WRNexus web-push SDK (sdk.js), bot widget + // (bots/widget.js) + runtime config/iframe served from the same origin // Note: unsafe-eval is removed in production (only needed during Astro HMR dev mode) const isProduction = import.meta.env.PROD; const scriptSrc = isProduction @@ -172,7 +173,7 @@ export const onRequest = defineMiddleware(async (context, next) => { "worker-src 'self'", "manifest-src 'self'", "object-src 'none'", // Block Flash/plugins (defense-in-depth) - "frame-src https://www.google.com", // Allow Google Maps iframe embed + "frame-src https://www.google.com https://api.wrnexus.com", // Google Maps iframe + WRNexus bot widget iframe "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'",