醫療保健 WordPress 遷移至 Next.js + Payload CMS (符合 HIPAA)
您的患者在 WordPress 網站上點擊「新患者表格」。六秒鐘過去。PDF 終於加載。他們打印出來,手工填寫,然後傳真回去——因為您的入院系統是在 2014 年構建的。同時,您的 IT 合規官員剛剛發現患者數據流經三個未保護的插件,您的移動 Lighthouse 分數是 34。東南部的一家中型骨科診所面臨過這個確切的情況。六個月後:Next.js 前端、Payload CMS 後端、符合 HIPAA 的入院表格,以及 94/99 的 Lighthouse 分數。但真正的勝利不是速度——而是我們在他們的審計前關閉的四個 HIPAA 暴露點。
目錄
- 起點:我們在處理什麼
- 為什麼選擇 Next.js 和 Payload CMS
- 無頭架構中的 HIPAA 考慮
- 患者入院重新設計
- 性能結果和 Lighthouse 分數
- 遷移策略:零停機、零排名損失
- 技術架構深入探討
- 經驗教訓
- 常見問題

起點:我們在處理什麼
該診所——我們就叫他們東南骨科診所(NDA,你知道怎麼回事)——自 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 發送給客户端。
- 開箱即用的圖像優化 ——帶有自動 WebP/AVIF 轉換的
next/image用適當大小的、延遲加載的圖像替換了那些 4MB PNG。 - 用於安全頭的中間件 ——我們使用 Next.js 中間件設置嚴格的 CSP 頭、HSTS 和其他 HIPAA 審計員喜歡看到的安全頭。
如果您對我們的方法感興趣,我們已經詳細記錄了我們的 Next.js 開發能力。
Payload CMS 是正確的後端
我們選擇 Payload CMS 3.0 而不是其他無頭選項,原因是特定於醫療保健的:
自託管設計。 Payload 在您自己的基礎設施上運行。對於 HIPAA,這是不可談判的。當您處理受保護的健康信息 (PHI) 時,您需要確切地知道您的數據位於何處、誰有訪問權限,並能夠與您的基礎設施提供商簽署 BAA。雲託管的 CMS 平臺如 Contentful 或 Sanity 將數據存儲在他們的服務器上——雖然一些在企業級提供 HIPAA 合規性,但成本通常是在 HIPAA 合格的提供商上自託管 Payload 所付費用的 3-5 倍。
TypeScript 原生。 Payload 的配置就是 TypeScript。這意味著我們的內容模型、API 響應和前端類型都共享同一個真實來源。當辦公經理向入院表格添加「保險預授權號」的新字段時,我們的前端通過生成的類型立即了解它。
內置訪問控制。 Payload 的字段級訪問控制意味著我們可以創建角色,其中營銷人員可以編輯博客文章和服務頁面,但無法涉及患者入院數據。辦公經理可以查看入院提交但無法修改表格結構。在記錄合規性訪問控制時,這種粒度很重要。
富文本做得對。 Payload 使用 Lexical(以前是 Slate)進行富文本編輯,編輯體驗確實很好。我們客户的辦公經理,多年來一直在使用 WordPress,在單個 45 分鐘的 Payload 管理員訓練課程中感到舒適。
我們定期與 Payload 和其他無頭 CMS 平臺合作——您可以看到更多關於我們 無頭 CMS 開發方法 的信息。
無頭架構中的 HIPAA 考慮
讓我明確說一點:沒有技術棧本身是「符合 HIPAA」的。 HIPAA 合規性是一種組織實踐,不是軟件功能。技術棧可以是什麼是「HIPAA 安全」——意味著它不會引入不必要的風險,並支持 HIPAA 要求的行政、物理和技術保障。
以下是我們實現的:
基礎設施
- 託管: AWS 簽署了 BAA。我們為 Payload CMS 容器使用了 ECS Fargate,並將 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。患者不是試圖拼寫「羥氯喹」,而是鍵入「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% |
| 首次內容繪製 (移動) | 4.2s | 0.8s | -81% |
| 最大內容繪製 (移動) | 8.1s | 1.4s | -83% |
| 總阻止時間 | 1,840ms | 45ms | -98% |
| 累積佈局移位 | 0.34 | 0.01 | -97% |
| 互動時間 | 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%
- 「我附近的骨科醫生」的平均位置從位置 14 改進到位置 5
- Google 的點擊率增加 28% (更好的 Core Web Vitals = 更好的移動 SERP 體驗)
- Search Console 中以前索引的 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 總阻止時間的性能預算。每個 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 天) 排名波動,這是正常的。到第三週,排名已經穩定並趨於上升。到月底,自然流量上升 34%,該診所的主要關鍵字平均改進了 4 個位置。Core Web Vitals 改進是最大的因素——Google 一直在因舊網站的移動性能不佳而在搜索結果中處罰它。