feat(studio-server): preview variable injection + render variables forwarding

Fourth PR of the template-variables Studio stack — the HTTP plumbing.

- preview routes (/preview and /preview/comp/*) accept
  ?variables=<url-encoded json> and inject
  `window.__hfVariables = {...}` into <head>, before the runtime and any
  composition script — the exact global the engine sets via
  evaluateOnNewDocument at render time, so preview-with-values cannot
  diverge from render output. Values are escaped against </script>
  breakout, malformed payloads 400 instead of silently previewing
  defaults, and the ETag is salted with a hash of the payload so cached
  previews revalidate when values change.
- POST /projects/:id/render accepts variables ({variableId: value}) and
  forwards them through StudioApiAdapter.startRender into the producer's
  RenderConfig.variables — the same channel `hyperframes render
  --variables` uses. Wired in both adapters (CLI embedded server + vite
  dev adapter).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
James
2026-07-09 13:31:03 -07:00
co-authored by Claude Fable 5
parent 91831f3f8e
commit 2e0b884521
8 changed files with 269 additions and 16 deletions
+2
View File
@@ -48,6 +48,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
format: string;
renderBodyScripts?: string[];
outputResolution?: "landscape" | "portrait" | "landscape-4k" | "portrait-4k";
variables?: Record<string, unknown>;
}) => unknown;
executeRenderJob: (
job: unknown,
@@ -246,6 +247,7 @@ export function createViteAdapter(dataDir: string, server: ViteDevServer): Studi
...(renderBodyScripts.length > 0 ? { renderBodyScripts } : {}),
outputResolution: opts.outputResolution,
...(opts.composition ? { entryFile: opts.composition } : {}),
...(opts.variables ? { variables: opts.variables } : {}),
});
const onProgress = (j: { progress: number; currentStage?: string }) => {
state.progress = j.progress;