diff --git a/apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx b/apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx index 1bb9434d06..8609f201d4 100644 --- a/apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx +++ b/apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx @@ -4,6 +4,7 @@ import type { IframeHTMLAttributes } from 'react'; import { forwardRef, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react'; import { observer } from 'mobx-react-lite'; import { connect, WindowMessenger } from 'penpal'; +import { PreloadScriptState } from '@/components/store/editor/sandbox'; import type { Frame } from '@onlook/models'; import type { @@ -86,6 +87,12 @@ export const FrameComponent = observer( const setupPenpalConnection = () => { try { + const sandbox = editorEngine.activeSandbox; + if (sandbox?.preloadScriptState === PreloadScriptState.LOADING) { + console.log(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - Preload script still loading, will retry on next load`); + return; + } + if (!iframeRef.current?.contentWindow) { console.error(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - No iframe found`); onConnectionFailed(); diff --git a/apps/web/client/src/components/store/editor/sandbox/index.ts b/apps/web/client/src/components/store/editor/sandbox/index.ts index 258eacaf37..5de79e56e5 100644 --- a/apps/web/client/src/components/store/editor/sandbox/index.ts +++ b/apps/web/client/src/components/store/editor/sandbox/index.ts @@ -22,6 +22,7 @@ export class SandboxManager { readonly gitManager: GitManager; private providerReactionDisposer?: () => void; private sync: CodeProviderSync | null = null; + private preloadRetryTimeoutId?: ReturnType; preloadScriptState: PreloadScriptState = PreloadScriptState.NOT_INJECTED routerConfig: RouterConfig | null = null; @@ -110,9 +111,13 @@ export class SandboxManager { this.preloadScriptState = PreloadScriptState.INJECTED } catch (error) { console.error('[SandboxManager] Failed to ensure preload script exists:', error); - // Mark as injected to prevent blocking frames indefinitely - // Frames will handle the missing preload script gracefully - this.preloadScriptState = PreloadScriptState.NOT_INJECTED + this.preloadScriptState = PreloadScriptState.NOT_INJECTED; + this.preloadRetryTimeoutId = setTimeout(() => { + if (this.preloadScriptState === PreloadScriptState.NOT_INJECTED) { + console.log('[SandboxManager] Retrying preload script injection...'); + void this.ensurePreloadScriptExists(); + } + }, 3000); } } @@ -214,11 +219,14 @@ export class SandboxManager { } clear() { - this.providerReactionDisposer?.(); - this.providerReactionDisposer = undefined; - this.sync?.release(); - this.sync = null; - this.preloadScriptState = PreloadScriptState.NOT_INJECTED - this.session.clear(); + if (this.preloadRetryTimeoutId) { + clearTimeout(this.preloadRetryTimeoutId); + this.preloadRetryTimeoutId = undefined; + } + this.providerReactionDisposer = undefined; + this.sync?.release(); + this.sync = null; + this.preloadScriptState = PreloadScriptState.NOT_INJECTED + this.session.clear(); } } diff --git a/apps/web/client/src/server/api/routers/project/project.ts b/apps/web/client/src/server/api/routers/project/project.ts index bfece724ee..91604a716b 100644 --- a/apps/web/client/src/server/api/routers/project/project.ts +++ b/apps/web/client/src/server/api/routers/project/project.ts @@ -84,15 +84,16 @@ export const projectRouter = createTRPCRouter({ const url = getSandboxPreviewUrl(branch.sandboxId, port); const app = new FirecrawlApp({ apiKey: env.FIRECRAWL_API_KEY }); - // Optional: Add actions to click the button for CSB free tier - // const _csbFreeActions = [{ - // type: 'click', - // selector: '#btn-answer-yes', - // }]; + const csbFreeActions = [{ + type: 'click', + selector: '#btn-answer-yes', + }]; + const result = await app.scrapeUrl(url, { formats: ['screenshot'], onlyMainContent: true, timeout: 10000, + actions: csbFreeActions, }); if (!result.success) {