Jakeuj's Notes Help

Writerside Sitemap 與 SEO 修正筆記

Writerside 部署到 GitHub Pages 並使用 custom domain 時,sitemap、OG URL 與 Schema URL 要和實際公開頁面路徑一致;如果站台實際頁面在根目錄,就要讓 sitemap 產出 https://jakeuj.com/<topic>.html ,並在 Search Console 提交 https://jakeuj.com/sitemap.xml

問題症狀

這次遇到的狀況是:

  • Google Search Console 要求提供 sitemap。

  • 線上 https://jakeuj.com/robots.txt 原本是 404。

  • 線上 https://jakeuj.com/sitemap.xml 回傳 200,但裡面的 URL 是舊路徑。

  • sitemap 的 <loc> 指向 https://jakeuj.com/writerside/master/*.html

  • 實際公開頁面在 https://jakeuj.com/*.html ,所以舊路徑會 404。

例如:

https://jakeuj.com/writerside/master/a-second-operation-started-on-this-context.html

會回傳 404,而真正可用的 URL 是:

https://jakeuj.com/a-second-operation-started-on-this-context.html

這種狀況會讓 Search Console 看到 sitemap 內有大量不存在頁面,也會讓 OG metadata、Schema URL 和實際 canonical URL 不一致。

先確認正式 URL 策略

這個站台的正式 URL 策略是根目錄短網址:

  • 首頁: https://jakeuj.com/

  • 文章: https://jakeuj.com/<topic-web-file-name>.html

  • Sitemap: https://jakeuj.com/sitemap.xml

  • robots.txt: https://jakeuj.com/robots.txt

不把 /writerside/master/ 視為正式公開路徑。

所以 Writerside 設定應維持這個方向:

<instance src="hi.tree"/>

不要重新加回:

<instance src="hi.tree" web-path="writerside" version="master"/>

否則 Writerside metadata 和 sitemap 會傾向產生 /writerside/master/ 前綴。

Writerside 的 sitemap 設定

Writerside 預設不一定會產生 sitemap,需要在 buildprofiles.xml 保留 <sitemap> 設定。

目前重點設定如下:

<buildprofiles> <variables> <web-root>https://jakeuj.com/</web-root> <generate-sitemap-url-prefix>https://jakeuj.com/</generate-sitemap-url-prefix> </variables> <build-profile instance="hi"> <sitemap priority="1" change-frequency="weekly" /> <variables> <product-web-url>https://jakeuj.com/</product-web-url> <noindex-content>false</noindex-content> </variables> </build-profile> </buildprofiles>

這幾個設定的分工是:

設定

用途

web-root

影響站台 metadata,例如 OG / Schema 相關 URL

generate-sitemap-url-prefix

影響 sitemap <loc> 的 URL prefix

sitemap

啟用 sitemap 產生,並設定 priority / change frequency

product-web-url

站台產品或文件根 URL

noindex-content

是否要求搜尋引擎不要索引內容

這次沒有啟用 generate-canonicals ,因為 Writerside 產生的 canonical 會指向設定的 web root;沒有先抽測輸出前,不要為了修 sitemap 就貿然開啟。

真正的根本原因

一開始看起來像是 Writerside sitemap 設定錯誤,但檢查 build artifact 後發現不是這樣。

實際狀況是:

  • repo 內的 writerside.cfgbuildprofiles.xml 已經能產生正確 root URL。

  • GitHub Actions 的 build artifact 裡, sitemap.xml 已經是 https://jakeuj.com/*.html

  • 線上 GitHub Pages 還停在舊 artifact。

  • 原因是 deploy job 在複製 robots.txtCNAME 時失敗,Pages artifact 沒有被重新上傳。

失敗點是 deploy job 只有下載 Writerside build artifact,沒有 checkout repo,因此工作目錄裡沒有 repo root 的 robots.txtCNAME

錯誤會像這樣:

cp: cannot stat 'robots.txt': No such file or directory

這代表要修的是 GitHub Actions deploy job,不是再去改 Writerside 的 URL prefix。

修正 deploy workflow

deploy job 需要在下載 artifact 前 checkout repo,讓 repo root 的 metadata 檔案存在。

deploy: needs: [build, test] runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 1 - name: Download artifact uses: actions/download-artifact@v4 with: name: docs - name: Unzip artifact run: unzip -O UTF-8 -qq "${{ env.ARTIFACT }}" -d dir - name: Add root site metadata run: | cp robots.txt dir/robots.txt cp CNAME dir/CNAME

然後在 upload Pages artifact 前加上 guard,避免錯誤 sitemap 再次部署出去。

- name: Validate Pages artifact SEO metadata run: | test -f dir/sitemap.xml test -f dir/robots.txt test -f dir/CNAME if grep -q "/writerside/master/" dir/sitemap.xml; then echo "::error file=dir/sitemap.xml::sitemap.xml still contains /writerside/master/ URLs" exit 1 fi if ! grep -q "<loc>https://jakeuj.com/" dir/sitemap.xml; then echo "::error file=dir/sitemap.xml::sitemap.xml does not contain root jakeuj.com URLs" exit 1 fi if ! grep -q "Sitemap: https://jakeuj.com/sitemap.xml" dir/robots.txt; then echo "::error file=dir/robots.txt::robots.txt is missing the sitemap directive" exit 1 fi

這樣如果 Writerside 設定或 deploy artifact 又產生錯誤 URL,CI 會在部署前停下來。

robots.txt

repo root 的 robots.txt 內容保持簡單即可:

User-agent: * Allow: / Sitemap: https://jakeuj.com/sitemap.xml

重點不是 robots.txt 本身很複雜,而是 GitHub Pages artifact 來自 Writerside build zip,不會自動包含 repo root 的一般檔案。

所以 deploy workflow 必須把 robots.txt 複製到 Pages artifact 根目錄。

sitemap.xml 與 sitemap-index.xml

目前站台只有數百篇文章,使用單一 sitemap 就夠了。

Search Console 應提交:

https://jakeuj.com/sitemap.xml

目前不需要提交:

https://jakeuj.com/sitemap-index.xml

sitemap-index.xml 回傳 404 是預期狀態,不是錯誤。

只有符合下列任一條件時,才需要改用 sitemap index:

  • 單一 sitemap 超過 50,000 URLs。

  • 單一 sitemap 未壓縮超過 50MB。

  • 明確要拆成多個 sitemap,例如文章、圖片、文件版本分開提交。

如果未來改用 sitemap index, robots.txt 和 Search Console 都要一起改指向 index;否則就維持 sitemap.xml

驗證指令

部署後先看根目錄 metadata:

curl -I https://jakeuj.com/robots.txt curl -I https://jakeuj.com/sitemap.xml curl -I https://jakeuj.com/sitemap-index.xml

預期結果:

  • robots.txt 回傳 200。

  • sitemap.xml 回傳 200。

  • sitemap-index.xml 回傳 404。

確認 sitemap 沒有舊 prefix:

curl -L https://jakeuj.com/sitemap.xml | grep -o '/writerside/master/' | head

正常情況下不應輸出任何內容。

抽測 sitemap URL:

curl -L -s -o /dev/null -w '%{http_code}\n' https://jakeuj.com/a-second-operation-started-on-this-context.html curl -L -s -o /dev/null -w '%{http_code}\n' https://jakeuj.com/abp.html curl -L -s -o /dev/null -w '%{http_code}\n' https://jakeuj.com/macos-mdns-ssh-hostname-resolution.html

這些根目錄文章 URL 應回傳 200。

如果要檢查 HTML head,可以抽 og:url 和 Schema url

curl -L -s https://jakeuj.com/default.html | rg 'og:url|"url"|/writerside/master'

og:url 和 Schema url 應該使用 https://jakeuj.com/default.html 這類根目錄 URL。

排查順序

以後遇到 sitemap 或 SEO URL 指錯時,先照這個順序判斷:

  1. 確認正式 URL 策略是 root path 還是子路徑。

  2. 檢查線上 sitemap.xmllast-modified ,判斷是不是舊 artifact。

  3. 檢查最新 GitHub Actions run 是否成功到 deploy。

  4. 下載或解開 build artifact,確認 artifact 內的 sitemap.xml 是否正確。

  5. 如果 artifact 正確但線上錯,修 deploy workflow。

  6. 如果 artifact 本身錯,再回頭修 writerside.cfgbuildprofiles.xml

  7. 最後再到 Search Console 重新提交 sitemap 並做 URL Inspection live test。

關鍵是不要只看到線上 sitemap 錯,就立刻改 Writerside 設定;先分清楚「建置輸出錯」還是「部署沒有成功更新」。

參考資料

10 June 2026