Brain Market · UX Mock · 2026-07-17 · rev.6
実現方式はSSEストリーミングを前提としています。OpenAI の Images API(gpt-image-1)は stream: true + partial_images で生成途中の画像を段階的に配信できるため、Rails でその partial 画像をブラウザへ中継し、著者は「画像が徐々に鮮明になる」様子を見られます。
実際の編集画面にUIを組み込んだ状態です。「成功Ver / 失敗Ver」を切り替え、「▶ フローを自動再生」を押すか、タブで各ステップに移動してください。
State × Event
1本のSSE接続で流れてくるイベントを受けて、上のモックの各ステートを遷移させます。partial は OpenAI の image_generation.partial_image を中継したもので、受信のたびに生成中の画像を差し替えます。
| UXステート | 画面表示 | 遷移トリガー(受信イベント) |
|---|---|---|
| 1. 生成ボタン | 編集画面のアイキャッチ未設定エリア | 著者のクリック → 確認モーダル表示 |
| 2. 解析中 〜2秒 | モーダル:プログレス1段目 | SSE接続確立 → event: prompt(組み立てた prompt を同梱) |
| 3. 生成中(だんだん鮮明に) 5〜15秒 | モーダル:3案がぼやけ→鮮明へ更新 | event: partial を受信するたびに該当案の画像を差し替え(partial 1〜3回 × 3案) |
| 4. 候補から選択 | 3案が確定表示 | event: completed(最終3件のURL)→ 接続クローズ |
| 5. 適用後 | アイキャッチ反映 + スナックバー | PATCH 成功(こちらは通常の同期リクエスト) |
| 4'. 生成失敗 | モーダル内エラー + 再試行ボタン | event: failed / 接続断 / クライアント側タイムアウト |
モーダル下部の文言(「画像を生成しています…」等)は経過時間ではなく、partial イベントに含まれる partial_image_index で切り替えます。総数は送信時の partial_images で確定しているため、「いま何合目か」を推測ではなく受信データから確定できます。
| 受信イベント | 画像 | チップ文言 |
|---|---|---|
partial index: 0 | 強くぼやけた状態で表示 | 画像を生成しています… |
partial index: 1 | ぼかしが弱まる | もう少しで完成します… |
partial index: 2 | ほぼ鮮明に | 仕上げています… |
| completed | 確定画像を表示 | チップを消す |
For Backend
sequenceDiagram
participant A as 著者(ブラウザ)
participant F as brain_market_front(Nuxt 3)
participant B as brain_market_api(Rails / ActionController::Live)
participant O as OpenAI Images API
A->>F: 「3案を生成する」クリック
F->>B: POST /v2/articles/:id/ai_thumbnails/stream
Note over F,B: SSE受信は fetch + ReadableStream
B->>B: タイトル・本文から image prompt 組み立て
B-->>F: event: prompt(組み立てた prompt)
F-->>A: 「解析中」→「生成中」へ
B->>O: images.generate(stream: true, partial_images: 2〜3, n: 3)
loop partial 画像を都度中継
O-->>B: image_generation.partial_image
B-->>F: event: partial(該当案・部分画像)
F-->>A: 生成中の画像を差し替え(ぼやけ→鮮明)
end
O-->>B: image_generation.completed
B-->>F: event: completed(最終3件のURL)
B->>B: ActiveStorage で S3 に attach、接続クローズ
F-->>A: 3案を確定表示
A->>F: 1案を選択して「使用する」
F->>B: PATCH 選択画像をアイキャッチに設定
B-->>F: 200 OK
F-->>A: アイキャッチ反映+完了通知
Note over A,B: failed / 接続断 / タイムアウト時はモーダル内でエラー表示・再試行へ