From 7751d3e43ee1abbba9a6cca026be78504f0c5dff Mon Sep 17 00:00:00 2001 From: Diego Imbert <70353967+diegoimbert@users.noreply.github.com> Date: Mon, 24 Aug 2026 08:50:23 +0200 Subject: [PATCH] feat(frontend): warn when COEP blocks cross-origin resources in raw app editor preview (#10328) * feat(frontend): warn when COEP blocks cross-origin resources in raw app editor preview Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Gr3udvsSKYyH6mnDvGDqEE * fix(frontend): hedge COEP toast wording and attach warning on detached preview initial load Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Gr3udvsSKYyH6mnDvGDqEE * chore(frontend): condense COEP warning rationale comment Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Gr3udvsSKYyH6mnDvGDqEE --------- Co-authored-by: Claude Fable 5 --- .../raw_apps/RawAppCoepWarning.svelte | 92 +++++++++++++++++++ .../components/raw_apps/RawAppEditor.svelte | 9 ++ 2 files changed, 101 insertions(+) create mode 100644 frontend/src/lib/components/raw_apps/RawAppCoepWarning.svelte diff --git a/frontend/src/lib/components/raw_apps/RawAppCoepWarning.svelte b/frontend/src/lib/components/raw_apps/RawAppCoepWarning.svelte new file mode 100644 index 0000000000..fca969de27 --- /dev/null +++ b/frontend/src/lib/components/raw_apps/RawAppCoepWarning.svelte @@ -0,0 +1,92 @@ + + + +
+

+ The app editor runs in a cross-origin isolated context (COOP/COEP headers). This is + required for SharedArrayBuffer, which powers the TypeScript language workers and + lets the editor build and preview your frontend live in the browser. +

+

+ A side effect is that the browser refuses to load cross-origin resources (images, scripts, + stylesheets, media…) unless the remote server explicitly opts in with CORS or a + Cross-Origin-Resource-Policy header. Resources from servers that don't are + blocked in the editor preview only. When this is the cause, the browser console shows + ERR_BLOCKED_BY_RESPONSE — a plain 404 or DNS error instead means the URL itself is + broken and will fail on the deployed app too. +

+

+ The deployed app is served without these headers, so the same resources load normally there — + open the deployed app link to verify. If you control the remote server, sending + Cross-Origin-Resource-Policy: cross-origin makes the resource load in the editor too. +

+
+
diff --git a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte index 0778fda4e4..4da35eb253 100644 --- a/frontend/src/lib/components/raw_apps/RawAppEditor.svelte +++ b/frontend/src/lib/components/raw_apps/RawAppEditor.svelte @@ -29,6 +29,7 @@ } from './utils' import { runDomQueryOnHtml, type RawAppDomQuery, type RawAppDomRequester } from './rawAppDom' import InlineElementPrompt from './InlineElementPrompt.svelte' + import RawAppCoepWarning from './RawAppCoepWarning.svelte' import DarkModeObserver from '../DarkModeObserver.svelte' import { getAppliedDarkModeVariant, type DarkModeVariant } from '$lib/darkModeVariant' import RawAppSidebar from './RawAppSidebar.svelte' @@ -351,6 +352,7 @@ let iframe: HTMLIFrameElement | undefined = $state(undefined) const PREVIEW_SHELL_URL = '/ui_builder/app-preview.html' let previewIframe: HTMLIFrameElement | undefined = $state(undefined) + let coepWarning: RawAppCoepWarning | undefined = $state(undefined) let previewIframeLoaded = $state(false) let lastBuild: { css: string; js: string } | undefined = undefined // Detached preview tab/window rendering the same app-preview bundle as the @@ -1164,6 +1166,9 @@ ) { externalPreviewReady = true feedExternalPreview() + // The detached window is cross-origin isolated like the inline preview, + // so blocked external resources warrant the same COEP warning. + coepWarning?.attachTo(externalPreviewWindow) return } @@ -1504,6 +1509,9 @@ win.addEventListener('load', () => { externalPreviewReady = true feedExternalPreview() + // Attach here too: against an artifact that predates the handshake, this + // is the only place the freshly opened window is ever seen loaded. + coepWarning?.attachTo(win) }) } @@ -2539,6 +2547,7 @@ src={PREVIEW_SHELL_URL} class="w-full flex-1 block" > + {#if buildError}