> 关键工具:Bolt.new(浏览器内全栈生成 + 一键部署)+ Gemini Vision API(多模态识别)

> 技术栈阶:低阶起步,30% 落在中阶

> 完整演示:构思 → 创建项目 → 提示词编写 → AI 制作 → 项目检验 → 落地上线

> 预计耗时:第一个能分享的版本约 1.5~2 小时(含申请 API Key、调试、部署)

这一篇怎么读

本篇把这个项目从一句想法到一个能发给朋友的网址,完整走一遍。每个阶段都给出你真正要做的动作、要敲的提示词、AI 大致产出的关键代码片段,以及怎么验收。跟着做,你会得到一个真实上线的小产品。

阶段一 · 构思:先把"要做什么"想清楚

动手前先回答四个问题,这一步只用纸笔或脑子,不碰任何工具。它决定了后面提示词的质量。

  • 给谁用、解决什么痛点:给"懒得想晚饭做什么"的人。痛点是"冰箱里有零散食材,但不知道能做什么菜"。
  • 核心流程一句话:拍照 → AI 认出食材 → 生成带卡路里的食谱。
  • 最小可用范围(MVP):只做"拍照识别 + 出 3 个食谱",不做账号、不做收藏、不做历史记录。砍掉一切非核心功能,是新手最该学的纪律。
  • 什么算成功:在手机上拍一张冰箱照片,30 秒内看到 3 个像样的食谱,且认错的食材能手动删掉。

构思阶段的产物:一句话规格

"一个移动端网页:拍照上传冰箱食材 → Gemini 识别 → 列出可删的食材标签 → 生成 3 张含卡路里的食谱卡片。纯前端,免登录。"

这句话就是你接下来所有提示词的"宪法"。

阶段二 · 创建项目:把工具和钥匙备好

这一步是上一版完全没讲、但"详解"必须有的——真正把项目脚手架立起来。分两件事:建项目、拿 API Key。

2.1 建项目(Bolt.new)

  1. 浏览器打开 bolt.new,用 GitHub 账号登录(方便后面同步代码和部署)。
  2. 在首页中央的输入框里,先不要写复杂需求,只写一句话起个底子,让它把脚手架搭好:
用 React + Vite + Tailwind 建一个移动端优先的空白单页应用,
项目名 fridge-chef,先给我一个干净的 Hello 页面能预览即可。
  1. Bolt 会在浏览器里直接生成项目、装依赖、起开发服务器,右侧实时预览。这一步你得到的是一个能跑的空壳——确认预览正常,再往下走。

为什么先要空壳

先让脚手架跑通,把"环境/依赖能不能起来"这类问题和"业务逻辑对不对"分开。环境一旦绿了,后面就只用关心功能。

2.2 拿 Gemini API Key(这是项目的"钥匙")

识别食材要调 Gemini Vision,需要一把 API Key:

  1. 打开 aistudio.google.com(Google AI Studio),登录。
  2. 找到 Get API Key → Create API Key,复制生成的密钥(形如 AIza...)。
  3. 回到 Bolt,不要把密钥硬写进代码。在项目里新建 .env,加一行:
VITE_GEMINI_API_KEY=你复制的密钥

第一条安全纪律

密钥进 .env,并确认 .env.gitignore 里。绝不能把密钥写进源码或提交到 GitHub——一旦泄露,别人能拿你的额度疯狂调用、给你刷出账单。这条从项目第一天就要守。

到这里,"项目"和"钥匙"都备齐了,可以让 AI 正式开工。

阶段三 · 具体提示词编写:把宪法翻译成工单

很多人此处直接说"做一个识别冰箱食材的 App",结果得到四不像。正确做法是把阶段一的"一句话规格"展开成一份结构清晰、留好接口的工单——尤其要"先用假数据跑通界面",把接 API 的风险推后。

主提示词(贴进 Bolt 对话框)

在当前项目上实现"冰箱剩菜食谱",按下面规格来:

【界面】移动端优先,米白底、圆角卡片、温暖风格。
- 顶部一个大的"拍照/上传食材照片"按钮。
- 上传后显示"识别到的食材":用一排标签(chips)列出每种食材,
  每个标签带一个可删除的小叉。
- 下方"为你推荐的食谱":3 张卡片,每张含 菜名 / 所需食材 /
  预计卡路里 / 3~5 步做法。
- 底部一个"重新生成食谱"按钮。

【先用假数据】识别和生成先各写一个返回 mock 数据的占位函数:
  recognizeIngredients(image) 和 generateRecipes(ingredients),
  让我先看到完整界面和交互。真实 API 我下一步再接。

【交互】食材标签可删除;删除后点"重新生成食谱"刷新食谱区。

【代码结构】把这两个函数单独放在 src/api/ 下,方便我后面替换成真实接口。
用 React 函数组件 + hooks,状态放组件内即可。

注意这份工单的三处用心:先 mock 跑界面把 API 函数抽离允许手动删标签——这三点正是为后面"接真实 API""AI 会认错"埋的伏笔。提示词的功力不在辞藻,在这些工程性的安排。

阶段四 · AI 制作:看 AI 产出了什么(关键片段)

Bolt 几十秒就生成了项目。这里只看最关键的几块,理解 AI 给了你什么、哪里需要你后续介入。

项目结构(AI 自动组织成了清晰的分层):

src/
  api/
    recognize.js     # 识别食材(先 mock,后接 Gemini)
    recipes.js       # 生成食谱(先 mock)
  components/
    UploadButton.jsx
    IngredientChips.jsx
    RecipeCard.jsx
  App.jsx

占位的识别函数(mock 版,先让界面跑起来):

// src/api/recognize.js —— 第一版:mock
export async function recognizeIngredients(imageFile) {
  await new Promise(r => setTimeout(r, 600)); // 模拟网络延迟
  return [
    { name: '西兰花', confidence: 0.93 },
    { name: '鸡蛋',   confidence: 0.88 },
    { name: '豆腐',   confidence: 0.71 },
  ];
}

食材标签组件(可删除的 chips,对应交互需求):

// src/components/IngredientChips.jsx
export default function IngredientChips({ items, onRemove }) {
  return (
    <div className="flex flex-wrap gap-2">
      {items.map((it) => (
        <span key={it.name}
          className="px-3 py-1 rounded-full bg-emerald-50 border border-emerald-200 text-sm">
          {it.name}
          <button onClick={() => onRemove(it.name)} className="ml-2 text-gray-400">×</button>
        </span>
      ))}
    </div>
  );
}

此刻在右侧预览里点一遍:上传(假的)、删标签、重新生成——交互闭环通了,但还没接真识别。这就是 70% 里"最丝滑"的部分,AI 几乎免费交付。

阶段五 · 项目检验(上):接真实 API 并逐个排雷

现在把 mock 换成真 Gemini,这一步会接连撞上三个真实的坑——也正是这个案例的 30% 工程所在。

5.1 接入 Gemini,强约束输出格式

接入提示词

把 src/api/recognize.js 换成真实实现,调用 Gemini Vision:
- 读 import.meta.env.VITE_GEMINI_API_KEY。
- 把图片转 base64 传给 Gemini。
- 给模型的 prompt 要求它【只】返回 JSON 数组,禁止 markdown 和解释:
  [{ "name": "中文食材名", "confidence": 0~1 }]
- 把给模型的 prompt 抽成单独常量 RECOGNIZE_PROMPT 方便我调。

AI 产出的真实版关键片段:

// src/api/recognize.js —— 第二版:真实调用(关键片段)
const RECOGNIZE_PROMPT = `你是食材识别助手。识别图片里所有可食用食材。
严格只输出 JSON 数组,禁止 markdown、解释或代码块标记。
每个元素:{"name": 中文食材名, "confidence": 0到1}。只列你确实看到的。`;

export async function recognizeIngredients(imageFile) {
  const base64 = await toBase64(imageFile);
  const res = await fetch(GEMINI_URL + `?key=${import.meta.env.VITE_GEMINI_API_KEY}`, {
    method: 'POST',
    body: JSON.stringify({ contents: [{ parts: [
      { text: RECOGNIZE_PROMPT },
      { inline_data: { mime_type: imageFile.type, data: base64 } },
    ]}]}),
  });
  const data = await res.json();
  return parseIngredients(data); // 见下一步:要做清洗和兜底
}

5.2 坑①:模型不老实——返回被 markdown 包裹

第一次真机一跑就报错:JSON.parse 失败。打开控制台看到 Gemini 把 JSON 包进了 ``` `json ``` 代码块。不要回头跟 AI 纠缠"你又错了",直接给现象和修法

修 bug 提示词

Gemini 有时把 JSON 包在 ```json ``` 里导致 parse 失败。
写一个 parseIngredients:先用正则截取第一个 [ 到最后一个 ] 之间的内容,
再 JSON.parse;整体 try/catch,失败返回 [] 并让界面提示"识别失败,请重试"。
function parseIngredients(data) {
  try {
    const text = data.candidates[0].content.parts[0].text;
    const json = text.slice(text.indexOf('['), text.lastIndexOf(']') + 1);
    return JSON.parse(json);
  } catch (e) {
    return []; // 上层据此提示"识别失败,请重试"
  }
}

5.3 坑②:概率结果——把"长颈鹿 11%"挡在门外

测试时它偶尔识别出"可能是橙子(0.18)"。置信度过滤是必须由人定阈值的取舍:

过滤提示词

显示前过滤掉 confidence < 0.5 的食材,阈值设为常量 CONFIDENCE_THRESHOLD。
过滤后为空时不要白屏,提示"没认出明确食材,换张更清晰、光线好的照片试试"。

5.4 坑③:跨端拍照——上线前最后一道坎

电脑上正常,发给朋友手机点"拍照"没反应。移动端唤起相机要正确的 input 配置 + HTTPS:

兼容提示词

上传按钮在手机上要能直接唤起相机,也要能从相册选:
用 <input type="file" accept="image/*" capture="environment">。
在 iOS Safari 和安卓 Chrome 都要正常。

阶段五 · 项目检验(下):按"边界清单"验收

验收不是看"它能跑",而是专测那 30% 的边界。逐项打勾:

检验项操作期望
空冰箱拍一张没食材的照片提示"没认出明确食材",不白屏
糊照片拍一张很模糊的照片低置信度被过滤,提示换清晰图
识别失败断网后上传提示"识别失败,请重试",应用不崩
跨端iPhone + 安卓各测拍照都能唤起相机
删除联动删一个标签后重新生成食谱据剩余食材刷新

四到五项全过,才算"能用",而不只是"能演示"。

阶段六 · 落地:部署上线,拿到能分享的网址

做出来不上线,等于没做。Bolt 内置部署,几步就能拿到公网地址。

  1. 在 Bolt 项目右上角点 Deploy(默认走 Netlify 集成),授权后它自动构建。
  2. 关键:部署环境也要配密钥。在部署设置(Netlify 站点的 Environment variables)里加上 VITE_GEMINI_API_KEY,否则线上识别会失败——本地 .env 不会被打包上去。
  3. 构建完成后得到一个 https://fridge-chef-xxx.netlify.app 网址,手机打开即可用。
  4. (可选)在 Netlify 绑定自定义域名,让它更像个正经产品。

落地阶段最常见的翻车

"本地好好的,线上识别全失败"——九成是忘了在部署平台配环境变量。本地 .env 只在你电脑上生效,云端构建看不到它。部署后第一件事就是去线上环境变量里补上密钥。

落地后的小事,但很重要

  • 限额保护:去 Google AI Studio 给这把 Key 设个用量上限,防止被刷爆。
  • 冷启动测试:用一台没缓存的设备、点开网址完整走一遍,确认陌生人也能顺利用。
  • 收集反馈:把网址发给三五个朋友,看他们卡在哪——真实用户永远会用出你没测到的姿势。

30% 复盘:人类到底守住了什么

AI 丝滑交付了界面、mock 交互、happy-path 识别(约 70%)。人类亲手补上的 30%,是四件 AI 不会主动替你做的事:

30% 工程点人类做了什么不做会怎样
输出不老实清洗 markdown 包裹 + try/catch 兜底偶发 JSON 报错、白屏
概率结果置信度阈值过滤 + 空结果提示显示"长颈鹿 11%",沦为笑话
跨端兼容capture 配置 + HTTPS + 相册回退一半用户手机点了没反应
落地配置部署平台补环境变量、设限额线上识别全挂、或被刷爆额度

一句话:AI 让你 10 分钟有了 demo,但这几件事决定了它是玩具,还是真能上线、敢发给朋友用的产品。

可复用心法与提示词模板

带得走的四条

  1. 先 mock 后接真:让 AI 先用假数据交付能点通的空壳,再替换真实 API。
  2. 强约束输出格式:要程序解析 AI 输出,就在提示词里写死"只返回 JSON、禁止 markdown",代码侧再清洗兜底。
  3. 为"AI 会错"留后路:置信度过滤 + 手动删除 + 友好失败提示。
  4. 落地即配密钥:部署后第一件事是去云端环境变量补上 Key,并设用量上限。

通用"接多模态 API"提示词模板

把 <占位函数> 换成真实实现,调用 <模型>。要求:
1. 输入转 base64;密钥读环境变量。
2. 提示词强制只返回 JSON(写清字段与类型),禁止 markdown 与解释。
3. 解析前清洗代码块包裹,try/catch 兜底,失败返回空 + 界面友好提示。
4. 过滤低置信度结果,阈值设为常量;为空时给引导提示。
5. 把模型 prompt 抽成单独常量,便于调参。