Travel Diary
旅の生の素材を、スクロールに合わせて語るウェブサイトに変換します:固定された衛星地図上に1日1枚のカードを表示、移動セグメント(キャンピングカー、車、自転車、徒歩、フェリー、ハウスボート)を地図上に描画、写真と動画を撮影位置にピン留め、スポット案内(「Unterwegs」/「沿道の見どころ」)にWikimedia Commonsの画像を追加、そして1日ごとのリプレイで3Dルート飛行と統計情報、標高プロファイル、撮影地点に現れる写真を提供します。
template/ 内のテンプレートは Vite + TypeScript + MapLibre プロジェクトです(フレームワークなし、APIキー不要)。
ユーザーがコードに触れる必要は一切ありません。ローカルセットアップ用Webアプリが言語、旅行データ、日記テキスト、ファイルをドラッグ&ドロップで収集し、それ以外はビルドスクリプトで処理します。
どのモード?
| ユーザーの発言 | モード | 手順へ |
|---|---|---|
| 「新しい旅行記」/「旅行サイトをセットアップ」/プロジェクト未作成 | init | §1 |
| 「新しい写真/GPX/Timeline/日記テキスト」/「N日目を追加」/プロジェクトあり | day | §2 |
| 「デプロイ」/「公開」/「単一ファイルを作成」/「オンラインに上げる」 | deploy | §3 |
プロジェクトが traveldiary プロジェクトであるかどうかは、data/trip.json と scripts/build-timeline.mjs が存在するかで判断します。
1. init – 新規プロジェクトの足場を作る
- メッセージから(または質問して)2つだけを尋ねます:ターゲットフォルダと、セットアップの質問にブラウザアプリで答えるか(デフォルト、より親切)チャットで答えるかのどちらかを選んでもらいます。それ以外はアプリが尋ねます。
node <skill-dir>/scripts/init.mjs <target-folder>を実行して足場を作ります。template/をコピーし、npm installを実行し、次のコマンドを表示します。- プロジェクト内で
npm run setupを実行してセットアップアプリを起動し(ポート5180)、ユーザーに http://localhost:5180 を開くよう伝えます。ブラウザペインが使用可能であれば、そのURLでpreview_startを使用します。アプリは以下の流れでユーザーを案内します:言語(de/en)→ タイトル、サブタイトル、日付、タイムゾーン、移動手段、出力タイプ、アクセントカラー → 1日1エントリ(日付、タイトル、Markdown形式の日記テキスト)→ 写真、動画、GPX、Google Timeline のドロップゾーン。これによりdata/trip.json、content/tagebuch.md、raw/フォルダが作成されます。アプリはいつでも再開できます。 - ユーザーが「完了」「fertig」と言ったり、素材を貼り付けて戻ってきたら、day モードに進みます。
ユーザーが代わりにチャットで回答する場合は、自身で data/trip.json(スキーマは references/data-formats.md を参照)と日記を content/tagebuch.md(## Tag N – <weekday, date> – <title> / ## 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内で、1日ごとに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で誤検出された種類を修正します(SKIING が実際は e-bike →ebike、友人の車 →car)。placesに停車場所を追加して、停車に「Pause」ではなく名前が表示されるようにします。 - ビルド:
npm run data(コンテンツ → トラック → タイムライン → POI → 写真)。公開ルーティング/標高/Commons サーバーはレート制限があります。スクリプトは一時停止とキャッシュを行い、ループはしません。 - 写真を確認する:新しい写真のコンタクトシートを作成し(スクリプトはリファレンスにあります)、読み取って、各写真に1文のキャプションを
data/captions.jsonに書き込みます。写真の位置(各写真の横に表示)から場所や山の名前が特定できる場合は名前を記入します。「Ortler group」のように山頂を推測するのではなく記述します。ぼやけた写真や誤ったショットはdata/exclude.jsonに入れます。 - スポット案内(POI):ユーザーが通過したが自分では良い写真がない注目スポット(トンネル、有名な湖、城など)については、2~3文の事実とCommonsの検索語を
data/pois.jsonに追加します。npm run data:poisで自由ライセンスの画像と帰属情報を取得します。選ばれた画像をコンタクトシートで確認し、最初の候補が良くない場合(彫刻、地図など)はより良いfileを指定します。 - 検証:
npm run devで開き、新しい日を確認します。線、ピン、キャプションをチェックし、リプレイを1回再生します。 - デプロイ(§3)し、プロジェクトがgitリポジトリの場合はコミットします。
プロジェクト内の CLAUDE.md を最新に保ってください(次回セッションへの引継ぎ文書です)。
3. deploy
trip.json → output にユーザーが選択した出力タイプが指定されています。詳細と正確なコマンドは references/hosting.md にあります。
- single:
npm run build:single→ プロジェクトと同じ場所に、データ、写真、動画を埋め込んだ単一HTMLファイルが生成されます(大きな動画はメモ付きで除外されます)。ユーザーへの注意:一部のスマートフォンではファイルシステムから開いたファイルで地図のWeb Workerが動作しないため、ホスティングの方が信頼性が高いです。 - web:
npm run deploy:web→ ビルド、.htaccess+.htpasswd(Basic認証)の生成、SSH経由で変更ファイルをアップロード(tarパイプ、ハッシュマニフェストによる差分アップロード)。.env.webが必要です(host、user、dir、logins)。 - nas:
npm run deploy→ tarパイプで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枚)を1枚のカードにまとめます(モバイルでは変わりません)。
- 高速道路トンネル上の標高プロファイルはその上の地形を示します。そのため、標高増加は自転車/徒歩のみで計算されます。
- すべてのUIテキストは
src/i18n.tsにあります(de, en)。言語を追加するには辞書を一つ増やすだけです。