[{"data":1,"prerenderedAt":660},["ShallowReactive",2],{"content-/2026-05-17-diary":3,"all-pages-for-dir":658,"og-image-/2026-05-17-diary":659},{"id":4,"title":5,"body":6,"category":639,"description":640,"extension":641,"meta":642,"navigation":580,"ogImage":643,"path":644,"project_name":645,"published":646,"publishedAt":647,"seo":648,"stem":649,"tags":650,"todo":643,"unpublished":646,"updatedAt":643,"__hash__":657},"pages/2026-05/2026-05-17/diary-2026-05-17.md","2026年5月17日の開発日記 - 家族旅行アーカイブを Astro + Cloudflare で立ち上げて一日で形にした",{"type":7,"value":8,"toc":622},"minimark",[9,14,23,27,34,37,42,49,55,68,79,82,86,93,97,115,123,125,129,140,144,155,163,165,169,172,176,190,198,200,204,219,223,247,255,257,260,513,515,518,563,565,569,595,597,600],[10,11,13],"h1",{"id":12},"_2026年5月17日の開発日記","2026年5月17日の開発日記",[15,16,17,18,22],"p",{},"日曜の朝、eurekapu-nuxt4 の未コミット 3 系統を片付けたところで、ふと「家族旅行の計画を Cloudflare にデプロイしたい」と思い立った。そこから一日中 Astro で ",[19,20,21],"code",{},"family-trips"," プロジェクトを組み立て、ガントチャート、Leaflet 地図、意思決定ページまで形にしてしまった日。",[24,25,26],"h2",{"id":26},"今日のタイムライン",[15,28,29],{},[30,31],"img",{"alt":32,"src":33},"タイムライン","/2026-05/2026-05-17/timeline-2026-05-17.png",[24,35,36],{"id":36},"今日やったこと",[38,39,41],"h3",{"id":40},"_1-朝eurekapu-nuxt4-の積み残し-3-系統を朝の-30-分で回収","1. 朝、eurekapu-nuxt4 の積み残し 3 系統を朝の 30 分で回収",[15,43,44,45,48],{},"昨日のサマリーには載っていないのに、",[19,46,47],{},"git status"," で 3 系統の未コミット作業（CH8 Micron 事例、TOC FAB、クイズパンくず）が残っていた。「ほぼ完成・未テスト」の状態をどう片付けるか、Claude Code に進捗をマークダウンで吐かせてから動いた。",[15,50,51],{},[52,53,54],"strong",{},"主な成果:",[56,57,58,62,65],"ul",{},[59,60,61],"li",{},"3 系統を chrome-devtools MCP で実機確認（ナロー初回レンダで FAB が出ない挙動も拾えた）",[59,63,64],{},"意味のある単位で 3 つの本コミットに分割して push",[59,66,67],{},"スクショ系のメモは untracked のまま残す判断",[15,69,70,73,74],{},[52,71,72],{},"詳細:"," ",[75,76,78],"a",{"href":77},"/investment-textbook-pending-commits","投資判断教科書の未コミット 3 系統を朝に発見、実機で確認しながら分割コミットで片付けた話",[80,81],"hr",{},[38,83,85],{"id":84},"_2-family-trips-プロジェクトを-astro-cloudflare-pages-で立ち上げ","2. family-trips プロジェクトを Astro + Cloudflare Pages で立ち上げ",[15,87,88,89,92],{},"8月の大分帰省を皮切りに、家族旅行の計画と記録を残すサイトを Astro でゼロから立ち上げた。Nuxt ではなく Astro を選んだのはコンテンツコレクションが「旅行ごとに1ページ」のアーカイブ構造とぴったり合うから。pnpm の ",[19,90,91],{},"minimumReleaseAge","（サプライチェーン攻撃対策）が Astro 6.3.3 を弾いて、10日前リリースの 6.3.1 にバージョン固定。",[15,94,95],{},[52,96,54],{},[56,98,99,102,105,108],{},[59,100,101],{},"Astro + Vue インテグレーション + Leaflet（OpenStreetMap）構成",[59,103,104],{},"GitHub（private）→ Cloudflare Pages デプロイ完了",[59,106,107],{},"Cloudflare Access（One-time PIN メール認証）で家族メンバーだけ閲覧できる方針",[59,109,110,111,114],{},"Wikimedia 画像の ORB ブロックには ",[19,112,113],{},"public/images/guides/"," に同一オリジン配信で対処",[15,116,117,73,119],{},[52,118,72],{},[75,120,122],{"href":121},"/family-trips-astro-cloudflare-launch","家族旅行アーカイブを Astro + Cloudflare Pages で立ち上げた記録（pnpm の minimumReleaseAge で躓いた話含む）",[80,124],{},[38,126,128],{"id":127},"_3-旅行日程ガントチャートのレーン構成転置レイアウトを試行錯誤","3. 旅行日程ガントチャートのレーン構成・転置レイアウトを試行錯誤",[15,130,131,132,135,136,139],{},"旅行詳細ページの最上部にガントチャートを置いた。レーン構成 2 本 → 6 本 → 7 本、時間目盛り 0/6/12/18 → 3 時間刻み、日付またぎ線の太さと色を 3 往復、短バーの潰れ対策に min-height 確保、そして横長から ",[52,133,134],{},"縦長レイアウトに転置","。ロジックは ",[19,137,138],{},"src/lib/gantt.ts"," に純粋関数として切り出して Vitest で 30 件 pass。",[15,141,142],{},[52,143,54],{},[56,145,146,149,152],{},[59,147,148],{},"縦長 7 レーンのガントチャートに着地",[59,150,151],{},"Vitest 30 件 pass、カバレッジ Statements 91% / Lines 94%",[59,153,154],{},"dev サーバを 4321/4322/4323/4324 と無計画に増やした失敗 → 全 kill して 4321 に統一",[15,156,157,73,159],{},[52,158,72],{},[75,160,162],{"href":161},"/gantt-chart-layout-iterations","旅行日程ガントチャートのレーン構成・転置レイアウトを試行錯誤した記録",[80,164],{},[38,166,168],{"id":167},"_4-大分エリアの行きたい場所-60-件福岡ガイド-2-本を-leaflet-で地図化","4. 大分エリアの行きたい場所 60 件＋福岡ガイド 2 本を Leaflet で地図化",[15,170,171],{},"ターミナルのタグ付きテーブルでは距離感が掴めなかったので、左サイドにカードリスト、右側に Leaflet マップを置く Google マップ風の分割 UI に作り変えた。福岡 2 泊 3 日の家族ガイドと 1 泊 2 日の下見ガイドも同じ構造で展開。ガントバーをクリックすると地図ズーム＋ピンハイライト＋右パネル表示が連動する仕掛けを入れた。",[15,173,174],{},[52,175,54],{},[56,177,178,181,184,187],{},[59,179,180],{},"Tooltip → 矢印付き Popup に切替（カードがピンから離れすぎていた）",[59,182,183],{},"タイル切替（OpenStreetMap ⇄ CartoDB Positron）＋ localStorage 保存",[59,185,186],{},"ピンのラベル常時表示モード ON/OFF トグル",[59,188,189],{},"座標ミス（ハーモニーランド）を Web 検索で正しい値に修正",[15,191,192,73,194],{},[52,193,72],{},[75,195,197],{"href":196},"/leaflet-map-points-of-interest","大分の行きたい場所 60 件＋福岡ガイド 2 本を Leaflet で地図化：左カードリスト×右マップの分割 UI を Claude Code に組ませた一日",[80,199],{},[38,201,203],{"id":202},"_5-意思決定ページと家族年齢の動的計算","5. 意思決定ページと家族年齢の動的計算",[15,205,206,207,210,211,214,215,218],{},"リゾートホテル A に泊まるかの意思決定を可視化する専用ページを作った。Excel の 3 シート（基本 4 シナリオ／5 シナリオ／体験価値分解）を JSON に起こして、計算ロジックを ",[19,208,209],{},"src/lib/sugino-i.ts"," に純粋関数として切り出し、Vue コンポーネントでインタラクティブな感度分析を載せた。家族の生年月は ",[19,212,213],{},".gitignore"," で除外して、",[19,216,217],{},"import.meta.glob"," で「あれば読む、無ければ空配列」に倒した。",[15,220,221],{},[52,222,54],{},[56,224,225,234,237,244],{},[59,226,227,228,230,231,233],{},"個人情報を ",[19,229,213],{}," + ",[19,232,217],{}," で防御的に隔離",[59,235,236],{},"旅行詳細ページを「結論はテーブル、詳細はクリックで」方針に組み直し",[59,238,239,240,243],{},"検討メモは右ドロワー（",[19,241,242],{},"\u003Cdialog>"," + CSS スライドアニメーション）で開閉",[59,245,246],{},"業界標準 3 層モデル（募集型パッケージ／DP／FIT）で交通手段の判断軸を整理",[15,248,249,73,251],{},[52,250,72],{},[75,252,254],{"href":253},"/decision-pages-and-dynamic-family-ages","家族旅行サイトに『意思決定ページ』と動的年齢計算を仕込んだ — import.meta.glob で個人情報を防御する",[80,256],{},[24,258,259],{"id":259},"今日の試行錯誤",[261,262,263,285],"table",{},[264,265,266],"thead",{},[267,268,269,273,276,279,282],"tr",{},[270,271,272],"th",{},"#",[270,274,275],{},"テーマ",[270,277,278],{},"試したこと",[270,280,281],{},"結果",[270,283,284],{},"気づき",[286,287,288,306,323,343,360,376,392,409,425,441,458,475,496],"tbody",{},[267,289,290,294,297,300,303],{},[291,292,293],"td",{},"1",[291,295,296],{},"Astro 依存解決",[291,298,299],{},"pnpm install で Astro 6.3.3 を入れる",[291,301,302],{},"エラー（minimumReleaseAge でブロック）",[291,304,305],{},"サプライチェーン攻撃対策が効いていた。設定を外すのではなく 10 日前の 6.3.1 に固定",[267,307,308,311,314,317,320],{},[291,309,310],{},"2",[291,312,313],{},"Cloudflare Pages デプロイ",[291,315,316],{},"wrangler で Direct Upload",[291,318,319],{},"成功するが GitHub 連携に切り替えたくなる",[291,321,322],{},"Direct Upload と GitHub 連携モードは相互変換不可。削除して作り直し",[267,324,325,328,331,334,337],{},[291,326,327],{},"3",[291,329,330],{},"Wikimedia 画像配信",[291,332,333],{},"hotlink で表示",[291,335,336],{},"ORB で blocked、空白",[291,338,339,340,342],{},"サイズ 500px 推奨、User-Agent 指定、最終的に ",[19,341,113],{}," にダウンロードして同一オリジン配信",[267,344,345,348,351,354,357],{},[291,346,347],{},"4",[291,349,350],{},"ガント レーン構成",[291,352,353],{},"移動／宿泊の 2 本 → 6 本 → 7 本",[291,355,356],{},"OK",[291,358,359],{},"「宿泊」だと実家かホテルか分からない。実家／外泊で分けたほうが情報量が増える",[267,361,362,365,368,371,373],{},[291,363,364],{},"5",[291,366,367],{},"ガント 日付またぎ線",[291,369,370],{},"1px 薄グレー → 2px 濃グレー → 2px 薄グレー",[291,372,356],{},[291,374,375],{},"1 往復目で「濃すぎる」と指摘され戻した。線は強すぎても弱すぎても主張が変わる",[267,377,378,381,384,387,389],{},[291,379,380],{},"6",[291,382,383],{},"ガント レイアウト",[291,385,386],{},"横長 → 縦長に転置",[291,388,356],{},[291,390,391],{},"短バーが潰れるなら、バー自体に min-height を確保するのが手っ取り早い",[267,393,394,397,400,403,406],{},[291,395,396],{},"7",[291,398,399],{},"dev サーバ",[291,401,402],{},"古いプロセスが残ったまま新規ポート起動を繰り返す",[291,404,405],{},"4321/4322/4323/4324 と増殖",[291,407,408],{},"全プロセスをまとめて kill して 1 個に戻す。最初からそうしておけば良かった",[267,410,411,414,417,420,422],{},[291,412,413],{},"8",[291,415,416],{},"Leaflet ピン表示",[291,418,419],{},"Tooltip → カードが遠すぎ → Popup（矢印付き）",[291,421,356],{},[291,423,424],{},"Popup なら矢印で関係性が一目で分かる",[267,426,427,430,433,436,438],{},[291,428,429],{},"9",[291,431,432],{},"ガント連動",[291,434,435],{},"バークリックで地図ズーム＋ピンハイライト＋詳細パネル",[291,437,356],{},[291,439,440],{},"連動できた瞬間が一番楽しかった",[267,442,443,446,449,452,455],{},[291,444,445],{},"10",[291,447,448],{},"座標",[291,450,451],{},"ハーモニーランドの座標を間違えて入力",[291,453,454],{},"別の場所にピンが立つ",[291,456,457],{},"Web 検索で正値（33.400804, 131.546473）に修正",[267,459,460,463,466,469,472],{},[291,461,462],{},"11",[291,464,465],{},"検討メモ表示",[291,467,468],{},"ページ遷移 vs モーダル vs 右ドロワー",[291,470,471],{},"右ドロワー採用",[291,473,474],{},"メイン情報が左に残るので、長い読み物にも耐える",[267,476,477,480,483,486,493],{},[291,478,479],{},"12",[291,481,482],{},"個人情報",[291,484,485],{},"家族の生年月を JSON で持ちたいが GitHub に上げたくない",[291,487,488,230,490,492],{},[19,489,213],{},[19,491,217],{}," で防御",[291,494,495],{},"「ファイルが無ければ空配列を返す」設計で別ブランチ/CI でもビルドが壊れない",[267,497,498,501,504,507,510],{},[291,499,500],{},"13",[291,502,503],{},"curl と実機確認",[291,505,506],{},"curl で HTML だけ見て「動いてる」と判断",[291,508,509],{},"実画面では潰れていた",[291,511,512],{},"画面を見ないと UI 系の崩れは絶対に拾えない",[80,514],{},[24,516,517],{"id":517},"今日の学び",[56,519,520,529,535,541,547,557],{},[59,521,522,525,526,528],{},[52,523,524],{},"未コミット作業はサマリーに書かないと翌朝忘れる",": 5/16 のサマリーに「ほぼ完成・未テスト」を載せていなかったせいで、朝に ",[19,527,47],{}," で気付くハメになった",[59,530,531,534],{},[52,532,533],{},"pnpm の minimumReleaseAge は外さない",": 設定を消すのではなく、10 日以上前のバージョンに固定する方が筋がいい。サプライチェーン攻撃対策は守る価値がある",[59,536,537,540],{},[52,538,539],{},"画面を見ないと UI 崩れは絶対に拾えない",": curl で HTML 確認しただけで「動いてる」と思い込むと、ユーザー（自分）から「潰れてますって」とすぐに突き返される",[59,542,543,546],{},[52,544,545],{},"dev サーバを増やすな",": 古いプロセスを kill せずに新規ポート起動を繰り返すと、4321/4322/4323/4324 と無駄に増える。最初に全部殺す",[59,548,549,556],{},[52,550,551,552,230,554,233],{},"個人情報は ",[19,553,213],{},[19,555,217],{},": 「ファイルが無ければ空配列を返す」設計にしておけば、別ブランチでも CI でもビルドが壊れない",[59,558,559,562],{},[52,560,561],{},"業界標準を調べてから自分のアプローチを組む",": 募集型パッケージ／DP／FIT の 3 層モデルを当てはめると、自分の特殊事情（実家泊 5 泊）が DP の旨味を削いでいる構造が見えた",[80,564],{},[24,566,568],{"id":567},"明日やること任意","明日やること（任意）",[56,570,573,583,589],{"className":571},[572],"contains-task-list",[59,574,577,582],{"className":575},[576],"task-list-item",[578,579],"input",{"disabled":580,"type":581},true,"checkbox"," family-trips をブラウザで通しで触って、移動／宿泊／観光／実家／外泊／仕事の 7 レーン構成に最後の違和感がないか確認",[59,584,586,588],{"className":585},[576],[578,587],{"disabled":580,"type":581}," Cloudflare Access の One-time PIN メール認証を実機で動かす",[59,590,592,594],{"className":591},[576],[578,593],{"disabled":580,"type":581}," 大分エリアの「行ったところ」マーク機能（既訪/未訪のフィルター）を追加",[80,596],{},[24,598,599],{"id":599},"関連記事",[56,601,602,606,610,614,618],{},[59,603,604],{},[75,605,78],{"href":77},[59,607,608],{},[75,609,122],{"href":121},[59,611,612],{},[75,613,162],{"href":161},[59,615,616],{},[75,617,197],{"href":196},[59,619,620],{},[75,621,254],{"href":253},{"title":623,"searchDepth":624,"depth":624,"links":625},"",2,[626,627,635,636,637,638],{"id":26,"depth":624,"text":26},{"id":36,"depth":624,"text":36,"children":628},[629,631,632,633,634],{"id":40,"depth":630,"text":41},3,{"id":84,"depth":630,"text":85},{"id":127,"depth":630,"text":128},{"id":167,"depth":630,"text":168},{"id":202,"depth":630,"text":203},{"id":259,"depth":624,"text":259},{"id":517,"depth":624,"text":517},{"id":567,"depth":624,"text":568},{"id":599,"depth":624,"text":599},"diary","日曜の朝に eurekapu-nuxt4 の積み残し 3 系統を片付け、その流れで家族旅行アーカイブを Astro + Cloudflare Pages でゼロから立ち上げた。ガントチャート、Leaflet 地図、意思決定ページ、家族年齢の動的計算まで一日で着地させた記録。","md",{},null,"/2026-05-17-diary","daily-log",false,"2026-05-17T00:00:00.000Z",{"title":5,"description":640},"2026-05/2026-05-17/diary-2026-05-17",[651,21,652,653,654,655,656],"日記","astro","cloudflare-pages","leaflet","gantt","eurekapu-nuxt4","TFZ8vCTfgBAYYzcBWaKtAS5U8IDuqKeY_Foiab7TLB0",[],"https://log.eurekapu.com/og/blog/2026-05-17-diary.png?v=2026-05-17T00%3A00%3A00.000Z&title=2026%E5%B9%B45%E6%9C%8817%E6%97%A5%E3%81%AE%E9%96%8B%E7%99%BA%E6%97%A5%E8%A8%98%20-%20%E5%AE%B6%E6%97%8F%E6%97%85%E8%A1%8C%E3%82%A2%E3%83%BC%E3%82%AB%E3%82%A4%E3%83%96%E3%82%92%20Astro%20%2B%20Cloudflare%20%E3%81%A7%E7%AB%8B%E3%81%A1%E4%B8%8A%E3%81%92%E3%81%A6%E4%B8%80%E6%97%A5%E3%81%A7%E5%BD%A2%E3%81%AB%E3%81%97%E3%81%9F&author=Kei%20Komatsu&sig=002639922b665c6a",1782528837463]