講座ページに「前へ/次へ」フッターナビを標準装備 - スマホで行き止まりになる問題とSVG 105件の本番未アップロード修正
朝、スマホで本番の講座ページ(SVG図解スキルのレッスン)を開いて、最後までスクロールしたところで指が止まった。次のページへ進むボタンがどこにもない。デスクトップなら横のナビゲーションで移動できるが、スマホ表示では読み終えても行き止まりになる。講義ノート系のページには「次へ進む」UIをつけていた記憶があったので、スクリーンショットを貼って「講座コンテンツにも全部つけてほしい」とClaude Codeに投げた。
SVG 105件が本番CDNに存在しなかった
あわせて、講座一覧のカード画像(SVG)が切れているのも見つけた。調査させると、切り分けは次の順で進んだ。
- ローカルにファイルは存在する
- SVG自体も
<img>で描画できる正常な形式(xmlns等も問題なし) - では本番は? → SVG 105件が本番CDNに未アップロードだった
ローカルでは何の問題もなく表示されるので、コードをいくら眺めても原因にたどり着けないタイプの不具合だった。配信先を直接叩いてはじめて分かった。状況が整理できたところでタスクとして登録し、アップロード作業に進ませた。
アップロードの試行錯誤
修正は一直線には進まなかった。
- アップロードコマンドをそのまま流すとエスケープ問題で詰まったので、スクリプトをファイルに書き出して実行する方式に切り替えさせた
- 次は wrangler が未ログインで止まった。認証を通し直してもらう
- まず1件だけアップロードして、本番CDNで実際に返ってくることを確認
- 1件成功を見てから、残り104件を並列アップロード
- 流しっぱなしにせず、105件全件を本番CDNに再チェックして全部返ってくることを確かめてから完了とした
「アップロードは流れた」と「全件表示できる」は別物なので、最後の全件チェックまでやってようやく安心できた。仕上げに本番の講座一覧ページを開き、カード画像が枠だけでなく中身ごと表示されるところまで見届けた。
フッターナビはレイアウト側で標準装備する
次へボタンのほうは、スマホ専用の暫定対応ではなく「全コンテンツの最下部に、移動先タイトル付きの前へ/次へボタンを標準で出す」方針にした。「次へ」だけでは次に何が待っているか分からないので、ボタンには移動先のコンテンツタイトルを表示する。
設計のポイントは、各ページに実装を足すのではなく、レイアウトコンポーネント側(MillerViewer)が自動で描画すること。
- 共通コンポーネント
MillerFooterNav.vueを新規作成 MillerViewer.vue(レイアウト側)から全コンテンツ共通で描画- ページ側の実装は不要。今後コンテンツを増やしてもナビの付け忘れが起きない
構成のイメージはこう(実コードではなく方針の骨格)。
<!-- MillerViewer.vue(レイアウト側)。各コンテンツページは何も書かない -->
<template>
<slot /> <!-- コンテンツ本体 -->
<MillerFooterNav /> <!-- 前後のコンテンツを解決してタイトル付きボタンを描画 -->
</template>
作業は git worktree で feat/miller-footer-nav ブランチを切って進めさせた。本体のチェックアウト(ポート3200のdevサーバー)はそのままに、worktree側で検証用サーバーをポート3210に立てる構成。本体の画面を壊さずに、隣で新レイアウトを動かして比べられる。
agent-browser での描画確認
検証は agent-browser でひととおり回した。
- デスクトップ表示: コンテンツ下部に前へ/次へが出る
- モバイル表示: フッターに「← 前へ(先頭ページでは無効)/ 次へ →」が表示され、タップで実際に遷移する
- 複数チャプター構成のページ: 移動先タイトルのラベルが正しく出る
- 開発サーバーのログ: エラーなし(既存の警告のみ)
モバイル確認では、スクリーンショットがデスクトップ幅のまま撮れてしまい、リサイズをやり直させる一幕もあった。「確認した」の中身がデスクトップ幅のままでは意味がないので、ビューポートの実寸まで疑って見直せたのはよかった。
ESLint も変更ファイルに掛けてから、コミット前には学習ゲート(/learn)のクイズを挟んだ。再出題も含めて全問合格し、受領証を発行してコミット(8c3173cb)。
報告はスクリーンショット3枚付きで受けた(途中2件がネットワークエラーで届かず再送になる小トラブルはあった)。検証用に立てていた3210のサーバーは、確認が済んだあと停止。動作確認はスクリーンショットで残っているので成果物への影響はなし、という整理でこの件はクローズした。
本体側への取り込み手順も控えておく。朝に入れた暫定変更を git restore app/components/bookkeeping/MillerViewer.vue で戻してから git merge feat/miller-footer-nav を実行すれば、いつもの3200でフッターナビ付きの表示になる。
「表示が変わっちゃった」の犯人は朝の自分だった
昼前、別セッションで作業していたら講座ページの見た目が変わっていることに気づいて、「ちょっと待って、これどうなってますか?」と聞いた。文脈ゼロの「これ」では伝わらず、まずリポジトリに残っている未整理の変更一覧が返ってきた。「表示が変わっちゃった」と言い直して切り分けてもらった結果、原因は朝8時13分に入っていた未コミットの MillerViewer.vue 変更。朝のセッションでスマホ表示の画面下部に前へ/次へボタンを足したものが、コミットされないまま本体側に残っていた。
worktree で並行開発していると、本体側の未コミット変更の存在を忘れて「表示が壊れた?」と一瞬焦る。git status を見れば一発で分かることなのに、見る前に驚いてしまった。
スマホ幅のヘッダー崩れも修正
フッターナビの流れで、スマホ幅でヘッダー(ログインボタンとパンくず)が崩れていたのも直してもらった。該当のヘッダーとパンくずコンポーネントを確認させ、修正後はデスクトップ・モバイル両方で実際の描画を確認。
あわせて、共通フッターナビに置き換わって未使用になったセクション用の computed と mobile-footer の CSS も削除させて、暫定対応の痕跡を残さないようにした。コンソールエラーと他講座への影響がないことも見てから閉じた。
学び
- 「画像が表示されない」は、ファイルの有無・ファイル形式・配信先の3段で切り分ける。今回はローカル正常・形式正常で、本番CDNに105件丸ごと無かった
- 一括アップロードは「1件成功を確認してから残りを並列」の順が安全。流したあとの全件再チェックまでがワンセット
- 全ページに必要なUI(ナビゲーション等)は、ページ側でなくレイアウト側に持たせると付け忘れが起きない
- worktree 並行開発中に「表示が変わった」と感じたら、まず本体側の未コミット変更を疑う。焦る前に
git status