醫療診所:WordPress 至 Next.js + Payload CMS 遷移
一家位於東南部的中型骨科診所找到我們時,面臨一個在醫療保健領域中痛苦地常見的問題:他們的 WordPress 網站速度很慢、患者登記流程是 PDF 下載和傳真回傳的噩夢,而他們的 IT 合規官員因 HIPAA 暴露風險而失眠。六個月後,他們擁有了一個 Next.js 前端、Payload CMS 後端、符合 HIPAA 的患者登記表單,以及讓競爭對手的網站看起來像在撥號上網的 Lighthouse 分數。以下是我們確切的做法。
目錄
- 起點:我們在處理什麼
- 為什麼選擇 Next.js 和 Payload CMS
- 無頭架構中的 HIPAA 考量
- 患者登記重新設計
- 性能結果和 Lighthouse 分數
- 遷移策略:零停機、零排名損失
- 技術架構深度探討
- 經驗教訓
- 常見問題

起點:我們在處理什麼
該診所——我們稱之為東南骨科診所(保密協議,你知道規則)——自 2017 年以來一直在運行 WordPress。他們的設置對於一家在沒有太多技術監督下有機增長的醫療診所來說是典型的:
- WordPress 6.2,有 34 個插件(其中 11 個超過一年未更新)
- 共享主機,每月費用為 $29
- Contact Form 7 處理患者詢問——沒有加密,主機提供商沒有 BAA
- PDF 登記表單,患者必須下載、列印、手工填寫,然後傳真或帶到預約
- 頁面加載時間,行動版平均 6.8 秒
- Lighthouse 行動版分數:38
那個 Lighthouse 分數不是打字錯誤。三十八分。該網站有未優化的主圖片(其中一張是 4.2MB 的 PNG)、來自五個不同插件的阻塞式 CSS 渲染,以及由於插件衝突導致 jQuery 加載三次。
但真正的問題不是性能。是風險。
他們的聯絡表單正在收集患者姓名、電話號碼,有時還有醫療投訴描述。這些資料通過未加密的表單插件流動,儲存在共享主機上的 WordPress 資料庫中,並備份到沒有業務夥伴協議 (BAA) 的服務。他們的合規官員已經標記了這一點,他們的醫療事故保險承運人提出了尖銳的問題。
簡介
該診所需要:
- 一個快速、現代的網站,反映他們醫療服務的品質
- HIPAA 安全的患者登記表單,用於取代紙質流程
- 一個他們的辦公室經理可以更新的 CMS,無需致電開發者
- 更好的 SEO 性能(他們正在失去本地搜尋排名給新診所)
- 所有這些都不破壞銀行存款——他們是一個醫療診所,不是科技新創公司
為什麼選擇 Next.js 和 Payload CMS
我們評估了多個架構選項。以下是我們提交給客戶的誠實比較:
| 選項 | 優點 | 缺點 | 預計成本 |
|---|---|---|---|
| WordPress 重建(新主題 + 插件) | 員工熟悉、較低的前期成本 | 相同的 HIPAA 風險、性能天花板、插件依賴 | $15-25K |
| Webflow + 第三方表單 | 快速建立、好的性能 | HIPAA 合規選項有限、持續的每座位成本、供應商鎖定 | $20-30K |
| Next.js + Payload CMS | 完全控制、HIPAA 安全架構、最佳性能 | 更高的前期投資、需要主機管理 | $35-50K |
| Next.js + Sanity | 很好的編輯體驗、好的生態系統 | Sanity 的定價隨使用量增加、PHI 處理對雲端託管 CMS 的擔憂 | $30-45K |
我們推薦了 Next.js 與 Payload CMS,理由如下。
Next.js 是正確的前端
Next.js 14(此專案於 2024 年底開始,我們後來升級到 15)為醫療網站提供了確切需要的功能:
- 內容頁面的靜態生成 — 醫生簡介、服務描述、位置資訊。這些頁面很少改變,所以我們在構建時預先渲染它們。零伺服器請求時運算意味著快速 TTFB。
- 動態內容的伺服器元件 — 預約可用性、部落格文章和登記表單邏輯都受益於伺服器端渲染,而無需向客戶端傳送不必要的 JavaScript。
- 開箱即用的圖片優化 —
next/image具有自動 WebP/AVIF 轉換功能,取代了那些 4MB 的 PNG 圖片,轉換為適當大小、延遲加載的圖片。 - 安全標頭的中介軟體 — 我們使用 Next.js 中介軟體來設定嚴格的 CSP 標頭、HSTS 和其他 HIPAA 審計員喜歡看到的安全標頭。
如果你對我們的方法感興趣,我們已經詳細記錄了我們的 Next.js 開發能力。
Payload CMS 是正確的後端
我們選擇 Payload CMS 3.0 而不是其他無頭選項有幾個特定於醫療保健的原因:
自託管設計。 Payload 在你自己的基礎設施上運行。對於 HIPAA 來說這是不容談判的。當你在處理受保護健康資訊 (PHI) 時,你需要確切知道你的資料位於何處、誰有訪問權限,並能夠與你的基礎設施提供商簽署 BAA。雲端託管的 CMS 平台如 Contentful 或 Sanity 將資料儲存在他們的伺服器上——雖然有些在企業層級提供 HIPAA 合規性,但成本通常是自託管 Payload 在符合 HIPAA 的提供商上的 3-5 倍。
TypeScript 原生。 Payload 的配置就是 TypeScript。這意味著我們的內容模型、API 回應和前端類型都共享相同的真實來源。當辦公室經理將新欄位「保險預先授權號碼」新增到登記表單時,我們的前端立即通過生成的類型了解到這一點。
內建訪問控制。 Payload 的欄位級別訪問控制意味著我們可以建立行角,其中行銷人員可以編輯部落格文章和服務頁面,但無法觸及患者登記資料。辦公室經理可以查看登記提交但無法修改表單結構。當你在記錄合規性的訪問控制時,這種粒度很重要。
正確的富文本。 Payload 使用 Lexical(之前是 Slate)進行富文本,編輯體驗真的很好。我們客戶的辦公室經理多年來一直在使用 WordPress,在一次 45 分鐘的培訓課程中對 Payload 的管理面板感到很舒適。
我們經常與 Payload 和其他無頭 CMS 平台合作——你可以看到更多關於我們的 無頭 CMS 開發方法。
無頭架構中的 HIPAA 考量
讓我清楚地說一件事:沒有技術棧本身是「符合 HIPAA 的」。 HIPAA 合規性是一種組織實踐,不是軟體功能。一個技術棧可以是「HIPAA 安全的」——意味著它不會引入不必要的風險,並支持 HIPAA 要求的管理、實體和技術保障。
以下是我們實施的內容:
基礎設施
- 主機: AWS 具有簽署的 BAA。我們使用 ECS Fargate 來運行 Payload CMS 容器,並將 Next.js 前端部署到 Vercel(不處理 PHI——重要的區別)。
- 資料庫: Amazon RDS PostgreSQL,使用靜態加密 (AES-256) 和傳輸中加密 (TLS 1.2+)。Payload 3.0 原生支援 Postgres,這是我們等待 v3 的重大原因。
- 檔案儲存: S3,具有伺服器端加密、限制訪問的儲存體政策,以及為審計追蹤啟用的版本控制。
患者登記的資料流
這是架構變得有趣的地方。患者登記表單位於 Next.js 前端,但我們永遠不會通過 Vercel 的基礎設施傳送 PHI。
患者瀏覽器 → HTTPS → API 路由 (Vercel 上的 Next.js) → 此處不儲存 PHI
↓
AWS API 閘道 (含 WAF)
↓
Lambda 函數 (驗證、加密)
↓
Payload CMS API (在 ECS Fargate 上)
↓
RDS PostgreSQL (靜態加密)
Next.js API 路由充當一個薄代理。它驗證請求結構(CSRF 令牌、速率限制、基本欄位驗證),但不記錄或儲存任何 PHI。實際的資料處理完全發生在 AWS 的符合 HIPAA 的服務中。
加密詳細資訊
我們為最敏感的資料實施了欄位級別的加密。患者 SSN 片段(最後 4 位)、保險 ID 和醫療投訴描述在應用程式層使用 AES-256-GCM 加密,甚至在它們進入資料庫之前。這意味著即使有人獲得了資料庫訪問權限,他們也只會看到敏感欄位的加密 blob。
// Payload 中欄位級別加密掛鉤的簡化版本
import { encrypt } from '../lib/crypto';
const PatientIntake: CollectionConfig = {
slug: 'patient-intake',
hooks: {
beforeChange: [
async ({ data }) => {
if (data.ssnLastFour) {
data.ssnLastFour = await encrypt(data.ssnLastFour);
}
if (data.medicalComplaint) {
data.medicalComplaint = await encrypt(data.medicalComplaint);
}
return data;
},
],
},
access: {
read: ({ req: { user } }) => {
return user?.role === 'office-admin' || user?.role === 'provider';
},
create: () => true, // 公開表單提交
update: ({ req: { user } }) => user?.role === 'office-admin',
delete: () => false, // 保留政策 - 通過 CMS 無法刪除
},
fields: [
// ... 欄位定義
],
};
審計日誌
對患者登記資料的每次訪問都會被記錄——誰查看了它、何時以及來自哪個 IP。我們構建了一個自訂 Payload 外掛程式,它寫入單獨的審計日誌表。此表是仅追加的;即使是管理員使用者也無法修改或刪除條目。在該診所的年度 HIPAA 風險評估期間,這個審計追蹤被特別稱讚為優勢。

患者登記重新設計
舊流程:患者下載 6 頁 PDF、列印、用筆填寫(一半時間字跡模糊)、帶到辦公室,工作人員手動將其輸入他們的 EHR 系統。從下載到 EHR 輸入的平均時間:3-5 個工作日。
新流程:患者在預約前 48 小時收到簡訊或電子郵件連結、在他們的手機上完成多步表單,大約 8 分鐘,資料在他們走進大門之前就已在該診所的系統中可用。
表單 UX 決策
我們將登記表單分為 7 個步驟:
- 身份驗證(姓名、出生日期、聯絡資訊)
- 保險資訊(承運人、ID、群組編號、卡片照片上傳)
- 病史(病症檢查清單、手術史)
- 目前藥物(帶有開放式藥物清單的自動完成)
- 就診原因(自由文字 + 疼痛位置的身體圖表)
- 同意和協議(電子簽名捕捉)
- 審閱並提交
一些 UX 細節產生了真實的差異:
- 進度指示器顯示「第 3 步,共 7 步」將放棄率降低了約 40%,相比我們最初顯示所有欄位的原型。我們在軟發布期間對此進行了 A/B 測試。
- 保險卡照片上傳,具有自動裁剪和預覽。患者拍攝卡片的正面和背面。這樣做就消除了大約 60% 的前台資料輸入。
- 藥物自動完成使用 RxNorm API。患者不是嘗試拼寫「hydroxychloroquine」,而是輸入「hydro」並從過濾清單中選擇。這大幅降低了藥物輸入錯誤。
- 會話持久性 — 如果患者開始表單並被中斷,他們的進度會被儲存(在 sessionStorage 中加密,絕不在 localStorage 中)30 分鐘。他們可以從中斷的地方繼續。
// 使用 RxNorm API 的藥物自動完成
const useMedicationSearch = (query: string) => {
return useQuery({
queryKey: ['medications', query],
queryFn: async () => {
if (query.length < 3) return [];
const res = await fetch(
`/api/medications/search?q=${encodeURIComponent(query)}`
);
return res.json();
},
staleTime: 1000 * 60 * 5, // 快取 5 分鐘
enabled: query.length >= 3,
});
};
伺服器端藥物搜尋端點通過我們的 AWS 後端查詢 RxNorm,將外部 API 呼叫遠離客戶端,並允許我們快取結果。
性能結果和 Lighthouse 分數
以下是之前和之後的對比:
| 指標 | WordPress(之前) | Next.js + Payload(之後) | 改進 |
|---|---|---|---|
| Lighthouse 行動版 | 38 | 94 | +147% |
| Lighthouse 桌面版 | 61 | 99 | +62% |
| First Contentful Paint(行動版) | 4.2s | 0.8s | -81% |
| Largest Contentful Paint(行動版) | 8.1s | 1.4s | -83% |
| Total Blocking Time | 1,840ms | 45ms | -98% |
| Cumulative Layout Shift | 0.34 | 0.01 | -97% |
| Time to Interactive | 9.3s | 1.2s | -87% |
| 頁面重量(首頁) | 4.8MB | 340KB | -93% |
| Core Web Vitals 通過 | 否 | 是(全綠) | — |
行動版 Lighthouse 分數 94(不是 100,我稍後會解釋為什麼)是在患者登記頁面上測量的,這是網站上 JavaScript 最多的頁面。首頁和服務頁面等內容頁面在行動版和桌面版上都持續得分 98-100。
為什麼不在行動版上達到完美的 100?兩個原因:
- 藥物自動完成小工具需要客戶端 JavaScript,這為登記表單頁面增加了大約 12KB 的 gzip。
- 我們在登記表單上使用 reCAPTCHA v3 作為機器人預防層,Google 的 reCAPTCHA 指令碼並不完全輕量級。我們延遲加載它,但它仍然讓我們失去了幾分。
我們考慮過移除 reCAPTCHA 來達到 100 分,但安全優勢超過了虛榮指標。沒有機器人保護的醫療保健登記表單是在要求真實患者資料中混入垃圾郵件提交。
遷移策略:零停機、零排名損失
遷移醫療診所網站會產生壓力,因為停機字面上意味著患者預約丟失。以下是我們的處理方式:
內容遷移
我們編寫了一個遷移指令碼,從 WordPress REST API 提取內容並將其轉換為 Payload CMS 文件。該指令碼處理了:
- 47 個服務頁面
- 12 個醫生/提供者檔案
- 89 篇部落格文章(帶有重新託管的圖片)
- 6 個位置頁面
- 所有 SEO 中繼資料(標題、描述、規範 URL)
URL 對應
每個 WordPress URL 都對應到其 Next.js 等效項。我們盡可能保留相同的 URL 結構,並在 next.config.js 中為少數改變的 URL 設定 301 重定向:
// next.config.js
const redirects = async () => [
{
source: '/services/:slug',
destination: '/orthopedic-services/:slug',
permanent: true,
},
{
source: '/team/:slug',
destination: '/providers/:slug',
permanent: true,
},
// ... 23 個更多重定向
];
DNS 切換
我們使用了藍綠部署策略。新網站平行執行了兩週,而我們進行測試。在切換日,我們在週日晚上維護時段內更新了 DNS 記錄。總可見停機時間:約 3 分鐘(DNS 傳播速度很快,因為我們提前一週預先降低了 TTL 至 60 秒)。
SEO 結果
發布後三個月:
- 有機流量增加 34%
- 「orthopedic doctor near me」平均位置從位置 14 改進至位置 5
- Google 的點進率增加 28%(更好的 Core Web Vitals = 更好的行動版 SERP 體驗)
- 搜尋控制台中之前索引的 URL 無 404 錯誤
技術架構深度探討
對於想要完整圖景的人:
┌─────────────────────────────────────────────┐
│ Vercel │
│ ┌─────────────────────────────────────────┐ │
│ │ Next.js 15 App Router │ │
│ │ - 靜態頁面 (ISR, 60s 重新驗證) │ │
│ │ - 伺服器元件 │ │
│ │ - API 路由 (僅代理,無 PHI) │ │
│ └─────────────────────────────────────────┘ │
└──────────────────┬──────────────────────────┘
│ HTTPS
┌──────────────────▼──────────────────────────┐
│ AWS (HIPAA BAA) │
│ ┌──────────────┐ ┌─────────────────────┐ │
│ │ API 閘道 │ │ CloudFront (資產) │ │
│ │ + WAF │ └─────────────────────┘ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ ┌─────────────────────┐ │
│ │ ECS Fargate │──│ RDS PostgreSQL │ │
│ │ (Payload 3) │ │ (加密) │ │
│ └──────┬───────┘ └─────────────────────┘ │
│ │ │
│ ┌──────▼───────┐ ┌─────────────────────┐ │
│ │ S3 (上傳) │ │ CloudWatch (日誌) │ │
│ │ (加密) │ │ (審計追蹤) │ │
│ └──────────────┘ └─────────────────────┘ │
└─────────────────────────────────────────────┘
月度基礎設施成本:AWS 上約 $180-220/月(ECS Fargate 在此規模上出人意料地經濟實惠)加上 Vercel Pro 每月 $20。與他們之前 $29/月的共享主機相比——是的,它更昂貴,但他們獲得符合 HIPAA 的基礎設施、自動擴展和真正的安全性。
經驗教訓
1. 早期開始 HIPAA 對話。 我們在編寫一行程式碼之前花了三週進行架構規劃。這使我們避免了至少兩次可能的重新設計。
2. Payload CMS v3 值得等待。 我們在 Payload 3.0 處於測試版時開始了這個專案。有粗糙的邊緣——遷移文件不完整,一些外掛程式還沒有更新。但原生 Postgres 支援和改進的管理員 UI 使其成為正確的選擇。
3. 不要過度設計登記表單。 我們的第一個原型有六層深的條件邏輯。辦公室經理看著它說:「我們不能按順序提出問題嗎?」她是對的。我們簡化了,完成率上升了。
4. 醫療保健客戶需要 CMS 培訓的手把手指導。 我們提供了三次培訓課程而不是我們通常的一次,加上用於常見任務的錄製 Loom 視訊。培訓投資在第一個月就收回了,當時辦公室經理能夠添加新的提供者頁面而無需提交支援票。
5. 性能預算是不容談判的。 我們在專案開始時設定了 <400KB 頁面重量和 <100ms Total Blocking Time 的性能預算。每個 PR 都在 CI 中針對此預算進行檢查。唯一一次我們嘗試添加動畫插圖庫時,它超出了預算,我們在它發布之前就發現了。
如果你正在考慮為醫療保健或受管制行業網站進行類似的遷移,我們很樂意討論具體情況。你可以 直接與我們聯繫 或查看我們的 定價頁面 以了解專案範圍。
常見問題
使用 Next.js 和 Payload CMS 會自動使網站符合 HIPAA 嗎? 不會。沒有技術棧本身符合 HIPAA。HIPAA 合規性需要管理保障措施(政策、培訓、風險評估)、實體保障措施(設施訪問控制)和技術保障措施(加密、訪問控制、審計日誌)。Next.js 和 Payload CMS 給你的是一個靈活的架構,你可以正確實施技術保障措施——尤其是 Payload 的自託管性質,它讓你控制 PHI 位於何處。
為什麼不只使用符合 HIPAA 的表單服務,如 Jotform 或 FormStack? 你完全可以,對於更簡單的用例,這是一個合理的選擇。我們評估了 Jotform 的 HIPAA 計劃($99/月)和 FormStack($83/月)。對於該客戶的問題是整合深度——他們希望登記資料流入一個自訂工作流程,該流程實時檢查保險資格並預先填充他們的 EHR 系統。現成的表單工具無法在沒有重要中介軟體的情況下處理這個問題,此時你無論如何都在構建自訂基礎設施。
總專案成本和時間線是多少? 該專案耗資約 $42,000,歷時 14 週。這包括發現和架構規劃(3 週)、設計(2 週)、開發(7 週)和測試/遷移(2 週)。持續的主機和維護費用約為每月 $250,包括基礎設施成本和小型支援保留。
Payload CMS 能否為醫療保健集團處理多個位置? 能。我們在 Payload 中構建了一個「位置」集合,欄位用於地址、營業時間、提供者、接受的保險和特定位置的內容。每個位置通過 Next.js 獲得自己的頁面,具有結構化資料標記(LocalBusiness 架構),用於本地 SEO。添加新位置與在 Payload 的管理面板中建立新條目一樣簡單。
你如何處理患者資料保留和刪除要求? 我們實施了自動資料生命週期政策。登記表單提交保留 7 年(與該診所的州醫療記錄保留要求相符),之後會自動存檔到 S3 Glacier,最終被刪除。患者也可以根據州隱私法請求資料訪問或刪除——我們在 Payload 中構建了一個管理工作流程,員工可以通過完整審計追蹤處理這些請求。
如果 Payload CMS 伺服器宕機怎麼辦? Next.js 前端從 Vercel 的 CDN 提供靜態生成的頁面,所以即使 Payload 後端完全離線,主網站也保持運行。患者登記表單在後端中斷期間將不可用,但我們已配置 ECS 與自動重啟策略、每 30 秒的健康檢查,以及會向我們團隊和該診所的 IT 聯絡人發出警報的 CloudWatch 警報。在 6 個月的生產中,我們有零個計劃外停機時間。
對於位置單一、患者量較少的小型診所來說,這個架構是過度設計嗎? 取決於你在處理什麼患者資料。如果你只是需要一個宣傳冊網站,上面有電話號碼和地址,WordPress 與一個好的主題就可以了——你不需要任何這些。但從你通過你的網站收集 PHI 的時刻(登記表單、醫療問卷、含有醫療詳細資訊的預約請求),你需要支援適當安全控制的基礎設施。我們構建的架構縮小規模很好——單一位置的診所由於流量較低,基礎設施成本會較低。
遷移如何影響 Google 排名? 我們在遷移後立即看到了短暫(約 10 天)的排名波動,這是正常的。到第 3 週,排名已穩定並趨於上升。到第 3 個月,有機流量上升了 34%,該診所的主要關鍵字平均改進了 4 個位置。Core Web Vitals 改進是最大的因素——Google 一直在搜尋結果中處罰他們舊網站的差劣行動版性能。