前言

這個 Shopify App 的首頁最初很像一張開發進度報告:列出 MVP 已完成哪些 phase、目前要求哪些 scopes、正式上架還缺哪些環境與 runbook。對開發者來說很完整,商家打開後卻不知道「我現在能做什麼」。

上一篇建立了 Shopify App Readiness CLI。當 developer diagnostics 已有自己的執行入口,下一個設計問題就是:商家 App Home 應保留哪些狀態,又有哪些內容應移到 CLI、CI、monitoring 或內部文件?

原本的做法與問題症狀

第一版首頁把所有進度都視為「狀態」:

  • App 已完成哪些技術模組。
  • 目前 API scopes。
  • production database 與 scheduler 是否準備。
  • privacy/listing/runbook 是否審閱。
  • 下一個開發 phase 是什麼。

資訊本身不一定錯,問題在責任對象。商家通常只能完成外部連線、欄位 Mapping、同步開關與失敗修復;他無法在 App Home 裡修改 production datasource、部署 migration 或更新 Partner Dashboard listing。

結果是高嚴重度但不可操作的紅字,和商家真正需要處理的設定混在一起。更糟的是,developer diagnostics 可能透露內部架構、環境狀態或安全控制名稱,卻沒有為商家增加決策價值。

問題是怎麼推敲出來的?

來源 Git history 有一個很直接的修正:remove developer readiness from merchant ui。對應測試從「首頁應顯示目前實作狀態」改成「首頁應顯示 merchant-focused sync overview,而且不能再出現 MVP、上架前重點與權限診斷文案」。

研究當下的 route 也把資料來源改成 shop-scoped facts:

  • 是否已連接外部資料系統。
  • 訂單與會員是否各有 active Mapping。
  • 兩種 Webhook 自動同步是否都啟用。
  • 最近同步是否有失敗。
  • 最近幾筆同步結果。

這些資料能直接產生「需要處理」與「前往設定」CTA。首頁不再回答「工程團隊完成了什麼」,而是回答「這間商店現在能否順利使用,以及下一步在哪裡」。

最後採用的架構

資訊依責任對象分成三個 surface:

Merchant App Home
  → shop-scoped connection / mapping / sync state
  → immediate attention items
  → settings and recovery CTA

Developer / Operator diagnostics
  → environment / schema / migration / scheduler
  → CI gates, readiness CLI, logs, alerts, runbooks

Shopify Dev Dashboard / Review
  → App config, listing, protected data requests
  → automated checks and App Review

同一個事實可能需要兩種表達。例如 worker 沒有執行:

  • 商家看到「自動同步未啟用」或「最近同步失敗」,並能前往設定或聯絡支援。
  • Operator 看到 scheduler endpoint、worker authentication、queue depth 與 deployment log。

不是把錯誤藏起來,而是讓每個人看到他能採取行動的解析度。

關鍵實作

Loader 只組合 merchant-facing 狀態:

const [connection, mappings, recentLogs, orderSync, customerSync] =
  await Promise.all([
    getConnection(shop),
    getMappings(shop),
    getRecentSyncLogs(shop, 5),
    getSyncSetting(shop, 'order'),
    getSyncSetting(shop, 'customer'),
  ]);

return {
  connected: Boolean(connection),
  orderMappingReady: hasActiveMapping(mappings, 'order'),
  customerMappingReady: hasActiveMapping(mappings, 'customer'),
  automaticSyncEnabled: orderSync.enabled && customerSync.enabled,
  attentionItems: buildMerchantAttentionItems(...),
};

畫面則依「狀態 → 需要處理 → 最近結果」排序:

<StatusSummary dashboard={dashboard} />
<AttentionItems items={dashboard.attentionItems} />
<Button href="/app/settings">前往設定</Button>
<RecentSyncResults rows={dashboard.recentSyncs} />

這裡還有一個重要安全邊界:errorMessage 不能把 raw API response、顧客資料、token 或內部 stack trace直接顯示給商家。Developer log 與 merchant-safe message 應是兩個欄位或經過明確 sanitization。

實際驗證

來源 route 與測試可證明:

  • Loader 使用 authenticated shop 查詢資料,不接受 browser 自行指定 shop。
  • Connection、Mapping、sync settings 與 recent logs 以同一 shop 為範圍。
  • 沒有連線、缺少任一 active Mapping、或最近同步失敗時會建立 attention item。
  • 首頁有同步狀態、需要處理、最近同步結果與設定 CTA。
  • Route test 明確拒絕 MVP、上架前重點與 developer scope 診斷文案。
  • Git history 保留從 progress report 改成 merchant workflow 的設計差異。

證據邊界是:研究當下來源 worktree 有尚未提交的 UI 變更。本文可以說程式與測試已存在,也能還原設計決策;不能說這個版本已合併、部署或經真實商家驗收。

仍然存在的限制

第一,四個 boolean 只適合早期版本。Mapping 可能是 needs review,sync 可能只啟用 order、最近一筆成功也不代表過去一小時沒有 error;長期需要更清楚的狀態模型。

第二,automaticSyncEnabled = order && customer 會把「只需要同步訂單」的合法商家顯示成未完成。首頁應依商家實際啟用的 use case 判斷,不該把所有 capability 當成必做 onboarding。

第三,最近五筆 log 不是 monitoring。它沒有 queue backlog、延遲、錯誤率、Webhook delivery failure 或 reconciliation 結果。商家可見摘要與 operator observability 仍需分開建置。

第四,錯誤訊息要能行動。只顯示「同步失敗」容易讓商家反覆重試;應附安全的錯誤分類、受影響資料、最後成功時間與正確 CTA。

最後,Shopify 的 App Home patterns 在持續演進。2026-07 的文件已提供 homepage/settings templates 與 setup guide composition;現有自製列表可以逐步換成這些模式,但不需要為了使用新元件而改變責任分面的原則。

可以延伸到哪些情境?

判斷一段資訊該放哪裡,可以問三個問題:

  1. 誰能採取行動?
  2. 行動能否在這個 surface 完成?
  3. 顯示這項資訊會不會暴露不必要的內部細節?

這套分法可套用到 billing、POS、Theme、ERP、warehouse 與 AI admin tool。商家介面顯示業務狀態與下一步;release readiness、security finding、deployment topology 與 raw traces 留在受控的 developer/operator 工具。

下一篇會處理更不能只看表面狀態的流程:Shopify GDPR Webhook 不只是回傳 200

參考資料

以上平台文件查核日期:2026-07-28。