diff --git a/packages/cli/src/server/studioServer.ts b/packages/cli/src/server/studioServer.ts index 63daca28e..d7165e2c7 100644 --- a/packages/cli/src/server/studioServer.ts +++ b/packages/cli/src/server/studioServer.ts @@ -481,6 +481,22 @@ export function createStudioServer(options: StudioServerOptions): StudioServer { app.get("/icons/*", serveStudioStaticFile); app.get("/favicon.svg", serveStudioStaticFile); + // ── Runtime env injection ─────────────────────────────────────────────── + // When the studio is served as a pre-built SPA, Vite `VITE_STUDIO_*` env + // vars were baked at build time. Collect any such vars from the current + // process.env and inject them as `window.__HF_STUDIO_ENV__` so the client + // can pick them up at runtime, overriding the baked defaults. + function buildRuntimeEnvScript(): string { + const overrides: Record = {}; + for (const [key, value] of Object.entries(process.env)) { + if (key.startsWith("VITE_STUDIO_") && value !== undefined) { + overrides[key] = value; + } + } + if (Object.keys(overrides).length === 0) return ""; + return ``; + } + // SPA fallback app.get("*", (c) => { const indexPath = resolve(studioDir, "index.html"); @@ -540,7 +556,12 @@ export function createStudioServer(options: StudioServerOptions): StudioServer { 500, ); } - return c.html(readFileSync(indexPath, "utf-8")); + let html = readFileSync(indexPath, "utf-8"); + const envScript = buildRuntimeEnvScript(); + if (envScript) { + html = html.replace("", `${envScript}`); + } + return c.html(html); }); return { app, watcher }; diff --git a/packages/studio/src/components/editor/manualEditingAvailability.ts b/packages/studio/src/components/editor/manualEditingAvailability.ts index bd3b59c5b..c37324730 100644 --- a/packages/studio/src/components/editor/manualEditingAvailability.ts +++ b/packages/studio/src/components/editor/manualEditingAvailability.ts @@ -30,7 +30,16 @@ export function resolveStudioBooleanEnvFlag( // and downstream `env[name]` reads would crash. Fall back to `{}` so // every flag resolves to its declared default outside Vite. Direct // property access keeps Vite's compile-time transform happy. -const env = (import.meta.env ?? {}) as StudioFeatureFlagEnv; +// +// When the studio is served as a pre-built SPA by the embedded Hono server, +// `import.meta.env` values were baked at build time. The server injects +// `window.__HF_STUDIO_ENV__` with any `VITE_STUDIO_*` env vars from the +// user's shell, so runtime overrides take precedence over baked defaults. +const runtimeEnv = + typeof window !== "undefined" + ? ((window as Window & { __HF_STUDIO_ENV__?: StudioFeatureFlagEnv }).__HF_STUDIO_ENV__ ?? {}) + : {}; +const env = { ...(import.meta.env ?? {}), ...runtimeEnv } as StudioFeatureFlagEnv; export const STUDIO_PREVIEW_MANUAL_EDITING_ENABLED = resolveStudioBooleanEnvFlag( env,