Community程式設計與開發github.com

ethanplusai/astro-轉換套件

將網站擷取凍結為基準線,並驗證 Astro 建置與之完全匹配——包括每個路由、重新導向(透過主機模擬的一次跳轉)、SEO 標頭欄位、可見文字、內部連結、媒體檔案、Sitemap 項目、Feed、表單、第三方腳本和安全標頭——並將核准的差異記錄在 exceptions.json 中,將改進項目記錄在 proposals.json 中。

astro-轉換套件 是什麼?

**ethanplusai/astro-conversion-kit** 是一個 AI 代理技能(適用於 Claude Code、Cursor、Codex),旨在確保 Astro 網站遷移或重新建置後與原始網站在功能上完全等同。它建立一個離線「基準線」(baseline),從 `capture/` 資料夾中的內容快照生成,然後針對每個 Astro 建置執行一系列嚴格的「關卡」(gates)——共計十個(路由、SEO、重新導向、媒體、表單、腳本、標頭、Sitemap、連結和文字)。這些關卡會比較建置輸出與基準線,驗證每個路由是否正確建置、SEO 標頭是否相符、內部連結是否解析、重新導向是否有效且僅為一次跳轉,以及可見文字是否完全一致。該工具強制執行一條「黃金法則」:預設建置必須與即時網站完全匹配,且關卡絕不因標誌而變寬鬆。差異必須記錄在 `exceptions.json` 中(經過核准),而改進項目則記錄在 `proposals.json` 中(需透過 `PROPOSALS=on` 啟用)。該套件支援 Vercel 和 Cloudflare 的重新導向編譯,並提供用於暫存、預覽和正式環境部署的驗證腳本。它旨在將主機從舊平台(如 WordPress)遷移到 Astro 時,提供可靠的回歸測試;關卡僅讀取基準線,從不讀取即時網站,因此即使舊主機已下線,建置仍可被驗證,而無需存取原網站。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/ethanplusai/astro-conversion-kit/tree/HEAD/skills/parity-gates

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

parity-gates

從 capture/ 建立基準線一次,然後在每次建置時執行關卡,直到所有關卡都通過。 關卡僅讀取 baseline/,從不讀取即時網站,因此即使舊主機已移除,建置仍可被驗證。

黃金法則

預設建置等於即時網站,且關卡絕不軟化。 沒有旗標能將失敗轉為警告。由此衍生出另外四條:

  1. 絕不手動編輯 baseline/。 唯一的例外:baseline/scripts.json 中的 keep,用於決定是否移除某個廠商(設定為 false,並記錄此決定)。
  2. 差異是條目,而非編輯。 不可避免的差異:exceptions.json。改進項目:proposals.json,僅在 PROPOSALS=on 時啟用。兩者都在 references/exceptions.md 中。
  3. 跳過不等於通過。 無法檢查某項的關卡會在其摘要行中顯示 N skipped (reason)。報告每個跳過項目。
  4. 錯誤的關卡應作為套件錯誤回報,絕不修改網站中的關卡,也不修改基準線。

執行腳本

由 convert-site 建立的網站會在 scripts/ 中放置腳本;從網站根目錄執行以下 npm 腳本,選項放在 -- 之後。在非範本化網站外部,從網站根目錄執行每個步驟下方顯示的 node 形式,其中 <skill-dir> 是在已執行 npm install 的套件副本中該技能資料夾的絕對路徑。每個腳本都會列印 --help;請執行它而非閱讀原始碼。退出碼 0 為通過,1 為失敗的關卡或漂移,2 為使用方式錯誤或缺少輸入。

1. 基準線(僅一次)

npm run baseline
node <skill-dir>/scripts/build-baseline.mjs --capture capture --out baseline    # 備用

它需要 capture/inventory.json、media.json(來自 capture 的 media.mjs)和 templates.json (templates.mjs),如果缺少其中一個,則會退出碼 2 並命名需執行的步驟。它會寫入 baseline/{routes,seo,redirects,media,forms,scripts,meta,counts}.json 和 baseline/text/,以及 網站根目錄的 redirects.csv。沒有目標的短連結會被省略並命名在 stderr 上。 捕獲鏈中的每個中間跳轉都會獲得一個直接指向最終目標的單獨行 (/old-services → /old-services/ → /services/ 也會產生 /old-services/,/services/,請注意 hop of /old-services),除非該跳轉本身是已建置的路由,因此指向該鏈中任何 URL 的連結都只需一次跳轉。 一起提交 baseline/ 和 redirects.csv。--check 會根據 counts.json 重新計數 baseline/(漂移則退出碼 1)。每個檔案的格式在 references/contracts.md 中。

2. 重新導向

redirects.csv(from,to,status,source,note)是網站重新導向的單一來源。 source 是來自 capture 的 crawl、sitemap、shortlink 或 seed;您新增的一行是 decision,其 note 命名決策 ID。絕不手動編輯編譯後的輸出;編譯方式:

npm run redirects:build
node <skill-dir>/scripts/build-redirects.mjs --csv redirects.csv --host vercel --out vercel.json --trailing-slash always    # 備用

--host cloudflare --out public/_redirects 用於 Pages(Astro 會將其複製到 dist/ 中)。Vercel: redirects 鍵會被取代,所有其他鍵保留,並且 trailingSlash 會被移除,並寫入編譯器自己位於網站規則之後的 308 斜線規則,因此未帶斜線的來源仍然只需一次跳轉。 只有以靜態檔案副檔名結尾的路徑才會被這些規則視為檔案,且不區分大小寫: 網頁類型、文件、媒體和歸檔類型(docx、xlsx、 csv、mov、wav、heic、gz、...),以及 dist/(否則為 public/)中找到的每個副檔名,因此請在 建置後重新執行;/upgrade-guide/3.5/ 是一個頁面,並保留其斜線。規則仍會重新導向的已建置檔案會使重新導向關卡失敗,顯示為 built file redirected。 Cloudflare:查詢行(/?p=7)無法由 _redirects 匹配,並會進入 cloudflare-query-redirects.csv,需要建立為單一重新導向(一個「需要您處理」的項目)。一個 目標是其自身路徑的查詢行(/?p=2 到 /)是無操作的,並且在兩個主機上都會被省略。

捕獲的行(任何 source 但不是 decision)是即時 URL 且不包含參數:對於 Vercel, 其中的每個 : 和 * 都會被跳脫(/foo:bar/ 被寫為 /foo\:bar/, /trackshttps://www.example.com/x/ 也是如此,這是捕獲所跟隨的損壞即時 href);// 則保留。 只有 decision 行使用 :name 參數和 * splat,即使在這種情況下,數字前的 :(連接埠)也會被跳脫。Vercel 拒絕裸露的 :,關卡的模擬也是如此。 沒有有效格式的來源(沒有前導 /、空白字元、控制字元;在 Cloudflare 上還有捕獲的 :<name> 或 *,_redirects 無法跳脫)會被丟棄,在 stderr 上命名,並在 redirects-skipped.json 中列出為 { source, reason }。該檔案位於 redirects.csv 旁邊(網站根目錄),絕不在 public/ 下,因此不會被部署。重新導向關卡和 verify-live 將列出的行計為跳過,絕不計為通過。當路徑根本不應該有重新導向時,請改為記錄一個「無重新導向」例外(第 4 節):{ "kind": "redirect", "path": "<source>", "reason": "...", "action": "none", "approvedBy": "...", "date": "..." }。

3. 驗證

npm run build
npm run verify -- --endpoint https://forms.example.com/f/abc --thank-you /thank-you/
node <skill-dir>/scripts/verify/run-all.mjs --endpoint https://forms.example.com/f/abc --thank-you /thank-you/    # 備用

run-all 按字母順序執行十個關卡,僅為每個關卡提供它接受的選項, 並在第一個失敗時停止。共用選項:--paths(逗號分隔清單,* 匹配任何內容)、 --json、--origin(連結、SEO、Sitemap:建置所針對的主機)、--allow-extra(路由)、 --endpoint、--honeypot、--thank-you(表單;當基準線中有 POST 表單時,--endpoint 為必要)、--host、--config(重新導向、連結)、--csv(重新導向)、--media-plan(媒體)。修復第一個失敗, 重建,重新執行。單獨一個關卡:node <skill-dir>/scripts/verify/<gate>.mjs。

關卡通過條件跳過表示
forms每個即時表單都存在於其頁面上,且欄位名稱相同、順序一致、方法相同;POST 表單的 action 是 --endpoint,並帶有 --honeypot;GET 表單(搜尋框)保留即時的 action 路徑,不需要這兩者(「比較了 N 個搜尋/GET 表單」);即時 action 位於另一個可註冊網域(電子報列表主機;www、http、子網域和 WordPress 處理程式,例如 admin-ajax.php 或 ?wpcf7 皆視為網站)的 POST 表單保持不變,透過其完整 action URL 像 GET 表單一樣進行比較,且不需要 --endpoint(「保留了 N 個表單(發布到 )」)無 --thank-you:未檢查 POST 表單的感謝頁面
headers主機設定在每個路徑上發送 nosniff、Referrer-Policy、X-Frame-Options 或 CSP frame-ancestors,並且當不可索引時,在每個路徑上發送 X-Robots-Tag: noindex 或(Vercel)在每個建置頁面上的 meta robots noindex;預覽主機規則(https://*.pages.dev/*)僅適用於預覽主機;使用 PUBLIC_INDEXABLE=true 時,禁止在每個路徑上使用 noindex
links每個內部 href 和 src 解析為已建置的頁面或檔案、重新導向來源或基準線媒體,或透過編譯後的規則(vercel.json 或 dist/_redirects:斜線規則和每個 redirects.csv 行)一次跳轉即可到達已建置的頁面,如同即時重新導向一樣(「透過重新導向解析了 N 個連結」);兩次跳轉或缺少目標則失敗;沒有主機設定時,/about(建置提供 /about/)失敗
media每個基準線媒體檔案都由建置以相同的位元組提供(--paths 透過路徑或引用它的頁面來選擇檔案):在計劃模式 repo 的 dist/ 中;在計畫的 prefix 下,儲存於 store manifest(store)或仍在即時網站上(live-temporary);在前綴之外,每種模式都在 dist/ 中。使用 PUBLIC_INDEXABLE=true 時,live-temporary 會使前綴下的每個檔案失敗(正式環境建置不得從即時網站提供媒體;沒有前綴的計劃涵蓋每個檔案),並且仍會檢查 dist/ 中前綴外的檔案在暫存建置上的計劃模式 live-temporary:前綴下的檔案從即時網站提供,不進行檢查
redirects每個基準線重新導向和 csv 行在一次跳轉中回答,且狀態碼相同,並且目標在 dist/ 中回答 200(或是外部的,或是在基準線 meta.json excluded 中的前綴下:則僅檢查第一次跳轉);沒有來源同時也是已建置的檔案;沒有已建置的頁面或檔案被重新導向其自身 URL 之外(built page redirected by rule <rule>;沒有例外涵蓋它,修復規則);具有「無重新導向」例外(kind: "redirect",action: "none")的路徑根本不會被重新導向無操作的查詢行、Cloudflare 上的任何查詢行,或 redirects-skipped.json 列出原因(not compiled)的無有效格式來源
routes每個頁面、文章、歸檔和 feed 在 200 狀態碼下建置,noindex 路由仍表示 noindex,沒有建置多餘的項目(捕獲在 baseline/js.json 中的自己的腳本和 baseline/css.json 中的樣式表,在其即時路徑上;即時 sitemap 名稱在 baseline/sitemaps.json 中,以及啟動圖示集都不是多餘的);以非 200、3xx、404 或 410 狀態碼捕獲的路由會失敗,顯示為 not captured: <status>,除非 routes 例外跳過它或命名其建置的替代方案帶有 to: "skip" 的 routes 例外:該路由從未被捕獲
scripts每個保留的廠商腳本正好存在於其即時頁面上,且 ID 相同;已移除的廠商腳本不存在於任何頁面上;沒有新的廠商腳本
seo每個頁面的 Title、Description、Canonical、Robots、Lang、H1、H2、og 和 JSON-LD @types 相等;網站 URL 位於網站的來源上。除非 PUBLIC_INDEXABLE=true,否則 robots 必須攜帶暫存用的 noindex, nofollow,而其餘部分在這些兩個標籤之後與即時網站相同;正式環境建置則完全比較 robots
sitemapsdist/ 中的每個頂層 Sitemap(Astro 的 sitemap-index.xml,或 baseline/sitemaps.json 中的即時名稱,例如 wp-sitemap.xml 或 sitemap_index.xml)列出來源上完全相同的可索引 200 頁面(百分比跳脫比較不區分大小寫:%c3 等同於 %C3);robots.txt 中的每個 Sitemap: 行位於來源上,並命名 dist/ 中的一個檔案,或者該行是即時 robots.txt(capture/robots.txt)逐字攜帶的;每個 Feed 都建置了與即時相同數量的項目
text每個頁面的可見文字等於 baseline/text/(字詞差異比較,5 個字詞的上下文)

使用 --exclude 進行的捕獲會將其路徑前綴記錄在 baseline/meta.json 的 excluded 中:links 關卡不檢查位於其下的連結(就像連結到其他主機一樣,註記為「未檢查排除路徑下的 N 個連結」),而 sitemaps 關卡在即時 robots.txt 逐字攜帶該行時,接受位於其下的 robots.txt Sitemap: 行(同一主機上的多站點子站點的 Sitemap)。

4. 差異與決策

當建置無法或不應與即時網站匹配時,請閱讀 references/exceptions.md。簡而言之:一個條目是 { path, field, from, to, reason, approvedBy, date };from: "" 記錄建置新增的值, to: "" 記錄建置移除的值;不再匹配的例外,或命名關卡不檢查的路徑,會使關卡失敗。即時網站上的每個異常(缺少 H1、失效的標籤、 損壞的連結)預設都會被重現,並會獲得一個決策行(id、topic、choice、default、 reason、cost if wrong)來說明這一點以及修復方法。

一個記錄具有 kind 而非 field:{ "kind": "redirect", "path": "<source>", "reason": "...", "action": "none", "approvedBy": "...", "date": "..." } 表示「此路徑沒有重新導向,是有意為之」(為損壞的 href 記錄的即時重新導向,不應重新導向任何內容)。每個鍵都是必需的:它移除了即時行為,因此像任何例外一樣需要簽核。重新導向關卡會請求該路徑,並且僅在規則未重新導向它時才通過;在關卡不檢查的路徑上,它會失敗,顯示為 path not checked;verify-live 會跳過它並附上原因。所有其他關卡都會忽略它。

5. 暫存、提案與正式環境建置

PUBLIC_INDEXABLE 和 PROPOSALS 會改變 Astro 的建置內容,因此請在建置上設定它們,而不僅僅是在關卡執行時;在沒有它們的情況下進行的建置上執行關卡,會檢查錯誤的網站。僅在建置本身是為該主機製作時才傳遞 --origin;範本化建置的 site 是即時來源,因此其 Canonical 和 Sitemap 會保留在該來源上。

npm run build && npm run verify -- --endpoint ... --thank-you ...                                       # 暫存
PROPOSALS=on npm run build && npm run verify:proposals -- --endpoint ... --thank-you ...                 # 提案
PUBLIC_INDEXABLE=true npm run build && npm run verify:release -- --endpoint ... --thank-you ...          # 正式環境

暫存部署後,透過 HTTP 根據基準線檢查它。正式環境部署的檢查方式相同,但不需要 --expect-noindex:

npm run verify:live -- --base https://my-site.vercel.app --expect-noindex
node <skill-dir>/scripts/verify-live.mjs --base https://my-site.vercel.app --expect-noindex    # 備用

--bypass "$VERCEL_AUTOMATION_BYPASS_SECRET" 僅在暫存被刻意保護時適用(保密值來自環境,絕不在聊天中貼上);公開的暫存別名則不需要。

它會檢查每個基準線路由是否為 200(或 --sample)、每個重新導向是否在一次跳轉中且具有相同類型的狀態碼、頁面是否具有 noindex(當且僅當設定了 --expect-noindex)、Sitemap,以及 20 個媒體檔案的位元組(或 --media-manifest,其 url 可以是 store 的絕對 URL 或在 <base><path> 檢查的網站路徑)。redirects-skipped.json 中列出的重新導向或被「無重新導向」例外(--skipped、--exceptions;兩者預設都從網站根目錄讀取)涵蓋的重新導向會被跳過,並以其原因命名。每個請求在 30 秒後超時,這是該檢查的失敗而不是封鎖。退出碼 3 表示它被封鎖:請等待並重新執行。退出碼 3 並帶有 deployment protection: 表示 Vercel 以其登入重新導向(302 到 vercel.com/sso-api)回應:請使用專案的正式環境別名(預設為公開)而非原始部署 URL;僅當暫存被刻意保護時才需要保密。”

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

ethanplusai/astro-conversion-kit

Crawl a live website, read-only and paced, into a capture/ folder that a rebuild is checked against — every page's HTML, text and head tags, redirects with every hop, links, third-party scripts, the media set, stylesheets, fonts, logo and icons, feeds, templates, and live screenshots at three widths. Use before converting or rebuilding a site, when asked to crawl, capture, snapshot or inventory a site, or when a capture stopped on blocks and needs resuming.

ethanplusai/astro-conversion-kit

Convert a live website (WordPress first; Drupal, Webflow, Squarespace, Wix and static sites too) into a static Astro site with the same URLs, content, head tags, media, redirects and look, proven by parity gates and a pixel-level visual review, ending in one pull request, a noindexed staging deploy and a launch runbook. Use when asked to convert, rebuild, migrate or clone a site to Astro, when handed a site URL with this kit's link, to resume a conversion from .conversion/state.json, or with --apply <id> to apply one suggestion as a proposal.

ethanplusai/astro-conversion-kit

Audit a live or staging website and report what would go wrong at launch — crawl and inventory, indexability, redirects for a domain cutover, links, images, forms, accessibility, performance, analytics, content sanity, and full-page screenshots for a visual pass. Use before or right after a site launch, when asked to QA, audit, or review a website, when a site is moving to a new domain, or when somebody asks whether a site is ready to go live. Read-only: it never submits a form, clicks a control, or edits anything.

ethanplusai/astro-conversion-kit

The moment DNS moves and for the thirty days after — verifies the cutover (DNS propagation, certificate, http and www redirects, the noindex, robots and sitemap on the live host, every redirect the audit mapped, forms, analytics, the staging copy, the old host, security headers), diffs production against the pre-launch baseline, and schedules the watch. Use when asked did the launch work, is the site live, what should I check after launch, the domain just switched, or when a site went live in the last month and something looks wrong. It is read-only and exits 0 whatever it finds.

相關技能