AI-assisted tool for building selfie-embedding prompts from template images, used by the benchmark and the design builder
The Prompt Generator is an admin tool for building the JSON prompts that drive merch AI art generation. The merch pipeline embeds a user's selfie into a template image (typically containing a placeholder humanoid figure, e.g. a green doll). The prompt tells the image model how to perform that replacement — which element to swap, what to infer from the selfie, and what must stay untouched.
Building such a prompt is iterative. The Prompt Generator supports the full loop in one dialog:
task field, and preserves everything else (pose, apparel, background, style).IMPORTANT array) or Adapt with AI (free-form rewrite, e.g. "make the image more contrastive").The dialog (90vw × 90vh) opens from two places:
| Host | Trigger |
|---|---|
Benchmark dashboard (/benchmark) | Prompt Generator button under the template image upload (visible once a template image is set) |
| Design tab (campaign builder) | Prompt Generator button next to the AI Prompt label (enabled once a Template Image is set, including inherited ones) |
The prompt is edited in two synchronized modes:
@uiw/react-json-view). Single-click a value to edit it inline, click keys to rename, hover for add/delete icons. The + icon opens a chooser (String / Array / Object). Typing [] / {...} as a value converts it to a real nested container.All edits keep the underlying prompt text in sync, so Save to prompt always saves exactly what is shown.
Add IMPORTANT appends instructions to the prompt's IMPORTANT array (created on first use). Instructions are saved to a global library (shared across all admins) so common rules — e.g. "keep the ethnicity of the selfie" — can be reused in every prompt:
Run Generation uses the host's currently selected parameters when set, otherwise the defaults:
| Parameter | Benchmark host | Design host | Default |
|---|---|---|---|
| Model | first selected model | design's AI model | gpt-image-2 |
| Quality | first selected quality | first quality tier | low |
| Input fidelity | first selected fidelity | design's fidelity | high |
| Overlay | dashboard overlay | design overlay | none |
| Selfie | western corpus selfie #1 ("female influencer") | same | same |
| Masking | none | none | none |
The output runs through the production pipeline (generate → center-crop → overlay) and is uploaded to merch/benchmark/preview/ on S3.
packages/merch-benchmark/client/ (@zooly/merch-benchmark-client)
components/prompt-generator-dialog.tsx
Decoupled component — host injects its admin API caller (PromptGeneratorApi)
Exported: PromptGeneratorDialog, PromptGeneratorApi, PromptPreviewParams
packages/merch-benchmark/srv/ (@zooly/merch-benchmark-srv)
describe-template.ts Template image → JSON description (Gemini vision)
adapt-prompt-selfie.ts Rewrite element references → "infer from selfie"
refine-prompt.ts Free-form AI rewrite of the whole prompt
format-prompt-json.ts Plain text → valid JSON structure
preview-generation.ts One-off test render (no DB rows)
Hosts:
benchmark dashboard-page.tsx passes the benchmark client's adminApi
design-config-editor.tsx passes the merch-admin client's adminApi
All AI text operations use Gemini 3.5 Flash (google/gemini-3.5-flash) via the AI gateway; test renders use the regular image model catalog.
All under /api/merch/admin/benchmark/, admin-only, CORS-enabled:
| Endpoint | Method | Purpose |
|---|---|---|
describe-template | POST | { imageUrl } → JSON description of the template image |
adapt-prompt-selfie | POST | { promptJson, element } → prompt rewritten to selfie references |
refine-prompt | POST | { promptJson, instructions } → whole-prompt AI rewrite |
format-prompt-json | POST | { text } → valid JSON restructuring of a free-text prompt |
preview | POST | { prompt, templateImageUrl, endpointId?, quality?, inputFidelity?, overlayUrl? } → test render |
important-instructions | GET / POST | List / save library instructions |
important-instructions/:id | DELETE | Remove an instruction from the library |
| Table / column | Purpose |
|---|---|
merch_benchmark_session.fan_location_text | Persists the Fan location text with each benchmark run so reruns prefill it |
merch_benchmark_important_instruction | Global IMPORTANT instruction library (id, text unique, created_at) |
In the design builder, the Fan location text is stored in the design's configJson.fanLocationText field.