@zalify/cli 0.11.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +49 -5
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -11860,7 +11860,7 @@ var POLL_INTERVAL_MS = 5000;
11860
11860
  var POLL_TIMEOUT_MS = 30 * 60 * 1000;
11861
11861
  var STREAM_BATCH = 20;
11862
11862
  function buildPrompt(manifest, entry) {
11863
- const style = entry.type === "model" ? manifest.modelStyle ?? manifest.style : manifest.style;
11863
+ const style = entry.type === "model" ? manifest.modelStyle ?? manifest.style : entry.type === "banner" ? manifest.bannerStyle ?? manifest.style : manifest.style;
11864
11864
  return `${style}
11865
11865
 
11866
11866
  ${entry.prompt}`;
@@ -11903,7 +11903,7 @@ async function submitJob(auth, manifest, entries) {
11903
11903
  workspaceId: auth.workspaceId,
11904
11904
  jobs: entries.map((e) => ({
11905
11905
  prompt: buildPrompt(manifest, e),
11906
- size: "1024x1024",
11906
+ size: e.size ?? "1024x1024",
11907
11907
  count: 1
11908
11908
  }))
11909
11909
  })
@@ -11970,7 +11970,7 @@ async function streamingGenerate(auth, manifest, missing, imagesDir, indexPath,
11970
11970
  jobs: batch.map((e) => ({
11971
11971
  prompt: buildPrompt(manifest, e),
11972
11972
  count: 1,
11973
- size: "1024x1024"
11973
+ size: e.size ?? "1024x1024"
11974
11974
  }))
11975
11975
  })
11976
11976
  });
@@ -12888,6 +12888,8 @@ async function shopifyUploadImages(storeDir, options = {}) {
12888
12888
  const manifest = readJson(join6(dir2, "images", "manifest.json"), "images/manifest.json");
12889
12889
  console.log(`Uploading images to the Shopify store connected to workspace "${auth.workspaceName}"`);
12890
12890
  for (const entry of manifest.images) {
12891
+ if (entry.type === "banner" || !entry.handle)
12892
+ continue;
12891
12893
  const filePath = join6(dir2, "images", entry.file);
12892
12894
  if (!existsSync6(filePath)) {
12893
12895
  console.log(` - ${entry.handle}: ${entry.file} not generated yet, skipped`);
@@ -13007,12 +13009,26 @@ alone. Validate anytime with \`zalify brand validate\` (defaults to cwd).
13007
13009
  - \`style\` prefixes packshot/detail prompts; \`modelStyle\` prefixes
13008
13010
  \`type: "model"\` prompts. Keep prompts concrete: materials, colors,
13009
13011
  camera angle, light.
13012
+ - **Banner / merchandising entries** (\`"type": "banner"\`, no \`handle\`)
13013
+ are theme imagery, not product shots: hero slides, editorial banners.
13014
+ They are generated and pushed to the asset library like any entry, but
13015
+ never attached to a product — theme templates reference them by their
13016
+ \`images/assets.json\` URL. Conventions:
13017
+ - Naming: \`hero-1.png\` + \`hero-1-mobile.png\`, \`hero-2.png\`…,
13018
+ \`editorial-1.png\`.
13019
+ - \`size\`: hero desktop + editorial \`"1536x1024"\`, hero mobile
13020
+ \`"1024x1536"\` (default is \`"1024x1024"\` — never right for banners).
13021
+ - \`bannerStyle\` prefixes banner prompts (falls back to \`style\`, whose
13022
+ "square 1:1" phrasing is wrong for banners — always set it).
13023
+ - NO text, lettering, or logos inside the image; the theme overlays
13024
+ copy. Leave calm negative space on one side for it.
13010
13025
  - **Prompt safety (gpt-image-2 rejects [sexual] otherwise)** — for
13011
13026
  human-model shots: say "woman"/"man", never "young …"; keep fitted
13012
13027
  garments layered or covered (blazer / cardigan / cover-up); crop at
13013
13028
  the chin or shoot from behind; prefer wider framing. Swimwear: show
13014
13029
  the garment via flat-lay + detail; make the model shot a cover-up
13015
- scene. Pet/object products: no such constraints.
13030
+ scene. Pet/object products: no such constraints. Applies to banner
13031
+ prompts too.
13016
13032
 
13017
13033
  ## Pipeline (after authoring)
13018
13034
 
@@ -13110,6 +13126,7 @@ var CATALOG_JSON = (vendor, currency) => JSON.stringify({
13110
13126
  var MANIFEST_JSON = JSON.stringify({
13111
13127
  style: "<shared prefix for packshot/detail prompts: photography style, background, light, 'no text, no watermark. Square 1:1 composition.'>",
13112
13128
  modelStyle: "<shared prefix for type:'model' lifestyle prompts — scene, mood, framing. Mind the prompt-safety rules in AUTHORING.md for human models.>",
13129
+ bannerStyle: "<shared prefix for type:'banner' theme imagery — wide cinematic scene, no text or logos, calm negative space on one side for overlaid copy.>",
13113
13130
  images: [
13114
13131
  {
13115
13132
  handle: "example-product",
@@ -13129,6 +13146,20 @@ var MANIFEST_JSON = JSON.stringify({
13129
13146
  type: "model",
13130
13147
  alt: "The Example Product in use",
13131
13148
  prompt: "<lifestyle prompt: who/what uses it, where, light>"
13149
+ },
13150
+ {
13151
+ file: "hero-1.png",
13152
+ type: "banner",
13153
+ size: "1536x1024",
13154
+ alt: "Hero banner: the brand's world in one wide scene",
13155
+ prompt: "<wide hero scene prompt: setting, subject, light — no text, negative space on one side>"
13156
+ },
13157
+ {
13158
+ file: "hero-1-mobile.png",
13159
+ type: "banner",
13160
+ size: "1024x1536",
13161
+ alt: "Hero banner, portrait crop for mobile",
13162
+ prompt: "<same scene, portrait composition — subject centered, negative space above>"
13132
13163
  }
13133
13164
  ]
13134
13165
  }, null, 2) + `
@@ -13155,6 +13186,7 @@ function brandInit(dir2 = ".", opts = {}) {
13155
13186
  Author in this order: brand.md → catalog.json → images/manifest.json` + `
13156
13187
  (rules + worked examples in AUTHORING.md; lint with \`zalify brand validate ${dir2}\`)`);
13157
13188
  }
13189
+ var MANIFEST_SIZES = new Set(["1024x1024", "1536x1024", "1024x1536"]);
13158
13190
  function brandValidate(dir2 = ".") {
13159
13191
  const target = resolve6(dir2);
13160
13192
  const problems = [];
@@ -13266,12 +13298,24 @@ function brandValidate(dir2 = ".") {
13266
13298
  problems.push(`${where}: duplicate file`);
13267
13299
  files.add(entry.file);
13268
13300
  }
13269
- if (entry.handle && handles.size && !handles.has(entry.handle)) {
13301
+ if (entry.type === "banner") {
13302
+ if (entry.handle) {
13303
+ warnings.push(`${where}: banner entries take no handle (ignored by attach)`);
13304
+ }
13305
+ } else if (!entry.handle) {
13306
+ problems.push(`${where}: handle required (only type "banner" entries omit it)`);
13307
+ } else if (handles.size && !handles.has(entry.handle)) {
13270
13308
  problems.push(`${where}: handle "${entry.handle}" not in catalog.json`);
13271
13309
  }
13310
+ if (entry.size && !MANIFEST_SIZES.has(entry.size)) {
13311
+ problems.push(`${where}: size must be one of ${[...MANIFEST_SIZES].join(", ")}`);
13312
+ }
13272
13313
  if (entry.type === "model" && (!manifest.modelStyle || manifest.modelStyle.startsWith("<"))) {
13273
13314
  warnings.push("images/manifest.json: modelStyle prefix not filled in (model shots present)");
13274
13315
  }
13316
+ if (entry.type === "banner" && (!manifest.bannerStyle || manifest.bannerStyle.startsWith("<"))) {
13317
+ warnings.push("images/manifest.json: bannerStyle prefix not filled in (banner entries present)");
13318
+ }
13275
13319
  }
13276
13320
  }
13277
13321
  for (const w of [...new Set(warnings)])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zalify/cli",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Zalify CLI - command-line interface for Zalify",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",