旅行日記
將旅行的原始素材轉化為一個捲動敘事網站:每一天一個卡片,顯示在固定的衛星地圖上, 移動區段(露營車、汽車、自行車、步行、渡輪、船屋)繪製在地圖上,照片和影片釘選在它們的 位置,資訊點(「沿路」)附有維基共享資源圖片,以及每日的回放功能, 以 3D 方式飛越路線,顯示統計數據、海拔剖面圖,並在拍攝位置彈出照片。
template/ 中的範本是一個 Vite + TypeScript + MapLibre 專案(無框架,無 API 金鑰)。
使用者無需碰觸程式碼:本機設定網頁應用程式透過拖放收集語言、行程資料、每日文字和
檔案;其餘部分由建置腳本處理。
哪種模式?
| 使用者說 | 模式 | 前往 |
|---|---|---|
| 「新的旅行日記」、「建立行程網站」,尚無專案 | init | §1 |
| 「新的照片 / GPX / 時間軸 / 日記文字」、「加入第 N 天」,專案已存在 | day | §2 |
| 「部署」、「發布」、「製作單一檔案」、「上線」 | deploy | §3 |
當一個專案包含 data/trip.json 和 scripts/build-timeline.mjs 時,即為 traveldiary 專案。
1. init – 建立新專案
- 詢問(或從訊息中取得)兩件事:目標資料夾以及使用者偏好在瀏覽器應用程式中(預設,較友善)還是在聊天中回答設定問題。其他事項由應用程式詢問。
- 執行建立腳本:
node <skill-dir>/scripts/init.mjs <target-folder>。它會複製template/,執行npm install,並列印下一條指令。 - 啟動設定應用程式:在專案內執行
npm run setup(連接埠 5180),並告訴使用者開啟 http://localhost:5180。如果瀏覽器面板可用,請使用該 URL 搭配preview_start。該應用程式會引導使用者完成:語言(de/en)→ 標題、副標題、日期、時區、交通工具、輸出類型、強調色 → 每天一個條目(日期、標題、Markdown 格式的日記文字)→ 照片、影片、GPX、Google Timeline 的拖放區域。它會寫入data/trip.json、content/tagebuch.md和raw/資料夾。他們可以隨時重新開啟。 - 當他們回來(說「完成了」、「fertig」,或只是貼上素材)時,繼續進行 day。
如果使用者改為在聊天中回答,請自行撰寫 data/trip.json(結構定義在 references/data-formats.md 中)並將日記寫入 content/tagebuch.md(## 第 N 天 – <星期, 日期> – <標題> / ## Day N – …)。
2. day – 處理新素材
在會話中第一次執行前,請閱讀 references/day-workflow.md;其中有確切的順序、慣用做法和陷阱。簡短版本:
- 盤點
raw/下有哪些新檔案(使用find raw -newer public/data/photos.json),以及日記中是否有新的一天。如果有 Claude Docs 連接器和文件連結可用,請將文件匯出為 Markdown 到content/tagebuch.md;否則由設定應用程式/使用者維護該檔案。 - 結構化 到
data/trip.json中:每天一個days[]條目(n、date、title、GPX 的tracks[]、空拍影片剪輯的video、無時間軸時的legs[])。將 GPX 檔案重新命名為YYYY-MM-DD_slug.gpx。 - 時間軸標籤:執行
npm run data:timeline,讀取主控台中的區段列表,並在trip.json → timeline.labels中為每個區段提供人類可讀的標籤(鍵 = 本地開始時間YYYY-MM-DDTHH:MM)。修正timeline.kinds中誤判的類型(例如 e-bike 被標為 SKIING →ebike,朋友的車 →car)。在places中新增停留地點,以便停留點顯示名稱而非「暫停」。 - 建置:
npm run data(內容 → 軌跡 → 時間軸 → 景點 → 照片)。公共路線/海拔/Commons 伺服器有速率限制;腳本會暫停並快取,絕不迴圈請求。 - 檢視照片:為新照片建立縮圖索引(參考文件中的腳本),閱讀它們,並為每張照片在
data/captions.json中寫入一句簡短的描述。當照片的位置(印在每張照片旁)可識別時,說出地名和山名;說「奧特勒山組」而非猜測某個山峰。將模糊或意外拍攝的照片放入data/exclude.json。 - 景點:對於使用者經過但沒有自己好照片的著名地點(隧道、知名湖泊、城堡),在
data/pois.json中新增條目,包含 2–3 句事實性描述和一個 Commons 搜尋詞;npm run data:pois會取得一張自由授權的圖片並附上來源資訊。在縮圖索引上檢查選取的圖片,如果第一個結果不佳(版畫、地圖),則指定一個更好的file。 - 驗證:使用
npm run dev,開啟新的一天,檢查路線、圖釘、說明文字,並播放一次回放。 - 部署(§3),如果專案是 git 儲存庫,則提交變更。
保持專案中的 CLAUDE.md 為最新(它是下一次會話的交接文件)。
3. deploy
trip.json → output 表示使用者的選擇;詳細資訊和確切指令在 references/hosting.md 中。
- 單一檔案:
npm run build:single→ 在專案旁產生一個 HTML 檔案,內嵌資料、照片和影片(大的自有影片會被排除並附上說明)。注意:在某些手機上,從檔案系統開啟的檔案會封鎖地圖的網頁工作者;託管更可靠。 - 網站:
npm run deploy:web→ 建置、產生.htaccess+.htpasswd(基本驗證)並透過 SSH 上傳變更的檔案(tar pipe,透過雜湊清單增量更新)。需要.env.web(主機、使用者、目錄、登入資訊)。 - NAS:
npm run deploy→ tar pipe 到 Synology nginx 容器;配置在nas/default.conf。
值得了解的事項
- 照片需要 EXIF 時間 + GPS(手機兩者都提供)。影片從檔案名稱取得時間(
PXL_YYYYMMDD_HHMMSS),並從時間軸、GPX、停留點或最近的照片取得位置。 - GPX 優先於時間軸:與 GPX 軌跡重疊的時間軸活動會被丟棄。
- 沒有 Google Timeline 時,駕駛路線會透過
days[].legs在已命名地點之間規劃路線。 - 船屋行程:類型
boat會沿著 OSM 河流/運河規劃路線(scripts/waterway.mjs,可選的timeline.waterways白名單),並使用照片 EXIF 位置作為航點 – 請參閱references/day-workflow.md。 - 桌面版(≥ 900 px):地圖左 50 %,故事右 50 % 並附有大照片網格;回放會在右側顯示照片卡片,並將 15 分鐘內拍攝的照片分組(最多 6 張)到一張卡片上(手機版不變)。
- 經過高速公路隧道的海拔剖面圖顯示的是上方地形;這就是為什麼海拔增加僅針對自行車/步行計算。
- 所有 UI 文字都在
src/i18n.ts(de, en)中;新增一個語言只需要新增一個字典。