第 07 章 — AI 編輯迴圈與降級設計目錄  

AI 互動行銷頁實戰 — 目標九宮格 — 第 07 章

AI 編輯迴圈與降級設計:
prompt 是可攜帶的資產

學完:讓使用者用一句話修改 AI 背景;改文字換配色零成本即時重繪;服務掛掉時漏斗照樣走得完。

核心觀念

迭代有兩種,成本差一千倍:
改背景 = 重新生圖,快則數十秒、慢則兩三分鐘,扣一次額度;
改文字、換配色 = canvas 重繪,不到 0.1 秒,免費

先打破一個錯覺:生圖 API 沒有記憶

edit 模式的請求:只差兩件事

// 原始 prompt 照舊:風格詞、構圖約束、「不准畫字」鐵律一個字都沒少
let prompt = imagePrompt(req.goal, req.subGoals, preset.words, req.orientation);

// 差異一:使用者那句話「追加」在後面,不是取代
if (req.editInstruction) {
  prompt += `\nRevision request from the user (apply it to the previous design): ${req.editInstruction}`;
}

const payload = { prompt,
  size: req.orientation === 'portrait' ? '1024x1536' : '1536x1024' };

// 差異二:上一張背景圖放進參考圖欄位(純 base64,去掉 data: 前綴)
if (req.referenceImagesBase64?.length)
  payload.reference_images_base64 = req.referenceImagesBase64;

只送「亮一點」三個字,模型就失去風格與構圖的所有上下文,生出來的是另一張不相干的圖。

把上一張背景帶上:縮圖再上傳

// main.js:editInstruction 有值 = 修改模式
if (editInstruction && bgRecord) {
  referenceImagesBase64.push(
    await blobToBase64(await resizeImageBlob(bgRecord.blob, 1280)),
  );
}

文字迭代零成本:只重繪,不重生

function rerenderWallpaper() {
  renderWallpaper(wallCanvas, {
    bgBitmap,                      // 背景不變,不重新生圖
    cells: state.cells,
    actions: state.actions,
    styleId: state.wallpaper.styleId,
    orientation: state.wallpaper.orientation,
    mode: wallpaperMode,
  });
}

上一章「背景與文字解耦」的紅利在這裡兌現。成品直接把規則講給使用者聽:「不滿意可以輸入修改指示重生背景;改文字或換風格則即時重繪、不用重生。」把貴的路和免費的路明白標出來,使用者自然把額度花在刀口上。

本章真正想教的行銷頁設計觀

生圖服務在排隊、金鑰沒設、額度用完——大多數網站回一句「請稍後再試」,等於送客
但我們手上握著一份完整的生圖 prompt,它不是只有自家後端能用

降級路徑:兩個純前端按鈕,零後端依賴

(a) 複製生圖 prompt

function buildPortablePrompt(goal, subGoals, styleId, orientation) {
  let p = imagePrompt(goal, subGoals, presetById(styleId).words, orientation);
  // API 參數換成人話:外面的工具不吃 size: '1024x1536' 這種參數
  p += orientation === 'portrait'
    ? '\nAspect ratio 2:3, vertical phone wallpaper.'
    : '\nAspect ratio 3:2, horizontal desktop wallpaper.';
  return p;
}

copyBtn.addEventListener('click', async () => {
  await navigator.clipboard.writeText(buildPortablePrompt(/* ... */));
  showMsg(bgMsgEl, '已複製。貼到 ChatGPT 或 Gemini 生成,' +
    '生好的圖用下方「匯入背景圖」帶回來。', 'ok');
});

前端的 imagePrompt 模板與 Worker 端逐字同步。clipboard 在非 https 或 file:// 可能不可用——降級路徑自己也要有降級:備一個唯讀 textarea。

(b) 匯入背景圖

importInput.addEventListener('change', async () => {
  const file = importInput.files[0];
  if (!file) return;
  try {
    bgBitmap = await createImageBitmap(file);
    // 跟 AI 生成的背景同等對待:存 IndexedDB,標記來源是手動匯入
    bgRecord = { blob: file, meta: { source: 'manual' },
                 createdAt: new Date().toISOString() };
    bgRecord.id = await idbPut('wallpapers', bgRecord);
    rerenderWallpaper();   // cover 裁切吃任何比例,直接重繪
  } catch {
    showMsg(bgMsgEl, '這張圖讀不進來,請換一張(支援一般圖片格式)。');
  }
});

不用檢查長寬比——上一章的 coverRect 本來就吃任何比例。匯入的圖走完全相同的後續流程,連「修改背景」都能接著用(它會成為下一輪的參考圖)。

最後一塊拼圖:錯誤訊息把路標出來

常見坑

重點回顧

下一章:防刷與額度——你的金鑰背後是真鈔。Turnstile 人機驗證加四層防線,讓共用額度撐得住公開上線。

對照成品:app/(故意不設金鑰走一次降級路徑) · demos/03-wallpaper/