1. プロジェクト概要
飲食店向け Instagram 自動投稿サービス。店舗スタッフが料理写真を Web アプリにアップロードし、AI がキャプションとハッシュタグを自動生成、Instagram 風プレビューを確認してワンタップで投稿する。
| 項目 | 内容 |
| プロジェクト名 | AIインスタ担当 |
| 協業先 | カプセル社 |
| 通常プラン | 月額 ¥20,000 |
| 上位プラン | 月額 ¥35,000 |
| リポジトリ | ~/projects/insta-auto/ |
1.1 現在のステータス
| フェーズ | ステータス | 期間 |
| Phase 1 — MVP | 完成済み | デプロイ済み |
| Phase 2 — 拡張機能 | 開発待ち | 2026-04-17 〜 2026-05-31 |
| USEN セミナーデモ | 直近 | 2026-04-16 |
1.2 デプロイ先・デモ情報
2. 技術スタック
| 要素 | 技術 | 備考 |
| フロントエンド | React 18 + Vite | Cloudflare Pages |
| バックエンド | Cloudflare Workers + Hono | エッジ実行 |
| DB | Cloudflare D1 (SQLite) | APAC リージョン |
| 画像一時保管 | Cloudflare KV | TTL 10分 |
| AI | Claude API (claude-sonnet-4-20250514) | 画像分析 + キャプション生成 |
| Instagram 投稿 | Instagram Graph API v21.0 | 単一 + カルーセル |
| 認証 | JWT (HS256) + PBKDF2 | 24時間有効 |
| トークン暗号化 | AES-GCM (Web Crypto API) | IG トークン保護 |
2.1 デプロイ環境
| リソース | 値 |
| D1 Database | insta-auto-db (ID: c1639e6f-1bd0-4be1-8721-8c40cbd3b21b) |
| KV Namespace | TEMP_IMAGES (ID: a8381fbb02d849f49034642957deda7a) |
| Workers シークレット | ANTHROPIC_API_KEY, JWT_SECRET, TOKEN_ENCRYPTION_KEY |
3. リポジトリ構成
~/projects/insta-auto/
├── packages/
│ ├── web/
│ │ └── src/
│ │ ├── App.tsx
│ │ ├── api/
│ │ │ ├── client.ts
│ │ │ └── demo.ts
│ │ ├── components/
│ │ │ ├── LoginForm/
│ │ │ ├── Header/
│ │ │ ├── ImageUploader/
│ │ │ ├── PostPreview/
│ │ │ └── SuccessScreen/
│ │ ├── hooks/
│ │ │ └── useToast.ts
│ │ └── types/
│ └── worker/
│ └── src/
│ ├── index.ts
│ ├── routes/
│ │ ├── auth/
│ │ ├── upload/
│ │ ├── generate/
│ │ └── publish/
│ ├── services/
│ │ ├── claude.ts
│ │ ├── instagram.ts
│ │ ├── store.ts
│ │ ├── password.ts
│ │ └── crypto.ts
│ ├── middleware/
│ │ └── auth.ts
│ └── db/
│ └── schema.sql
4. Phase 1 API 設計 完成済み
4.1 POST /api/auth/login
レートリミットあり: 5回/15分(IP + storeId)
| 方向 | フィールド | 型 | 説明 |
| Request | storeId | string | 店舗ID |
| Request | password | string | パスワード |
| Response | success | boolean | 成否 |
| Response | token | string | JWT(24h有効) |
| Response | storeName | string | 店舗表示名 |
4.2 POST /api/upload JWT必須
| 方向 | フィールド | 型 | 説明 |
| Request | images | multipart | 1〜10枚の画像ファイル |
| Response | images[].id | string | 画像ID |
| Response | images[].url | string | 一時URL |
| Response | images[].originalName | string | 元ファイル名 |
バリデーション: MIME チェック、サイズ 10MB 以下、マジックバイト検証
4.3 POST /api/generate JWT必須
処理フロー: 店舗設定取得 → 直近5件のネタ被り防止 → Claude API 呼び出し
Request
{
"images": [
{ "id": "img_xxx", "url": "https://..." }
]
}
Response 型定義
type ImageAnalysis = {
dishName: string;
dishCategory: string;
visualDescription: string;
appealPoints: string[];
}
type CaptionResult = {
text: string;
hashtags: string[];
postingSuggestion: string;
}
4.4 POST /api/publish JWT必須
| 方向 | フィールド | 型 | 説明 |
| Request | images | array | 画像情報配列 |
| Request | caption | object | キャプション+ハッシュタグ |
| Response | mediaId | string | IG メディアID |
| Response | postId | string | DB投稿ID |
Instagram Graph API 投稿フロー
POST /{ig_user_id}/media
waitForContainer(container_id)
POST /{ig_user_id}/media_publish
for each image:
POST /{ig_user_id}/media
waitForContainer(child_container_id)
POST /{ig_user_id}/media
waitForContainer(carousel_container_id)
POST /{ig_user_id}/media_publish
5. DB スキーマ
5.1 stores(店舗マスタ)
| カラム | 型 | 説明 |
id | TEXT PK | 店舗ID |
name | TEXT | 店舗名 |
plan | TEXT | プラン(standard / premium) |
ig_user_id | TEXT | Instagram ユーザーID |
access_token | TEXT | IG アクセストークン(AES-GCM 暗号化) |
token_expires_at | TEXT | トークン有効期限 |
brand_voice | JSON | トーン・語り口・一人称・文体・絵文字密度 |
hashtag_config | JSON | 固定タグ・上限設定 |
caption_config | JSON | 文字数上限・書き出しスタイル・CTA例 |
prohibited | JSON | 禁止表現リスト |
sns_method | TEXT | SNS運用手法(上位プランのみ) |
posting_schedule | TEXT | 推奨投稿スケジュール |
feedback_enabled | BOOLEAN | フィードバック学習の有効/無効 |
password_hash | TEXT | PBKDF2 ハッシュ値 |
5.2 posts(投稿履歴)
| カラム | 型 | 説明 |
id | TEXT PK | 投稿ID |
store_id | TEXT FK | 店舗ID |
ig_media_id | TEXT | IG メディアID |
ig_permalink | TEXT | 投稿パーマリンク |
image_ids | JSON | 画像ID配列 |
image_urls | JSON | 画像URL配列 |
caption_text | TEXT | キャプション本文 |
hashtags | TEXT | ハッシュタグ |
dish_names | JSON | 料理名配列 |
analysis_raw | JSON | AI分析結果(生データ) |
status | TEXT | draft / published / scheduled / failed |
published_at | TEXT | 公開日時 |
scheduled_at | TEXT | 予約日時 |
5.3 post_metrics(Phase 2用、定義済み未使用)
| カラム | 型 | 説明 |
id | TEXT PK | メトリクスID |
post_id | TEXT FK | 投稿ID |
fetched_at | TEXT | 取得日時 |
likes | INTEGER | いいね数 |
comments | INTEGER | コメント数 |
saves | INTEGER | 保存数 |
reach | INTEGER | リーチ数 |
impressions | INTEGER | インプレッション数 |
engagement_rate | REAL | エンゲージメント率 |
5.4 feedback_summaries(Phase 2用、定義済み未使用)
| カラム | 型 | 説明 |
id | TEXT PK | サマリーID |
store_id | TEXT FK | 店舗ID |
period | TEXT | 集計期間 |
summary | TEXT | 分析サマリー |
prompt_patch | TEXT | プロンプト改善パッチ |
6. Claude API プロンプト設計
buildSystemPrompt() が店舗設定から動的にシステムプロンプトを生成する。
6.1 プロンプト構成要素
| 要素 | ソース | 説明 |
| ブランドボイス | stores.brand_voice | トーン、語り口、一人称、文体、絵文字密度 |
| ハッシュタグ戦略 | stores.hashtag_config | 固定タグ、上限15個 |
| キャプション設定 | stores.caption_config | 文字数上限300、書き出しスタイル、CTA例 |
| SNSメソッド | stores.sns_method | 上位プランのみ適用 |
| 禁止表現 | stores.prohibited | 使用禁止ワードリスト |
| 直近投稿 | posts テーブル | 直近5件を参照しネタ被りを防止 |
7. セキュリティ
| 対策 | 仕様 |
| パスワードハッシュ | PBKDF2 (SHA-256, 100,000回, salt 16byte) |
| 認証トークン | JWT HS256, 24時間有効 |
| IGトークン暗号化 | AES-GCM (12byte IV, Web Crypto API) |
| レートリミット | KVベース、IP + storeId で 5回失敗/15分 |
| 画像バリデーション | MIME チェック + マジックバイト検証 |
| CORS | localhost:5173(開発)、insta-auto.pages.dev(本番)のみ許可 |
8. Phase 2 開発要件 開発待ち
開発期間: 2026-04-17 〜 2026-05-31
推奨実装順: F-06 → F-03 → F-02 → F-01 → F-04 → F-05
F-06: IG トークン自動更新 [優先: 高] 小規模
- Cron Trigger: 毎日 AM 2:00
- 有効期限 14日以内のトークンを自動リフレッシュ
- Graph API:
GET /oauth/access_token で60日延長
- 追加シークレット:
FB_APP_ID, FB_APP_SECRET
最優先で実装すること。トークン失効すると全店舗の投稿が停止する。
F-03: 店舗設定画面 [優先: 高] 大規模
- 現在 D1 に直接 SQL で投入している設定を GUI で管理
- タブ構成: ブランドボイス / ハッシュタグ / キャプション / 禁止表現 / フィードバック
- API:
GET /api/store/settings, PUT /api/store/settings
F-02: 投稿履歴画面 [優先: 高] 中規模
- カード形式でステータス別表示(公開済 / 予約中 / 失敗)
- ページネーション: 20件/ページ
- 失敗投稿の再投稿機能
- 予約投稿のキャンセル機能
- API:
GET /api/posts, POST /api/posts/:postId/retry
F-01: 予約投稿 [優先: 高] 中規模
- 日時指定で投稿を予約
- Cron Triggers: 5分ごとに実行チェック
- 画像を KV に長期保存(TTL = scheduledAt + 1時間)
- 失敗時は最大3回リトライ
- API:
POST /api/schedule, DELETE /api/schedule/:postId
F-04: フィードバック学習 [優先: 中] 大規模
- 週1バッチ(毎週月曜 AM 3:00)で IG Insights を取得
- engagement_rate 上位20%を「成功投稿」として分析
prompt_patch を生成してキャプション生成に自動反映
- API:
GET /api/store/metrics
データ蓄積が必要なため、他機能の実装後に着手。
F-05: 助っ人 API 連携 [優先: 中] 中規模
- カプセル社 API 提供待ち
- 13万アカウントの人気投稿トレンドを参考データとして活用
- 上位プランのみ利用可能
外部依存: カプセル社の API 仕様確定を待って着手。
9. API 一覧(全エンドポイント)
9.1 Phase 1(稼働中)
| メソッド | パス | 認証 | 説明 |
| GET | /api/health | 不要 | ヘルスチェック |
| GET | /api/temp-image/:id | 不要 | 一時画像取得 |
| POST | /api/auth/login | 不要 | ログイン(レートリミットあり) |
| POST | /api/upload | JWT | 画像アップロード |
| POST | /api/generate | JWT | AI キャプション生成 |
| POST | /api/publish | JWT | Instagram 投稿 |
9.2 Phase 2(実装予定)
| メソッド | パス | 認証 | 機能ID | 説明 |
| POST | /api/schedule | JWT | F-01 | 予約投稿作成 |
| DELETE | /api/schedule/:postId | JWT | F-01 | 予約投稿キャンセル |
| GET | /api/posts | JWT | F-02 | 投稿履歴一覧 |
| POST | /api/posts/:postId/retry | JWT | F-02 | 失敗投稿の再投稿 |
| GET | /api/store/settings | JWT | F-03 | 店舗設定取得 |
| PUT | /api/store/settings | JWT | F-03 | 店舗設定更新 |
| GET | /api/store/metrics | JWT | F-04 | フィードバック指標取得 |
10. Cron 設定 / wrangler.toml
10.1 スケジュール一覧
| Cron 式 | 頻度 | 機能 | 機能ID |
*/5 * * * * | 5分ごと | 予約投稿の実行チェック | F-01 |
0 2 * * * | 毎日 AM 2:00 | IG トークン自動更新 | F-06 |
0 3 * * 1 | 毎週月曜 AM 3:00 | フィードバック学習バッチ | F-04 |
10.2 wrangler.toml 最終形(triggers セクション)
[triggers]
crons = ["*/5 * * * *", "0 2 * * *", "0 3 * * 1"]
11. コスト試算(10店舗想定)
| 項目 | 月額コスト |
| Cloudflare + imgbb | ~$5 |
| Claude API | $50 〜 $100 |
| 合計 | $55 〜 $106(約 ¥8,000 〜 ¥16,000) |
| 指標 | 値 |
| 月間売上(10店舗) | ¥200,000 |
| 粗利率 | 90 〜 95% |
12. 依頼事項
Phase 1 は完成済み・デプロイ済み。Phase 2 の6機能の実装を依頼する。
| 機能ID | 機能名 | 規模 | 優先度 | 備考 |
| F-06 | IG トークン自動更新 | 小 | 最優先 | トークン失効防止 |
| F-03 | 店舗設定 GUI | 大 | 高 | SQL直接投入からの脱却 |
| F-02 | 投稿履歴画面 | 中 | 高 | ステータス管理・再投稿 |
| F-01 | 予約投稿 | 中 | 高 | Cron 5分ごと実行 |
| F-04 | フィードバック学習 | 大 | 中 | データ蓄積後に着手 |
| F-05 | 助っ人 API 連携 | 中 | 中 | カプセル社 API 提供待ち |
既存コード: ~/projects/insta-auto/