fix(csp): allow gethinode.com to embed the demo site#2008
Conversation
The showcase pages on gethinode.com embed demo.gethinode.com in a live preview iframe, but the demo refused to render: it inherited the theme default `frame-ancestors 'self'`, so the browser blocked the cross-origin frame. - Add exampleSite/config/production/params.toml, overriding frame-ancestors for the demo deployment only. The theme default stays 'self', so downstream Hinode sites are unaffected. - Generate the production headers from the exampleSite rather than the main site. Netlify deploys exampleSite/public, so its config is the correct source; the previous netlify.toml was missing the exampleSite CSP entries (cookieyes) and the localized 404 redirects. - Regenerate netlify.toml. Note that this alone does not restore the preview: gethinode.com must also list the demo in its own CSP frame-src directive. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
✅ Deploy Preview for gethinode-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
The block reference from mod-docs, published at demo.gethinode.com/docs/blocks/preview, previews a Wikipedia article and an OpenStreetMap map. Neither host was listed in the demo's own CSP frame-src directive, so the browser blocked both iframes and the page showed two empty boxes. - Add the two hosts to frame-src, under the docs module so they union with the theme's own sources rather than replacing them. - Upgrade mod-blocks to v2.0.3, which fixes the preview component's embedding detection. The same page previews google.com on purpose, to demonstrate a site that refuses to be framed; it sends X-Frame-Options: SAMEORIGIN, and before v2.0.3 that was rendered as a live iframe, so the "blocked" example was itself an empty box rather than the intended screenshot fallback. - Regenerate netlify.toml. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Added: the demo renders previews tooI originally scoped this PR to
The google.com preview is deliberate: the docs use it to demonstrate a site that refuses to be Changes
VerificationBuilt the exampleSite and cross-checked every rendered preview against the regenerated
Follow-up worth consideringThese two sources arguably belong in mod-docs itself — the module that embeds Wikipedia and |
mod-docs v1.15.0 declares the frame-src sources its preview block reference needs, so the demo no longer has to hand-maintain them. Drop the site-level entries and upgrade the modules: - mod-docs v1.14.1 => v1.15.0, which declares *.wikipedia.org and www.openstreetmap.org. - mod-blocks v2.0.3 => v2.1.0, whose preview component now also checks a URL against the frame-src the site itself publishes, and falls back to the screenshot when it is not covered. The generated netlify.toml is unchanged: the two sources are now inherited rather than declared locally, so the published policy is identical. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Updated: inherit the CSP sources from mod-docsBoth follow-ups are released, so the site-level entries I added earlier are gone:
The generated VerifiedBuilt the exampleSite with the released modules: No preview warnings, and Net effect of this PR
|
|
🎉 This PR is included in version 3.0.2 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Problem
The live previews on gethinode.com/showcases are broken for
the Hinode (classic), Agency and gethinode.com showcases. Only the AdaptiQ preview
renders; the others fall back to a static screenshot.
The previews are iframes, so both sides of the embed must permit it. This repo owns one of those
sides: demo.gethinode.com (the exampleSite deployment) currently responds with
so the browser refuses to let gethinode.com frame it. AdaptiQ works precisely because it allows
gethinode.com *.gethinode.comin its ownframe-ancestors.config/development/params.tomlalready listsgethinode.com(commented "Production embedding"),so the intent was there — it was simply never mirrored to production.
Change
exampleSite/config/production/params.toml(new) — overrideframe-ancestorsto'self' gethinode.comfor the demo deployment only. The theme default inconfig/production/params.tomlstays'self', so downstream Hinode sites are unaffectedand do not silently inherit a policy allowing gethinode.com to frame them.
package.json— generate the production headers from the exampleSite instead of the mainsite. Netlify deploys
exampleSite/public, so the exampleSite config is the correct source.netlify.toml— regenerated.Regenerating from the exampleSite also restores entries the main-site-derived file was missing,
and which the deployed demo actually serves: the cookieyes CSP entries (
*.cookieyes.com,cdn-cookieyes.com) and the localized 404 redirects.Verification
Regenerated
netlify.tomlnow emits:[build],publishand the plugin config are unchanged.Not sufficient on its own
This restores only the demo's side of the embed. gethinode.com must also add the demo to its own
CSP
frame-src— its current policy blocks the iframe before the request is even made (verifiedvia a live
securitypolicyviolationevent witheffectiveDirective: "frame-src"). Companion PRs:gethinode/gethinode.com— add'self'and*.gethinode.comtoframe-srcgethinode/theme-agency— sameframe-ancestorsfix for the Agency showcase🤖 Generated with Claude Code