逆レシピ帳 - 料理写真からAIがレシピを推測するWebアプリの作り方
動画で紹介した「逆レシピ帳」の開発手順をまとめています。各コマンド・プロンプトはコピーボタンでワンクリックコピーできます。
| 材料 | 分量 |
|---|---|
| Windows PowerShell | 1個 |
| Claude Pro プラン | 1個(月額 $20) |
| Gemini API キー | 1個(無料) |
| Node.js | v22 推奨 |
| Proxmox VM(盛り付け用・任意) | 1CPU / 4GB / 50GB |
PowerShellを開いて、プロジェクト用のフォルダを作ります。
mkdir C:\gyaku_recipe
Claude Code をインストールします。
irm https://claude.ai/install.ps1 | iex
どのディレクトリからでも claude コマンドが使えるようにします。
[Environment]::SetEnvironmentVariable("PATH", [Environment]::GetEnvironmentVariable("PATH", "User") + ";$env:USERPROFILE\.local\bin", "User")
プロジェクトディレクトリに移動して Claude Code を起動します。初回はブラウザ認証が必要です。
cd C:\gyaku_recipe claude
レシピ推測に使う AI の API キーを発行します。
https://aistudio.google.com/apikey
Claude Code を再起動して、以下のプロンプトをまるごとコピペしてEnterを押します。あとはAIが全自動で開発してくれます。
cd C:\gyaku_recipe claude
# 逆レシピ帳 — 料理写真からAIがレシピを推測するWebアプリ
以下の指示に従い、Webアプリを一から構築してください。
## 前提
- 作業ディレクトリは空
- Node.js インストール済み
## 技術スタック
- Next.js (App Router) + TypeScript + Tailwind CSS
- DB: SQLite (better-sqlite3) — `next.config.ts` の `serverExternalPackages` に追加すること
- AI: Google Gemini (`@google/generative-ai`, モデル: `gemini-2.5-flash-lite`)
- 写真保存: ローカルファイルシステム (`public/uploads/` に保存、DB初期化時に自動作成)
## セットアップ手順
1. `create-next-app` で初期化
2. `npm install better-sqlite3 @google/generative-ai && npm install -D @types/better-sqlite3`
3. `.env.local` を Node.js の `fs.writeFileSync` で UTF-8 で作成する(echo コマンドは Windows で UTF-16 になるため使わないこと)。中身は `GEMINI_API_KEY=your_api_key_here` の1行のみ
4. **`.env.local` の中身は絶対に読まないこと**
5. `src/app/favicon.ico` を削除する(Next.js デフォルトの N マークが表示されるため)
## next.config.ts
```ts
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
serverExternalPackages: ["better-sqlite3"],
};
export default nextConfig;
```
## ファイル構成
```
src/
├── lib/
│ ├── db.ts # SQLite初期化 + public/uploads/ 自動作成
│ └── gemini.ts # Gemini API呼び出し
├── components/
│ └── Header.tsx # 共通ヘッダー(トップ / 一覧)
└── app/
├── layout.tsx # 共通レイアウト(Header組み込み、lang="ja"、icons: [] でfavicon無効化)
├── page.tsx # トップ画面
├── recipes/
│ ├── page.tsx # 一覧画面
│ └── [id]/
│ └── page.tsx # 詳細画面
└── api/
├── generate-recipe/
│ └── route.ts # POST: Geminiでレシピ生成
├── uploads/
│ └── [filename]/
│ └── route.ts # GET: 画像配信
└── recipes/
├── route.ts # POST: 保存 / GET: 一覧
└── [id]/
└── route.ts # GET: 詳細
```
## DB スキーマ (SQLite)
```sql
CREATE TABLE IF NOT EXISTS recipes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
dish_name TEXT NOT NULL,
servings INTEGER NOT NULL,
ingredients TEXT NOT NULL,
steps TEXT NOT NULL,
comment TEXT NOT NULL,
dish_image_path TEXT NOT NULL,
ingredients_image_path TEXT,
created_at TEXT NOT NULL DEFAULT (datetime('now', 'localtime'))
);
```
DBファイルは `data/recipes.db` に保存。`data/` ディレクトリも自動作成すること。
## API Routes
### POST /api/generate-recipe
- リクエスト: `{ dishImage: string(base64), dishMimeType: string, ingredientsImage?: string(base64), ingredientsMimeType?: string }`
- Gemini にプロンプトと画像を送り、レシピ JSON を返す
- エラー時はエラーメッセージの詳細をレスポンスに含めること
### GET /api/uploads/[filename]
- `public/uploads/` 内の画像ファイルを配信する
- パストラバーサル防止のバリデーションを入れること
### POST /api/recipes
- 画像は Base64 → Buffer → `public/uploads/{uuid}.{ext}` に書き出し
- DB にはパスを `/api/uploads/{filename}` 形式で保存
### GET /api/recipes — 一覧取得(新しい順)
### GET /api/recipes/[id] — 詳細取得
## Gemini 呼び出し
- `generateContent` には `{ contents: [{ role: "user", parts }] }` 形式で渡す
- 返答の ```json``` マークダウンを除去してから JSON.parse
- JSON形式: `{ "dishName", "servings", "ingredients": [{"name", "amount"}], "steps": [string], "comment" }`
## フロントエンド
- トップ: 写真選択 → プレビュー → 「逆レシピ化する」→ 結果表示 → 保存
- 一覧: カード形式グリッド(サムネ+料理名+日付)
- 詳細: 写真、材料テーブル、手順リスト、AIコメント
- 共通ヘッダー: オレンジ背景、ナビゲーション
- Tailwind CSS でオレンジ系テーマ
## 最終確認
- `npm run build` でビルドエラーがないことを確認する
認証・広告は不要。家庭内LAN利用。
Step 5 で取得した Gemini API キーを設定します。Claude Code が作成した .env.local を開いて your_api_key_here の部分を実際のキーに書き換えてください。
開発が完了したらアプリを起動して確認します。
npm run dev
ブラウザで以下を開きます:
http://localhost:3000
自宅サーバーがある方は、LAN内の VM にデプロイして家族みんなで使えるようにできます。サーバーがない場合は Step 8 のまま localhost でおいしくいただけます。
# 逆レシピ帳 — Ubuntu VMへのデプロイ 現在のディレクトリにある Next.js アプリを、LAN内の Ubuntu VM にデプロイしてください。 ## 前提 - 現在のディレクトリに Next.js アプリ(逆レシピ帳)が構築済み - デプロイ先: `192.168.x.x`(Ubuntu 22.04、SSH鍵認証済み) - SSH接続は `ssh ubuntu@192.168.x.x` でパスフレーズなしで接続可能 ## 手順 1. ローカルで `npm run build` が通ることを確認 2. VM側に Node.js 22.x + PM2 をセットアップ 3. 必要なファイルのみを scp で転送(node_modules, .next は除外) 4. VM側で `npm install` → `npm run build` → PM2 で起動 ## 注意 - `.env.local` の中身は絶対に読まないこと - IPアドレスは自分の環境に合わせて変更してください