-
Notifications
You must be signed in to change notification settings - Fork 8.7k
FEATURE: Full Ember app embed mode for blog comments #36613
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
8d3912a to
b05da07
Compare
Adds a new `fullApp` option to the embed snippet that renders the
complete Discourse Ember application in the iframe instead of the
simplified Rails-templated view.
When enabled:
- Redirects /embed/comments to the topic with ?embed_mode=true
- Hides header, sidebar, and footer in embed mode
- Forces all links to open in new tabs
- Uses scrollable iframe with configurable height (default 600px)
This allows embedded comments to have the full Discourse experience
including likes, reactions, and inline replies.
Usage:
```js
DiscourseEmbed = {
discourseUrl: 'https://forum.example.com/',
discourseEmbedUrl: 'EMBED_URL',
fullApp: true,
// embedHeight: '800px', // optional
};
```
Full app embed mode loads Discourse in an iframe on a different origin. jQuery considers these requests cross-domain and skips the CSRF token header, causing 403 errors on POST/PUT/DELETE requests. This change: - Sends CSRF token even on cross-domain requests when in embed mode - Adds X-Discourse-Embed-Mode header for server-side detection - Allows redirect to topic URL across hosts (needed for dev proxy)
In full app embed mode, clicking links that navigate away from the current topic (user profiles, other topics, etc.) should open in a new tab rather than navigating within the iframe. Uses routeWillChange to intercept Ember transitions and redirect non-topic routes to a new browser window.
The previous approach using routeWillChange didn't work because link clicks were causing full page reloads instead of going through Ember's router. This fix intercepts navigation at two key points: - intercept-click.js: For cooked HTML links, explicitly call preventDefault() and window.open() in embed mode - DiscourseURL.routeTo(): For programmatic navigation, open in new tab except for same-topic navigation (post scrolling) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
Safari's Intelligent Tracking Prevention (ITP) blocks third-party cookies in iframes, preventing logged-in users from being recognized when viewing embedded comments. This adds a prompt for Safari users in embed mode to request storage access via the Storage Access API. Once granted, the page reloads and the session cookie becomes available. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
When users click actions requiring authentication (like, reply, etc.) while in embed mode, the login and signup pages now open in a new tab instead of navigating within the iframe. This is essential for SSO configurations where login redirects to external identity providers.
- Fix logic conflict between intercept-click.js and url.js: removed EmbedMode handling from intercept-click.js so clicks properly flow to DiscourseURL.routeTo() where same-topic navigation is allowed while other navigation opens in new tabs - Extract hardcoded strings in embed-storage-access.js to locale file for i18n support - Replace innerHTML with proper DOM element creation for security 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Request specs: - Verify X-Frame-Options header is kept without embed_mode param - Verify X-Frame-Options header is kept with invalid referer - Verify X-Frame-Options header is stripped with valid embeddable host - Verify X-Frame-Options header is stripped with embed_any_origin setting System specs: - Verify embed-mode class is applied to body with embed_mode=true - Verify embed-mode class is not applied without the param - Verify suggested topics are hidden in embed mode - Verify topic content loads without JS errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
frontend/discourse/app/instance-initializers/embed-storage-access.js
Outdated
Show resolved
Hide resolved
frontend/discourse/app/instance-initializers/embed-storage-access.js
Outdated
Show resolved
Hide resolved
| import EmbedMode from "discourse/lib/embed-mode"; | ||
| import { i18n } from "discourse-i18n"; | ||
|
|
||
| function isSafari() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have an isSafari function on the capabilities service already.
But also, is this even required on desktop Safari? I tried the demo, it popped up the Discourse permission box, I clicked ok... and then nothing happened? I didn't see any browser permission dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have ITP enabled on your Safari ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Use dialog service instead of vanilla JS for storage access prompt - Use capabilities.isSafari instead of custom function - Remove unnecessary allow_other_host: true from redirect
The old detection method using HTMLElement Constructor test and Safari push notification object no longer works on modern Safari when running inside an iframe. Switch to user agent based detection for iframes, which reliably identifies Safari by checking for 'Safari' while excluding 'Chrome' and 'Chromium'.



Summary
Adds a new
fullAppoption to the embed snippet that renders the complete Discourse Ember application in the iframe instead of the simplified Rails-templated view. This allows embedded comments to have the full Discourse experience including likes, reactions, and inline replies.When
fullApp: trueis set:/embed/commentsredirects to the topic URL with?embed_mode=trueDemo
https://discourse-full-embed.pages.dev/embed-test
Usage
Security
The
embed_modeparameter only removes the X-Frame-Options header if:embed_any_originsite setting is enabled, ORThis matches the existing security model for
/embed/comments.