Day 1 (monorepo + Node layout engine): - Turborepo + pnpm workspaces with apps/web, apps/render-worker, and packages for types, layout-engine, prompts, api-lib. - @banner-studio/types: BannerSpec contract, every layer kind, ResolvedLayer, zod schemas mirroring each interface. - @banner-studio/layout-engine: Dropflow WASM wrapper, text measurement, shrink-to-fit, push_siblings, resolveLayout. Snapshot-tested. Day 2 (browser parity + AI pipeline): - Layout engine ./browser subpath: same resolveLayout in the browser via Dropflow WASM build. Quarantined wasm-locator import (dropflow 0.5.1 exports gap). - Cross-group push_siblings bug fix: deltas now thread through group recursion via a shared accumulator; regression test added. - DEMO_TEMPLATE_300x250 promoted to packages/layout-engine/src/templates/. - @banner-studio/prompts: versioned extract + generate prompts with zod-defined tool schemas (claude-sonnet-4-6, forced tool-use). - @banner-studio/api-lib: CSV feed loader, extract/generate/route-node/ assemble agents, orchestrator returning fully-resolved BannerSpec. Generate agent retries on character-limit overflow. - apps/web (Next.js 14 App Router): /api/generate route, /parity diff page, promise-singleton browser engine init. - feeds/demo.csv with five hand-authored rows of varied length. - SLICE_DEVIATIONS.md documents the five intentional gaps from ARCHITECTURE.md with V1 reversal paths. Verified end-to-end: POST /api/generate against the live Claude API returns three resolved BannerSpecs and two honestly-skipped rows (overflow after two attempts). 26 unit + integration tests passing.
20 lines
658 B
TypeScript
20 lines
658 B
TypeScript
'use client';
|
|
// Promise-singleton init for the browser layout engine. The first caller
|
|
// kicks off the wasm fetch + font registration; subsequent callers get
|
|
// the same in-flight promise. Survives App Router client navigations.
|
|
|
|
import { initLayoutEngine } from '@banner-studio/layout-engine/browser';
|
|
|
|
let promise: Promise<void> | null = null;
|
|
|
|
export function ensureBrowserEngine(): Promise<void> {
|
|
if (!promise) {
|
|
promise = initLayoutEngine({
|
|
fonts: [
|
|
{ family: 'Inter', weight: 400, path: '/fonts/Inter-Regular.ttf' },
|
|
{ family: 'Inter', weight: 700, path: '/fonts/Inter-Bold.ttf' }
|
|
]
|
|
});
|
|
}
|
|
return promise;
|
|
}
|