AWS Builder 工作坊

使用 Kiro 建置:他加祿語 學習 App 的教育優先開發技巧工作坊

工作坊系列

對象: 正在建置學習產品、內部賦能工具或社群 App 的專業開發者
時間: 2 小時
主要 AWS AI 服務: Kiro
專案輸出: 一個教育優先的 他加祿語 練習 App,包含學習分類、禮貌規則、驗證 helper 與 Kiro 輔助測試。

工作坊摘要

他加祿語 Kiro 工作坊

本工作坊協助開發者先以教學法思考,再設計語言學習軟體功能。參與者使用 Kiro 捕捉學習目標、禮貌用語規則、練習分類、內容審查期待與測試。練習展示教育限制如何引導資料模型、UI 行為與自動化,讓 他加祿語 練習 App 保持實用、初學者友善、文化上謹慎,並方便日後擴充內容。

工作坊目標

本工作坊教開發者如何建置一個先重視教育、再處理技術的語言學習 App。此 App 聚焦初學者信心、尊重的說法、可重複練習、發音,以及實用情境。Kiro 用來建立 spec、透過 steering 引導實作、產生程式碼、產生測試,並定義 hook 以維持教育合約的一致性。

2 小時議程

時間 模組 開發者成果
0–10 分鐘 教育範圍 已定義非商業學習規則
10–25 分鐘 Kiro steering 已保存產品、教學法與技術標準
25–40 分鐘 Kiro spec 已產生教育需求與任務
40–65 分鐘 練習分類 已實作分類模型與卡片資料
65–85 分鐘 禮貌用語引擎 規則 helper 會選擇較安全的禮貌指引
85–105 分鐘 練習 UI 已建立提示/揭示式學習卡
105–115 分鐘 測試與 hook 已驗證審查狀態與語氣標籤
115–120 分鐘 總結 已建立擴充路線圖

步驟 1 — 定義教育優先的 steering

Kiro 提示範例

為一個教育導向的 他加祿語 學習 App 建立 steering 文件。
這個 App 必須降低學習者的害怕感、讓犯錯變得正常、教導禮貌說法,並提供短小的練習。
使用 React、TypeScript、Vite、Vitest 與本機 JSON 資料。
產生的語言內容在母語者審查前都視為草稿。

系統設計決策

  1. 把教學法當成架構: 產品目標不只是把英文翻成 他加祿語。App 必須協助初學者安全練習、理解語氣,並在社群活動中有禮貌地開口。教育規則應該放進 steering,因為它們會影響 schema 設計、UI 版面、測試與內容審查。
  2. 透過限制保護學習安全: App 應避免過度自信的 AI 行為。審查狀態、短說明、語氣標籤與母語者審查提醒,能讓系統誠實呈現限制。這在教授語言與文化情境時尤其重要。
  3. 讓開發流程可重複: 專業開發者需要一套可重複的方法來建立學習功能。Steering 文件確保 Kiro 在整個工作坊中都使用相同的專案詞彙,例如練習分類、句子卡、禮貌形式、發音、例句與審查狀態。

程式碼範例 — .kiro/steering/pedagogy.md

# 教育指引

這個 App 透過小型、可重複、尊重語境的練習卡來教導初學者。
每張卡都應協助學習者理解該說什麼、何時說,以及聽起來有多正式。

## 學習規則

- 優先使用可大聲念出的短例句。
- 先顯示自然 他加祿語,再顯示較俏皮的 Filipino-English。
- 將俏皮的 Filipino-English 標示為非正式。
- 說明 `po`、`opo`、`kayo` 與 `ninyo` 是尊重標記。
- 在片語旁提供發音。
- 使用審查狀態:`draft`、`native-reviewed` 或 `blocked`。
- 未經母語者審查前,不要把產生的語言內容視為最終版本。

程式碼說明

  • 商業邏輯: 這份 steering 檔案定義每個功能都應遵守的教育標準。
  • 程式碼邏輯: Kiro 讀取 Markdown 脈絡,並用它來塑造產生的需求、元件、測試與審查建議。
  • 預期結果: 產生的實作會持續貼合學習策略,而不是變成一般的單字卡 App。

步驟 2 — 產生教育導向的 Kiro spec

Kiro 提示範例

建立一份名為 educational-practice-flow 的 Kiro spec。
此功能透過練習分類、提示/揭示卡、禮貌說明、發音與審查狀態來教授 他加祿語。
使用可透過 Vitest 與 Testing Library 測試的驗收條件。

系統設計決策

  1. 以功能層級 spec 描述學習流程: Spec 聚焦學習者如何練習,而不只是資料如何呈現。這讓系統能從學習者角度測試:選擇分類、閱讀英文提示、揭示 他加祿語、查看禮貌說明,然後重複練習。
  2. 用驗收條件推動實作: 可測試的條件能降低模糊性。如果 spec 寫著「當學習者揭示卡片時,系統應顯示禮貌 他加祿語」,開發者就能直接實作並測試該行為。
  3. 小型垂直功能切片: 兩小時工作坊需要一個垂直切片。分類選擇、提示/揭示與禮貌說明,已足以示範 Kiro 的 spec 驅動工作流程,而不必加入認證、資料庫或外部 API。

程式碼範例 — .kiro/specs/educational-practice-flow/tasks.md

# 任務

- [ ] 定義 PracticeCategory 與 PracticeCard 型別。
- [ ] 加入 greetings、directions、workshops、thanks 與 waiting 的種子卡片。
- [ ] 實作禮貌用語 helper,為第一次接觸的人回傳較安全的指引。
- [ ] 建立 CategorySelector 元件。
- [ ] 建立具備揭示行為的 PracticeCard 元件。
- [ ] 為分類篩選、揭示行為、非正式標籤與審查狀態加入測試。
- [ ] 加入 hook 指引,提醒在卡片資料變更後執行測試。

程式碼說明

  • 商業邏輯: 任務代表從資料到練習行為的教育工作流程。
  • 程式碼邏輯: 每個任務都可以獨立實作,並在 Kiro 中勾選完成。
  • 預期結果: 開發者能從需求一路清楚前進到可運作的 App。

步驟 3 — 建立練習分類資料

Kiro 提示範例

為 他加祿語 練習分類與卡片產生 TypeScript 模型。
包含活動分類:greetings、directions、workshops、thanks、waiting。
每張卡都需要英文提示、自然 他加祿語、禮貌 他加祿語、語氣、發音與審查狀態。

系統設計決策

  1. 用分類組織學習意圖: 學習者是在準備情境,而不是背抽象字彙清單。greetings、directions、workshops、thanks 與 waiting 等分類,能直接對應到 AWS Manila Community Day 的實際行動。
  2. 提示/揭示格式支援記憶: 先顯示英文提示可鼓勵主動回想。之後再揭示 他加祿語,形成簡單的練習循環,未來也能演進成間隔重複。
  3. 審查狀態跟著內容走: 教育品質仰賴正確性,因此每張卡都儲存審查狀態。這讓 UI 與測試能避免把未審查內容呈現成最終版本。

程式碼範例 — src/data/practiceCards.ts

export type PracticeCategory = "greetings" | "directions" | "workshops" | "thanks" | "waiting";
export type ReviewStatus = "draft" | "native-reviewed" | "blocked";

export interface PracticeCard {
  id: string;
  category: PracticeCategory;
  englishPrompt: string;
  naturalTagalog: string;
  politeTagalog: string;
  tone: "casual" | "polite" | "event-ready" | "informal-playful";
  pronunciation: string;
  reviewStatus: ReviewStatus;
}

export const practiceCards: PracticeCard[] = [
  {
    id: "greetings-hello-learning",
    category: "greetings",
    englishPrompt: "Hello, I am learning 他加祿語.",
    naturalTagalog: "Kumusta, nag-aaral ako ng 他加祿語.",
    politeTagalog: "Kumusta po, nag-aaral po ako ng 他加祿語.",
    tone: "event-ready",
    pronunciation: "koo-MOOS-tah poh, nag-ah-AH-ral poh AH-koh ngah tah-GAH-log",
    reviewStatus: "draft"
  },
  {
    id: "directions-workshop-room",
    category: "directions",
    englishPrompt: "Where is the workshop room?",
    naturalTagalog: "Saan ang workshop room?",
    politeTagalog: "Saan po ang workshop room?",
    tone: "polite",
    pronunciation: "SAH-ahn poh ahng workshop room",
    reviewStatus: "draft"
  },
  {
    id: "waiting-on-my-way",
    category: "waiting",
    englishPrompt: "I am on my way.",
    naturalTagalog: "Papunta na ako.",
    politeTagalog: "Papunta na po ako.",
    tone: "event-ready",
    pronunciation: "pah-POON-tah nah poh AH-koh",
    reviewStatus: "draft"
  }
];

程式碼說明

  • 商業邏輯: 這份資料讓學習者準備真實活動行動:打招呼、問路與協調抵達。
  • 程式碼邏輯: Union type 限制有效分類、語氣值與審查狀態,避免意外出現自由格式標籤。
  • 預期結果: 開發者可以依分類篩選卡片,並呈現一致的練習流程。

步驟 4 — 實作禮貌用語指引 helper

Kiro 提示範例

建立一個 TypeScript helper,用來說明禮貌 他加祿語 是否較安全。
輸入:受眾類型與情境。
回傳:指引訊息、建議版本與原因。

系統設計決策

  1. 把禮貌用語當成產品邏輯: 尊重的說法不是附註。App 的核心價值,是協助初學者在面對講者、主辦方、志工、場地人員、長輩與第一次見面的人時,選擇較安全的措辭。
  2. 先有規則,再談 AI 產生: 確定性的 helper 能提供可預測的指引。AI 可以產生草稿,但執行時的教育行為應該穩定且可測試。以規則為基礎的指引在工作坊中也比較容易稽核。
  3. 與 UI 分離: Helper 不負責渲染 HTML,而是回傳簡單物件,讓同一套邏輯可支援網頁 UI、測試、文件或未來 API 回應。

程式碼範例 — src/lib/politeness.ts

export type Audience = "peer" | "speaker" | "organizer" | "volunteer" | "venue-staff" | "elder" | "unknown";

export interface PolitenessGuidance {
  recommendedVariant: "natural" | "polite";
  message: string;
  reason: string;
}

const formalAudiences: Audience[] = ["speaker", "organizer", "volunteer", "venue-staff", "elder", "unknown"];

export function getPolitenessGuidance(audience: Audience): PolitenessGuidance {
  if (formalAudiences.includes(audience)) {
    return {
      recommendedVariant: "polite",
      message: "先使用禮貌 他加祿語 版本。",
      reason: "面對第一次接觸的人、活動工作人員、講者、長輩與志工時,禮貌說法較安全。"
    };
  }

  return {
    recommendedVariant: "natural",
    message: "在氣氛輕鬆時,對同儕使用自然 他加祿語 是可接受的。",
    reason: "建立關係後,casual 說法可以顯得友善。"
  };
}

程式碼說明

  • 商業邏輯: Helper 教學習者判斷何時使用尊重說法較安全。
  • 程式碼邏輯: 固定的正式受眾清單控制建議版本要回傳 politenatural
  • 預期結果: 呼叫 getPolitenessGuidance("speaker") 會回傳禮貌建議,而 getPolitenessGuidance("peer") 會回傳自然說法指引。

步驟 5 — 建立分類選擇器

Kiro 提示範例

建立一個 CategorySelector React 元件。
它接收 categories、selected category 與 onChange callback。
使用具備無障礙語意的按鈕,並顯示清楚的啟用狀態。

系統設計決策

  1. 情境優先的導覽: 分類對應活動情境。當學習者需要快速找到一句話時,開發者不應強迫他們捲動一堆無關卡片。
  2. 受控元件模式: 選擇器從父層接收狀態。這讓篩選邏輯集中管理,也讓元件更容易測試與重用。
  3. 工作坊示範使用按鈕而非下拉選單: 按鈕讓分類切換在現場教學時更清楚可見,也讓參與者在兩小時內更容易檢查、測試與調整樣式。

程式碼範例 — src/components/CategorySelector.tsx

import type { PracticeCategory } from "../data/practiceCards";

interface Props {
  categories: PracticeCategory[];
  selected: PracticeCategory;
  onChange: (category: PracticeCategory) => void;
}

export function CategorySelector({ categories, selected, onChange }: Props) {
  return (
    <nav aria-label="Practice categories" className="category-selector">
      {categories.map((category) => (
        <button
          key={category}
          type="button"
          aria-pressed={category === selected}
          className={category === selected ? "active" : ""}
          onClick={() => onChange(category)}
        >
          {category}
        </button>
      ))}
    </nav>
  );
}

程式碼說明

  • 商業邏輯: 學習者選擇想練習的活動情境。
  • 程式碼邏輯: 元件把分類 map 成按鈕,並透過 onChange 回報變更。
  • 預期結果: 點選分類會更新父層元件中被選取的練習群組。

步驟 6 — 建立提示/揭示式練習卡

Kiro 提示範例

建立一個 PracticeCardView 元件。
先顯示英文提示。
學習者點選 Reveal 後,顯示自然 他加祿語、禮貌 他加祿語、發音、語氣與審查狀態。
如果 tone 是 informal-playful,顯示 Informal 徽章。

系統設計決策

  1. 主動回想優先於被動閱讀: 提示/揭示設計讓學習者在看到答案前先思考。相較於一開始就顯示所有翻譯,這能提高練習價值。
  2. 揭示機制降低認知負荷: 初學者可能被文法、語氣與發音壓垮。先顯示英文提示,再揭示細節,能創造更溫和的體驗。
  3. 語氣與審查狀態保持可見: 即使揭示答案後,學習者仍需要知道內容是否為草稿、風格是否非正式。UI 不應隱藏品質或語氣 metadata。

程式碼範例 — src/components/PracticeCardView.tsx

import { useState } from "react";
import type { Audience } from "../lib/politeness";
import { getPolitenessGuidance } from "../lib/politeness";
import type { PracticeCard } from "../data/practiceCards";

interface Props {
  card: PracticeCard;
  audience: Audience;
}

export function PracticeCardView({ card, audience }: Props) {
  const [revealed, setRevealed] = useState(false);
  const guidance = getPolitenessGuidance(audience);

  return (
    <article className="practice-card">
      <p className="practice-card__category">{card.category}</p>
      <h2>{card.englishPrompt}</h2>
      <p>{guidance.message}</p>

      <button type="button" onClick={() => setRevealed((value) => !value)}>
        {revealed ? "Hide answer" : "Reveal 他加祿語"}
      </button>

      {revealed && (
        <section aria-label="Practice answer">
          <p><strong>Natural 他加祿語:</strong> <span lang="tl">{card.naturalTagalog}</span></p>
          <p><strong>Polite 他加祿語:</strong> <span lang="tl">{card.politeTagalog}</span></p>
          <p><strong>Pronunciation:</strong> {card.pronunciation}</p>
          <p><strong>Tone:</strong> {card.tone}</p>
          {card.tone === "informal-playful" && <span className="badge">Informal</span>}
          <p><strong>Review:</strong> {card.reviewStatus}</p>
          <p><strong>Why:</strong> {guidance.reason}</p>
        </section>
      )}
    </article>
  );
}

程式碼說明

  • 商業邏輯: 元件建立一個學習互動:閱讀英文、選擇是否揭示,然後比較自然與禮貌形式。
  • 程式碼邏輯: React state 控制揭示/隱藏行為;禮貌用語 helper 依受眾回傳指引。
  • 預期結果: 學習者可以一次練習一個提示,並依選取的受眾取得較安全的語氣指引。

步驟 7 — 組合教育導向的練習 App

Kiro 提示範例

建立 App.tsx,讓學習者選擇分類與受眾。
依分類篩選練習卡,並渲染提示/揭示卡。
預設分類應為 greetings,預設受眾應為 unknown。

系統設計決策

  1. 先做篩選,再考慮搜尋: 對小型工作坊 App 來說,分類篩選比全文搜尋更簡單、也更容易解釋。它強化活動情境模型,並讓實作容易檢查。
  2. 具備受眾意識的練習: 同一句話在 casual 或 polite 情境中可能都可接受。受眾選擇能協助學習者理解,為什麼面對陌生人、工作人員或講者時,禮貌版本較安全。
  3. 可組合的狀態: App shell 擁有被選取的分類與受眾。子元件維持聚焦且可重用。這是適合工作坊的清楚 React 設計,因為開發者可以快速推理狀態流向。

程式碼範例 — src/App.tsx

import { useMemo, useState } from "react";
import { practiceCards, type PracticeCategory } from "./data/practiceCards";
import type { Audience } from "./lib/politeness";
import { CategorySelector } from "./components/CategorySelector";
import { PracticeCardView } from "./components/PracticeCardView";

const categories: PracticeCategory[] = ["greetings", "directions", "workshops", "thanks", "waiting"];
const audiences: Audience[] = ["unknown", "peer", "speaker", "organizer", "volunteer", "venue-staff", "elder"];

export default function App() {
  const [selectedCategory, setSelectedCategory] = useState<PracticeCategory>("greetings");
  const [audience, setAudience] = useState<Audience>("unknown");

  const visibleCards = useMemo(
    () => practiceCards.filter((card) => card.category === selectedCategory),
    [selectedCategory]
  );

  return (
    <main>
      <h1>AWS Manila Community Day 教育導向 他加祿語 練習</h1>
      <p>選擇情境、選擇受眾,然後揭示 他加祿語 答案。</p>

      <label>
        受眾
        <select value={audience} onChange={(event) => setAudience(event.target.value as Audience)}>
          {audiences.map((item) => <option key={item} value={item}>{item}</option>)}
        </select>
      </label>

      <CategorySelector categories={categories} selected={selectedCategory} onChange={setSelectedCategory} />

      {visibleCards.map((card) => (
        <PracticeCardView key={card.id} card={card} audience={audience} />
      ))}
    </main>
  );
}

程式碼說明

  • 商業邏輯: 學習者依情境與受眾練習片語。
  • 程式碼邏輯: useState 追蹤分類與受眾;useMemo 針對選取分類有效率地篩選卡片。
  • 預期結果: 選擇「directions」會顯示問路卡;選擇「speaker」會先建議使用禮貌 他加祿語。

步驟 8 — 加入測試與資料品質 hook

Kiro 提示範例

為教育練習流程產生測試。
驗證分類篩選、揭示行為、speaker 受眾的禮貌指引,以及審查狀態是否可見。
建立一個 Kiro hook,在卡片資料變更時提醒開發者驗證 reviewStatus。

系統設計決策

  1. 行為測試優先於 snapshot 測試: 關鍵學習行為是分類篩選與揭示。測試應模擬學習者操作,而不是只比較 HTML snapshot。
  2. 必須驗證禮貌指引: App 的差異化在於教育性的語氣支援。如果受眾選擇不再對講者建議禮貌說法,即使 UI 仍可渲染,產品仍然失敗。
  3. 資料變更 hook: 語言 App 會頻繁更新內容。監看 src/data/ 的 Kiro hook 可在內容變更時提醒開發者檢查審查狀態、非正式標籤與發音覆蓋率。

程式碼範例 — src/tests/politeness.test.ts

import { describe, expect, it } from "vitest";
import { getPolitenessGuidance } from "../lib/politeness";

describe("getPolitenessGuidance", () => {
  it("recommends polite 他加祿語 for speakers", () => {
    const result = getPolitenessGuidance("speaker");
    expect(result.recommendedVariant).toBe("polite");
    expect(result.message).toContain("polite 他加祿語");
  });

  it("allows natural 他加祿語 for relaxed peer context", () => {
    const result = getPolitenessGuidance("peer");
    expect(result.recommendedVariant).toBe("natural");
  });
});

程式碼說明

  • 商業邏輯: 測試確認教育規則:面對講者時,禮貌說法較安全。
  • 程式碼邏輯: 測試直接呼叫 helper,並斷言回傳的建議。
  • 預期結果: 如果禮貌規則意外被削弱,測試會失敗。

Kiro hook 範例 — .kiro/hooks/card-data-quality.md

# Hook:卡片資料品質提醒

觸發條件:儲存 `src/data/` 底下的檔案時。
動作:
1. 檢查每張卡都有 `reviewStatus`。
2. 檢查每張卡都有發音文字。
3. 提醒開發者,`draft` 內容在發布到正式環境前需要母語者審查。
4. 如果新增分類,建議新增或更新測試。

Hook 說明

  • 商業邏輯: 隨著資料集成長,hook 讓教育內容持續可審查。
  • 程式碼邏輯: 它把品質提醒綁定到資料變更,而不是依賴人工記憶。
  • 預期結果: 每當內容變更時,開發者都會被提醒維持審查與發音標準。

完成檢查清單

  • 已建立教育導向 steering。
  • 已建立 Kiro spec 任務。
  • 練習卡模型包含分類、語氣、發音與審查狀態。
  • 禮貌用語 helper 是確定性的,且已有測試。
  • 分類選擇器可以篩選卡片。
  • 提示/揭示卡可正常運作。
  • 已有資料品質的 Kiro hook 指引。

工作坊後的選用 AWS 延伸

  • 將靜態建置部署到 AWS Amplify Hosting。
  • practiceCards 以具版本控管的 JSON 存在 Amazon S3。
  • 使用 Kiro 為已審查的學習內容產生發布檢查清單。
  • 只有在人工作審查流程後方,才加入 Amazon Bedrock 草稿產生功能。

額外動手開發實驗

這些實驗是 工作坊 2 — 教育優先開發技巧 專屬內容。它們以教學法、學習者信心、內容審查與尊重語言 guardrail,延伸核心提示/揭示 App。重點不是一般 Kiro 設定,而是把教育意圖轉化成開發者看得見的產品行為。

動手實驗 A — 在加入更多卡片前建立學習成果評量規準

開發者操作

  • 請 Kiro 建立一份 rubric,定義初學者完成每個分類後應該能做到什麼。
  • 把 rubric 加到 .kiro/steering/learning-rubric.md
  • 請 Kiro 依照 rubric 比對目前的 practiceCards 資料。
  • 把缺少的學習成果轉成小型實作任務。

Kiro 提示範例

為這個 他加祿語 練習 App 建立學習成果 rubric。
依 greetings、directions、workshops、thanks 與 waiting 分組成果。
為每個分類定義初學者成功標準、尊重說法期待、發音期待與審查風險備註。
接著檢查目前的練習卡模型,並把缺口列為實作任務。

系統設計決策

  • 先有 rubric,再擴充內容: 更多卡片不會自動改善學習。Rubric 會在開發者大量加入資料前,先說清楚每個分類應該教什麼。
  • 以成果驅動資料審查: 卡片只有在支援具體學習者行動時才有用,例如有禮貌地向志工打招呼,或詢問房間在哪裡。
  • 讓 Kiro 擔任課程審查助手: Kiro 可以依 rubric 比對實作成品並產生可行的缺口清單,而最終語言審查仍由母語者負責。

程式碼範例 — .kiro/steering/learning-rubric.md

# 學習 Rubric

每個練習分類都必須支援一個初學者行動、一個尊重標記,以及一個開口信心目標。

## Greetings
- 初學者行動:介紹自己是正在學 他加祿語 的人。
- 尊重期待:在第一次接觸的問候中顯示 `po`。
- 發音期待:包含 `Kumusta` 與 `他加祿語` 的重音指引。
- 審查風險:避免宣稱某個問候在所有地區或場合都正確。

## Directions
- 初學者行動:詢問活動房間、報到櫃台或出口在哪裡。
- 尊重期待:面對志工與場地人員時使用禮貌問句形式。
- 發音期待:包含 `Saan po` 的短指引。
- 審查風險:地點用語應檢查是否符合自然活動用法。

## Workshops
- 初學者行動:詢問是否可以發問、請對方重複、加入或入座。
- 尊重期待:面對講者與主辦方時使用禮貌措辭。
- 發音期待:包含溫和提問的開口提示。
- 審查風險:避免聽起來像命令的措辭。

程式碼說明

  • 商業邏輯: Rubric 先定義教育品質,再談內容數量。
  • 程式碼邏輯: Kiro 可在產生卡片、測試與審查任務時使用這份 steering 檔案。
  • 預期結果: 未來新增卡片會依學習成果檢查,而不是只因為能編譯就被接受。

動手實驗 B — 為初學者練習加入信心等級模型

開發者操作

  • 為每張練習卡加入學習者可見的信心等級。
  • 請 Kiro 更新 TypeScript 模型與種子資料。
  • 在提示附近呈現信心等級,讓學習者知道卡片難度。
  • 加入測試,確認每張卡都有信心等級。

Kiro 提示範例

在練習卡資料合約中加入初學者信心模型。
使用 confidenceLevel 值:starter、guided、stretch。
Starter 卡片應該短,且適合第一次接觸時使用。
Guided 卡片可以包含短情境備註。
Stretch 卡片可以包含較長的禮貌片語。
更新型別、範例資料、UI 標籤與測試。

系統設計決策

  • 信心是學習設計的一部分: 初學者需要知道哪些片語適合先嘗試。難度標籤可避免 App 把每個句子都視為同樣容易接近。
  • 用小型 enum 取代自由文字: 固定的 union type 可避免 easy、beginner、simple 或 basic 等不一致標籤。
  • Metadata 應可見: 信心等級應顯示在 UI 中,而不是藏在資料裡,因為學習者會用它選擇練習流程。

程式碼範例 — src/data/practiceCards.ts

export type ConfidenceLevel = "starter" | "guided" | "stretch";

export interface PracticeCard {
  id: string;
  category: PracticeCategory;
  englishPrompt: string;
  naturalTagalog: string;
  politeTagalog: string;
  tone: "casual" | "polite" | "event-ready" | "informal-playful";
  pronunciation: string;
  reviewStatus: ReviewStatus;
  confidenceLevel: ConfidenceLevel;
}

export const confidenceLabels: Record<ConfidenceLevel, string> = {
  starter: "Start here",
  guided: "Practice with context",
  stretch: "Try after rehearsal"
};

程式碼說明

  • 商業邏輯: 模型協助學習者選擇可達成的練習卡。
  • 程式碼邏輯: ConfidenceLevel 限制有效值,confidenceLabels 則集中管理顯示文字。
  • 預期結果: 新卡片若省略預期的初學者難度,就會造成型別或驗證缺口。

動手實驗 C — 為提示/揭示練習建立提示階梯

開發者操作

  • 請 Kiro 加入 optional hints,在完整 他加祿語 答案前顯示。
  • 實作一個 helper,為卡片回傳有順序的提示。
  • 用「Show hint」與「Reveal answer」動作更新練習卡 UI。
  • 加入測試,驗證提示會在答案前出現。

Kiro 提示範例

為提示/揭示練習建立提示階梯。
提示應在顯示完整答案前,先揭示分類情境、第一個字、尊重標記與發音提示。
讓提示保持確定性,並從既有卡片物件推導。
為提示優先的學習流程加入元件測試。

系統設計決策

  • 支架式回想,而不是立刻給答案: 提示階梯鼓勵學習者在完整揭示前先主動記憶。
  • 推導式提示降低內容負擔: 第一版可從既有卡片欄位推導提示,而不要求作者維護新的提示資料集。
  • 確定性行為可測試: UI 可以證明提示會依序出現,且完整答案會保持隱藏直到被要求顯示。

程式碼範例 — src/lib/hints.ts

import type { PracticeCard } from "../data/practiceCards";

export interface PracticeHint {
  label: string;
  value: string;
}

export function buildHintLadder(card: PracticeCard): PracticeHint[] {
  const firstWord = card.politeTagalog.split(/\s+/)[0] ?? "";
  const hasPo = /\bpo\b/i.test(card.politeTagalog);

  return [
    { label: "情境", value: `這是用於 ${card.category} 的練習。` },
    { label: "第一個字", value: firstWord },
    {
      label: "尊重標記",
      value: hasPo ? "聽聽禮貌版本中的 po。" : "這個片語沒有 po 標記。"
    },
    { label: "發音提示", value: card.pronunciation }
  ];
}

程式碼說明

  • 商業邏輯: 提示協助學習者排練,而不是立刻複製答案。
  • 程式碼邏輯: Helper 讀取 categorypoliteTagalogpronunciation,建立可預測的提示步驟。
  • 預期結果: 學習者可以在揭示完整片語前,逐步要求指引。

動手實驗 D — 為禮貌指引加入受眾安全矩陣

開發者操作

  • 請 Kiro 建立受眾與建議語氣行為的矩陣。
  • 用結構化 policy 輸出取代單一訊息的禮貌指引。
  • 為每個 audience 值加入單元測試。
  • 請 Kiro 找出可能讓學習者困惑的 UI 標籤。

Kiro 提示範例

將禮貌用語 helper 重構為受眾安全矩陣。
對每個 audience 回傳 recommendedVariant、safetyLevel、reason 與 learnerWarning。
對 speakers、organizers、volunteers、venue staff、elders 與 unknown contacts 使用更嚴格的指引。
為每個 audience 值產生 Vitest case。

系統設計決策

  • Policy table 優先於巢狀條件式: 矩陣比散落的 if statement 更容易讓教育者與母語者審查。
  • 安全等級支援 UI 決策: App 可在不改變卡片 schema 的情況下,對陌生人或 blocked 內容顯示更強的警示。
  • 完整測試保護語氣規則: 每個 audience 值都應有測試,避免未來重構默默削弱尊重說法指引。

程式碼範例 — src/lib/audiencePolicy.ts

export type Audience = "peer" | "speaker" | "organizer" | "volunteer" | "venue-staff" | "elder" | "unknown";
export type SafetyLevel = "relaxed" | "careful" | "strict";

export interface AudiencePolicy {
  recommendedVariant: "natural" | "polite";
  safetyLevel: SafetyLevel;
  reason: string;
  learnerWarning: string;
}

export const audiencePolicy: Record<Audience, AudiencePolicy> = {
  peer: {
    recommendedVariant: "natural",
    safetyLevel: "relaxed",
    reason: "Natural 他加祿語 can be friendly with peers after rapport is established.",
    learnerWarning: "如果不確定,請使用禮貌措辭。"
  },
  speaker: {
    recommendedVariant: "polite",
    safetyLevel: "strict",
    reason: "Speakers are leading the session, so respectful speech is safer.",
    learnerWarning: "先從禮貌版本開始。"
  },
  organizer: {
    recommendedVariant: "polite",
    safetyLevel: "strict",
    reason: "Organizers manage the event and may be first-time contacts.",
    learnerWarning: "先使用禮貌措辭。"
  },
  volunteer: {
    recommendedVariant: "polite",
    safetyLevel: "careful",
    reason: "Volunteers are helping attendees, so respectful questions are appropriate.",
    learnerWarning: "請求協助時使用 po。"
  },
  "venue-staff": {
    recommendedVariant: "polite",
    safetyLevel: "strict",
    reason: "Venue staff are professional contacts in a public setting.",
    learnerWarning: "先使用禮貌版本。"
  },
  elder: {
    recommendedVariant: "polite",
    safetyLevel: "strict",
    reason: "Respectful speech is safer with elders.",
    learnerWarning: "除非對方另有提醒,否則使用禮貌標記。"
  },
  unknown: {
    recommendedVariant: "polite",
    safetyLevel: "strict",
    reason: "Unknown contacts require the safest default.",
    learnerWarning: "在情境明確輕鬆前,選擇禮貌 他加祿語。"
  }
};

程式碼說明

  • 商業邏輯: Policy 教導更安全、具受眾意識的說話選擇。
  • 程式碼邏輯: Record<Audience, AudiencePolicy> 讓缺少的受眾項目能被 TypeScript 看見。
  • 預期結果: UI 與測試可以共用一個清楚的 policy 物件處理所有語氣指引。

動手實驗 E — 為母語者回饋建立內容審查佇列

開發者操作

  • 請 Kiro 從草稿卡片產生審查佇列。
  • 加入一個函式,依分類與審查狀態分組卡片。
  • 在 App 或 console report 中呈現僅供開發者使用的審查摘要。
  • 加入測試,確認 blocked 卡片不會出現在學習者的預設練習清單中。

Kiro 提示範例

為 他加祿語 練習卡建立內容審查佇列。
依 reviewStatus 與 category 分組卡片。
Draft 卡片應顯示審查者問題。
Blocked 卡片應從預設學習者練習中排除。
加入一個小型且可測試的 helper,以及面向開發者的摘要元件。

系統設計決策

  • 審查 workflow 本身就是功能: 因為語言內容需要母語者審查,開發者需要看見哪些內容仍未審查。
  • 分離學習者視圖與審查者視圖: 學習者不應收到 blocked 內容作為建議練習,但審查者仍需要檢查它。
  • 依分類分組: 審查者可以在情境中評估片語,而不是掃描扁平清單。

程式碼範例 — src/lib/reviewQueue.ts

import type { PracticeCard, PracticeCategory, ReviewStatus } from "../data/practiceCards";

export type ReviewQueue = Record<ReviewStatus, Partial<Record<PracticeCategory, PracticeCard[]>>>;

export function buildReviewQueue(cards: PracticeCard[]): ReviewQueue {
  return cards.reduce<ReviewQueue>((queue, card) => {
    queue[card.reviewStatus] ??= {};
    queue[card.reviewStatus][card.category] ??= [];
    queue[card.reviewStatus][card.category]!.push(card);
    return queue;
  }, { draft: {}, "native-reviewed": {}, blocked: {} });
}

export function learnerPracticeCards(cards: PracticeCard[]) {
  return cards.filter((card) => card.reviewStatus !== "blocked");
}

程式碼說明

  • 商業邏輯: Helper 將審查管理與學習者練習分開。
  • 程式碼邏輯: buildReviewQueue 依狀態與分類分組卡片,learnerPracticeCards 則篩掉不安全內容。
  • 預期結果: 開發者可以看見哪些內容需要審查,而 blocked 內容不會被推薦給學習者。

動手實驗 F — 加入講師 exit ticket 與學習分析事件模型

開發者操作

  • 請 Kiro 為工作坊學習成果定義僅限本機的分析事件。
  • 加入 category selected、hint viewed、answer revealed 與 confidence selected 的事件類型。
  • 工作坊期間將事件保存在記憶體或 console;不要把 telemetry 傳到外部。
  • 依事件名稱產生講師 exit ticket 範本。

Kiro 提示範例

為工作坊 App 定義僅限本機的學習事件模型。
追蹤 category_selected、hint_viewed、answer_revealed 與 confidence_marked。
不要加入外部 telemetry 或網路呼叫。
建立一份短的講師 exit ticket 範本,詢問學習者練習了什麼,以及哪裡仍需要協助。

系統設計決策

  • 沒有外部複雜度的學習分析: 本機事件模型協助講師討論行為,同時讓工作坊保持隱私友善且免設定。
  • 事件對應教學法: 事件對應的是學習行動,而不是行銷指標。
  • Exit ticket 完成回饋循環: 開發者可以看見產品 instrumentation 如何支援教學改進。

程式碼範例 — src/lib/learningEvents.ts

export type LearningEventName =
  | "category_selected"
  | "hint_viewed"
  | "answer_revealed"
  | "confidence_marked";

export interface LearningEvent {
  name: LearningEventName;
  cardId?: string;
  category?: string;
  value?: string;
  occurredAt: string;
}

const events: LearningEvent[] = [];

export function recordLearningEvent(event: Omit<LearningEvent, "occurredAt">) {
  events.push({ ...event, occurredAt: new Date().toISOString() });
}

export function readLearningEvents() {
  return [...events];
}

程式碼說明

  • 商業邏輯: 模型捕捉可影響未來教學設計的學習者行動。
  • 程式碼邏輯: 工作坊期間事件儲存在記憶體中,不需要新增服務也能檢查。
  • 預期結果: 參與者可以討論教育產品如何負責任地衡量練習行為。

參考架構備註

  • 本工作坊強調的 Kiro 能力:教學法 steering、學習成果審查、受控的 TypeScript 重構、規則式禮貌 policy、由教育驗收條件產生測試,以及具審查意識的開發。
  • 產品範圍:為活動準備打造初學者友善的 他加祿語 練習。語言內容在 他加祿語 母語者審查前都維持草稿狀態。
  • 執行範圍:先做本機 React App。建立審查流程後,選用部署可使用 AWS Amplify Hosting 或 Amazon S3。