iT邦幫忙

2026 iThome 鐵人賽

DAY 14
0
Build on Google AI

今天學什麼?30 天用 Google AI 打造智慧學習卡系列 第 14 篇

Day 14|現在還需要自己刻前端嗎?讓 AI 幫我建立第一版 Learning Card UI

  • 分享至 

  • xImage
  •  

前幾天一路從 Gemini 的回傳格式,做到 Structured Output、Schema、Array,昨天又把 JSON 對應成 TypeScript 的 LearningCard 型別。

做到這裡,資料大概已經長這樣:

type LearningCard = {
  emoji: string;
  title: string;
  content: string;
  question: string;
  answer: string;
};

照以前的開發方式,下一步大概就是開一個 React 專案,開始建 Component、寫樣式,再慢慢把 Learning Card 畫面刻出來。

但都已經做到 Build on Google AI 了,我突然想到另一個問題:

現在的第一版 UI,真的還需要全部自己從零開始刻嗎?

既然 Gemini 可以幫我產生學習內容,那前端 UI 是不是也可以先交給 AI 試試看?

所以今天先不急著自己寫 Component,我想直接把目前已經定義好的 LearningCard 丟給 Gemini,看看它會怎麼設計第一版 UI。


這次先不使用 Structured Output

Day 10~Day 12,我一直開著 Structured Output,因為當時的目標很明確:

我要 Gemini 回傳符合指定結構的 Learning Card JSON。

但今天的任務不一樣。

今天不是要 Gemini 回傳:

{
  "emoji": "🐢",
  "title": "海龜"
}

而是希望它幫我產生 React UI 的程式碼。

因此這次我另外開了一個新的對話,選擇 Gemini 3.8 Flash,並關閉 Structured Output,避免前面設定的 Learning Card Schema 限制這次的回傳內容。

今天我要測的不是「JSON 能不能固定格式」,而是:

只告訴 Gemini 資料格式與基本 UI 需求,它能不能自己完成第一版 React 介面?


Prompt:這次我只告訴它最基本的需求

我沒有特別指定畫面 Layout,也沒有告訴 Gemini Component 應該怎麼拆。

Prompt 如下:

我正在製作一個智慧學習卡 Web App。

請幫我建立第一版 Learning Card UI,使用 React + TypeScript。

一張 Learning Card 的資料格式如下:

type LearningCard = {
  emoji: string;
  title: string;
  content: string;
  question: string;
  answer: string;
};

目前的學習對象是 3~4 歲幼兒,
內容主題是海洋動物。

UI 需要顯示:

- Emoji
- 標題
- 學習內容
- 問題
- 答案

請設計成簡單、清楚、適合學習卡使用的介面。

其實要求很單純。

我只指定了:

React + TypeScript
LearningCard 資料格式
3~4 歲幼兒
海洋動物
需要顯示的五個欄位

至於畫面怎麼排、要不要有互動、要用什麼 CSS,我都沒有指定。


Gemini 不只幫我「把資料畫出來」

Gemini 回傳了一個完整的 LearningCardApp.tsx。

首先,它保留了前一天定義的資料結構:

export type LearningCard = {
  emoji: string;
  title: string;
  content: string;
  question: string;
  answer: string;
};

接著自己建立了幾張海洋動物的範例資料:

const oceanCards: LearningCard[] = [
  {
    emoji: "🐳",
    title: "藍鯨",
    content:
      "藍鯨是世界上體型最大的動物,頭頂會噴出好高好高的水花喔!",
    question: "誰是海裡最大的動物呢?",
    answer: "就是藍鯨!",
  },
  // ...
];

這部分其實還在預期之內。

真正讓我注意到的是,它沒有只做一張靜態 Card。

Gemini 自己加入了 State:

const [currentIndex, setCurrentIndex] = useState(0);
const [showAnswer, setShowAnswer] = useState(false);

const currentCard = oceanCards[currentIndex];

currentIndex 負責現在顯示第幾張學習卡,而 showAnswer 則負責答案是否顯示。


我沒有要求「隱藏答案」,但 Gemini 自己加了

例如問題區塊,它沒有直接把答案顯示出來,而是先產生一顆按鈕:

{showAnswer ? (
  <div
    onClick={() => setShowAnswer(false)}
    className="w-full bg-emerald-500 text-white font-bold text-center py-2.5 px-4 rounded-xl shadow-md cursor-pointer animate-bounce"
  >
    🎉 {currentCard.answer}
  </div>
) : (
  <button
    onClick={() => setShowAnswer(true)}
    className="w-full bg-amber-400 hover:bg-amber-500 text-amber-950 font-bold py-2.5 px-4 rounded-xl shadow-sm transition active:scale-95"
  >
    點我看答案 👀
  </button>
)}

使用者必須先想一下,再按:

點我看答案 👀

才會看到答案。

但回頭看我的 Prompt,我其實根本沒有要求這個功能。


甚至連「上一張、下一張」都幫我做了

Gemini 還自己加入:

const handlePrev = () => {
  setShowAnswer(false);
  setCurrentIndex((prev) =>
    prev === 0 ? oceanCards.length - 1 : prev - 1
  );
};

const handleNext = () => {
  setShowAnswer(false);
  setCurrentIndex((prev) =>
    prev === oceanCards.length - 1 ? 0 : prev + 1
  );
};

搭配底部的:

<button onClick={handlePrev}>
  ⬅️ 上一張
</button>

<button onClick={handleNext}>
  下一張 ➡️
</button>

因此 Gemini 產生的已經不只是:

JSON → 畫面

而比較接近:

LearningCard[]
      ↓
React State
      ↓
顯示目前卡片
      ↓
查看答案
      ↓
上一張 / 下一張

第一版 Learning Card 的基本互動,其實已經出現了。


還有一件事:我根本沒有指定 Tailwind

另外一個很明顯的地方,是 Gemini 自己選擇使用 Tailwind CSS。

例如:

<div className="min-h-screen bg-sky-50 flex flex-col items-center justify-center p-4">

以及:

<div className="w-full max-w-sm bg-white rounded-3xl shadow-xl border-4 border-sky-200">

從 bg-sky-50、rounded-3xl、shadow-xl 到按鈕的 active:scale-95,整個 UI 都直接使用 Tailwind utility classes。

這點對我來說滿有意思。

因為我的 Prompt 只有:

使用 React + TypeScript。

並沒有寫:

請使用 Tailwind CSS。

也就是說,Tailwind 是 Gemini 自己做的技術選擇。

這也代表如果真的要把這段程式碼放進自己的專案,還是要先確認目前專案的技術環境與 Dependency 是否符合。

AI 可以產生 Code,不代表複製貼上之後一定什麼都不用管。

前端工程師還沒這麼快失業(笑)。


AI 其實已經開始幫我做「產品決策」

把第一次結果重新看一遍,我發現今天最有趣的其實不是:

Gemini 會寫 React。

這件事現在好像已經沒有那麼令人意外了。

比較值得注意的是,我原本只提出:

顯示 Emoji
顯示標題
顯示內容
顯示問題
顯示答案

Gemini 卻自己補成:

Learning Card
├── 幼兒化的視覺設計
├── 多張學習卡
├── 卡片進度
├── 隱藏答案
├── 查看答案互動
├── 上一張
└── 下一張

換句話說,它不是單純照著規格把五個欄位 Render 出來,而是根據「學習卡」這個使用情境,自己推導了一些它認為合理的互動。

這當然很方便。

但從工程角度來看,也出現了一個新的問題:

AI 覺得合理的功能,就等於產品真的需要嗎?

答案顯然不能直接畫上等號。


AI 產生程式碼,不代表不用 Code Review

如果只是做 Prototype,這個結果其實已經讓我省下不少從零開始刻 UI 的時間。

但如果真的要繼續開發,我還是會開始檢查很多事情。

例如目前 LearningCard Type、範例資料和 UI 都放在同一份程式碼裡,之後可能會再拆成不同檔案;Gemini 自己產生的學習內容也還只是 Mock Data,不能直接當成最後教材。

更重要的是,目前這份:

const oceanCards: LearningCard[] = [...]

並不是 Day 12 Gemini Structured Output 回傳的那五張 Learning Card。

所以現在其實還是:

AI 產生範例資料
        +
AI 產生 UI
        ↓
第一版 Prototype

而不是我們真正想完成的:

使用者輸入學習需求
        ↓
Gemini
        ↓
Structured Output
        ↓
LearningCardResponse
        ↓
LearningCard[]
        ↓
React UI

這兩件事情差很多。


今天的小結

原本我以為 Day 14 會是「終於開始寫 React」。

結果真正做完之後,反而幾乎沒有自己從零開始刻 UI。

我只提供了資料格式、使用對象以及最基本的畫面需求,Gemini 就幫我產生了一版 React + TypeScript UI,甚至自己加入 Tailwind CSS、State、查看答案與卡片切換。

這讓第一版 Prototype 的起點快了很多。

但同時也讓我更清楚看到:

AI 可以幫我快速產生第一版,但工程師還是要決定哪些東西該留下來。

以前可能是先想好 UI,再一行一行把 Component 寫出來。

現在則多了一種工作方式:

定義需求
↓
讓 AI 產生第一版
↓
實際執行
↓
Code Review
↓
保留 / 修改 / 刪除
↓
再整合真正的資料

所以「現在還需要自己刻前端嗎?」

至少以今天的實驗來看,第一版不一定要全部從零開始刻,但也還不到可以完全不管的程度。

而且今天做到這裡時,我本來以為實驗已經結束了。

結果回到 Gemini 的回覆選單,我又看到了一個選項:

Make this an app

看來事情還沒結束(笑)。


Day 15|一段 React Code 還不夠?用 Make this an app 直接做成 Learning Card App

今天 Gemini 幫我產生了第一版 LearningCardApp.tsx。

如果按照一般開發流程,接下來應該就是建立專案、安裝套件,再把這些程式碼真正跑起來。

但既然 Gemini 已經提供了 Make this an app,明天就來試試看:

如果連「把程式碼變成 App」這一步也交給 AI,最後會發生什麼事?

而這次 Gemini 做的,似乎比我原本要求的 Learning Card 還要多很多。


上一篇
Day 13|JSON 有了,TypeScript 呢?建立 LearningCard 型別
下一篇
Day 15|一段 React Code 還不夠?用 Make this an app 直接做成 Learning Card App
系列文
今天學什麼?30 天用 Google AI 打造智慧學習卡 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言