先問清楚四件事,不要讓決策散落在工作中間
執行三個並行 Phase 最貴的成本不是打程式碼,而是工作到一半停下來等答案。 開工前列了 21 條 TodoWrite,然後一次性問清楚四個後段會卡住的決策: GitHub Sponsors 帳號開了沒(已開)、付款服務商選誰(Polar.sh,Merchant of Record、4% 抽成)、 定價策略是什麼(IP 判斷 TW/其他,雙幣別自動偵測)、Phase 3 文章發在哪裡(Bobo Labs /formulas/ 子站)。
四個決策全部前置收完,後面推進才真正不會中斷。 比「做到哪、問到哪」省下大量 context switching,這個模式值得在未來所有多 Phase 任務裡複用。
Phase 1:贊助按鈕為什麼不放在右下角
計畫書原本寫「右下角浮動按鈕」。實作前評估了兩個問題: CLAUDE.md 開發禁忌明列「不放計算機按鈕區廣告」,而且浮動層在手機上會擋到 UI。 沒有硬性規定一定要右下角,只是「浮動 = 曝光」這個直覺把人帶過去的。
最後改在 header controls 區放一個心形按鈕(紅 #f43f5e),36×36 圓形、與右側 help 按鈕並排。
設計一致、不擋 UI、語意清楚——三個條件都達到,而且不需要任何額外的 z-index 管理。
設計問題的答案通常不在「要不要加」,而在「放在哪裡才不尷尬」。
Modal 的重用策略:借語意不精確的 class,換一致的 layout
∑ Calc 已有三個 modal(help / formula / graph),每個各自一套 CSS,沒有共用的 base class。 新的 support modal 需要 overlay + 置中容器 + 關閉按鈕這三件事,.help-modal 剛好有這三件事。
「help-modal」這個命名其實是「dialog overlay layout」的意思,只是歷史原因叫這個名字。 我選擇複製 .help-modal 結構給 supportModal,再加 .support-cta / .support-uses 等內容專用樣式。 寧可借語意不夠精確的舊 class,也不為一個新功能再開一套設計系統。 如果未來三個 modal 都要統一,那時再一次性抽 base class,現在抽是過早設計。
a11y 完整跟進:role="dialog" + aria-modal="true" + aria-labelledby="supportModalTitle", 與既有 openModal()/closeModal() helper 整合(焦點移入、Tab 陷阱、Escape 關閉、關閉後焦點還原)。 #/support 與 #support 兩種 hash route 都支援。
驗證踩坑一:hash 路由是 microtask,同步斷言永遠太早
第一輪驗證寫了一段 console 測試:設定 location.hash = '#/support',然後立刻讀 modal 的 classList。 結果 modal_active: false,以為 bug。
實際原因是:hashchange 事件是 microtask,同步讀取狀態的時間點是在事件 handler 執行前。 加了 await new Promise(r => setTimeout(r, 50)) 之後,modal_active: true,一切正常。 DOM 副作用 + event listener 的驗證,務必跨一個 microtask 再讀狀態。
驗證踩坑二:截圖工具的「mobile」不等於 375px
截圖看 modal 視覺「向左溢出」,懷疑 RWD 壞掉。inspect 實測: viewport_width 是 478(preset 'mobile' 不是預期的 375)、modal_x = 16、modal_width = 446, 完全沒有 overflow。是截圖工具的顯示比例造成視覺錯覺。
先 inspect 實際 BoundingClientRect 再下排版判斷。 截圖看起來壞掉不等於真的壞掉,視覺縮放比例會說謊。
Phase 2.1:公式分層先寫 Markdown,不直接改程式碼
100 條公式要分 Free / Pro 兩層。分層比例最終是 Free 59 / Pro 41, 按「會在國高中課本看到」全 Free、「大三以上 + 業界專用」全 Pro 的原則切分。 E=mc² 雖然名氣大但放 Pro——「破解愛因斯坦最有名方程式」是強付費鉤子。
但這 41 條 Pro 的分類沒有直接寫進 builtInFormulas 程式碼——
而是寫進 docs/MONETIZATION-PHASE-2-TIER-SPLIT.md(148 行 Markdown)。
原因很直接:使用者要調整名單時不需要 revert 程式碼,改 Markdown 即可,
等確認後再批次寫入 tier: 'pro' 欄位。
結構性大改動,先用文件層討論完再落程式。
Phase 3:十篇文章的選題邏輯
/formulas/ 子站建在靜態 HTML 架構裡,新增 formula.css(240 行)加入公式專用樣式: formula-box、變數表、iframe 容器、警示框、卡片 grid。 索引頁 90 條未寫公式標 is-placeholder 灰卡,不占文章 token。
十篇選題按「高搜尋量 + 覆蓋 6 分類」:勾股定理、二次函數、歐姆定律、複利終值、 72 法則、pH 值、動能、波速(Wi-Fi / 5G 連結時事)、BMI(全球搜尋量第一健康公式)、 E=mc²(Pro 鉤子)。第一篇(勾股)寫 1500 字完整版作為黃金示範, 後九篇精煉到 800-1200 字維持 token 預算,單 session 完成十篇。
iframe deep link 用 ?formula=N query param,加 16 行 JS:
頁面載入時 parse query → 切到公式 tab → setTimeout 80ms 後 trigger 卡片 click → 自動開 modal。
完整 embed mode(隱藏 header / sidebar)留後續。
「點 iframe 直接看到目標公式」已能滿足 SEO 文章的試算需求,MVP 原則套用在新功能同樣有效。
三次 commit,兩個 repo,一輪 push
整個 session 的程式碼最終壓縮成三筆 commit: Phase 1 Sponsor(v3.7.0,boboidvtw.github.io,160 行)、 Phase 2.1 + 3.2(v3.7.1,同 repo,164 行)、 Phase 3.1-3.4(bobo-labs,1708 行,10 篇 + CSS + sitemap + robots.txt)。 兩個都是公開 repo,push 前用 AskUserQuestion 拿核可。
驗證清單全部過:sw.js = sigma-calc-v3.7.1、?formula=11 自動開勾股定理 modal、 ?formula=71 自動開動能 modal、Bobo Labs /formulas/ 各頁 200、console 零 error。
關鍵教訓
決策前置收完:三 Phase 並行時,一輪 AskUserQuestion 把所有阻塞性決策全收完。比「做到哪、問到哪」省下大量 context switching 成本。
Markdown 先行:結構性大改動(公式分層 41 條)先寫文件讓人審閱,確認後再一次性落程式。文件改比 code revert 成本低幾個數量級。
hash 路由驗證要跨 microtask:hashchange 是 microtask,同步斷言永遠在事件 handler 前。加 setTimeout(50) 是正確的等待點,不是 workaround。
截圖說謊,BoundingClientRect 不說謊:viewport preset 不等於你以為的寬度,視覺「溢出」可能只是縮放比例問題。先 inspect 再判斷。
借舊 class 不開新設計系統:一個新功能的 modal 借用現有 .help-modal layout,過早抽 base class 是浪費。等三個 modal 都需要統一再一次抽。
內容生產要先建模板再批量產出:10 篇公式文章,第 1 篇 1500 字黃金示範,第 2-10 篇套模板 800-1200 字。單 session 完成,token 預算可控。