Eurekapu簿記問題集をNuxt4へ移行
朝、旧プロジェクトのコードを開いた瞬間にVue 2のfilters構文が目に飛び込んできて、「これは丸ごと書き直しだ」と腹をくくった。そこからCLAUDE.md作成、画像193枚のダウンロード、UIの組み直し、テスト整備、パフォーマンスチューニングまで、一気に駆け抜けた一日。
移行の準備
CLAUDE.mdの作成とpnpm統一
eurekapu-nuxt4リポジトリにCLAUDE.mdを整備し、Claude Codeが迷わず動ける土台を作った。パッケージマネージャもnpmからpnpmに統一。lockファイルの不整合がなくなり、CIでの再現性が上がった。
VPS経由の画像一括ダウンロード(193枚)
簿記問題集の画像はCloudflare配下の本番サーバーに置いてあったが、FTP経由でのダウンロードがCloudflareのプロキシに阻まれて通らなかった。VPS(ConoHa)にSSH接続し、サーバー間で直接wgetして手元にscpで引き取る方法で解決。193枚の仕訳図・T勘定画像を一括取得した。
UIの実装
2カラムレイアウト
PCでは左にテキスト(問題文・選択肢)、右に画像(仕訳図やT勘定)を並べるレイアウトを組んだ。モバイルでは縦積みに切り替わる。問題を解きながら図を参照する動線が、旧サイトより自然になった。
正解/不正解の色分けとレイアウトシフト防止
回答後に正解は緑、不正解は赤でハイライトする。選択肢のボタンサイズを事前に固定し、色が変わってもレイアウトがガタつかないようにした。旧サイトでは回答のたびに画面がジャンプしていたので、ここは意識して潰した。
ヒントメッセージ
各問題にヒントメッセージを追加。最初は非表示で、ボタンを押すと展開される。ヒントの内容は旧サイトの解説テキストから抽出し、JSON側に持たせた。
デザイン原則に基づくUI改善
クイズ一覧ページ
問題集の一覧ページに、章ごとのグループ表示と進捗率バーを実装。どこまで解いたか、正答率はどうかが一覧で見える。
シグニファイア(行動を誘導する手がかり)
「クリックできる」ことが見た目でわかるよう、カード型のホバーエフェクトとアイコンを追加。トップページから問題集への導線も設置し、初見のユーザーが迷わず問題集にたどり着けるようにした。
テスト環境の構築
Vitest: 24テスト全パス
ユニットテストをVitestで整備。問題データのバリデーション、正解判定ロジック、スコア計算など24テストを書いて全パス。
Playwright E2E: 12テスト全パス
ブラウザテストをPlaywrightで構築。「問題を開く→選択肢を選ぶ→正解/不正解が表示される→次の問題に進む」というフロー全体を12テストでカバー。
ベンチマーク
問題データのロード時間とページ遷移速度を計測し、ベースラインを記録した。後述のlazy import化で数値が大きく動いた。
セキュリティ/パフォーマンス/SREレビュー
Claude Codeにセキュリティ・パフォーマンス・SRE観点のレビューを依頼し、指摘された全項目に対応した。
JSON lazy import化(305KB → 300バイト、99.9%削減)
問題データのJSONファイル(305KB)が初回バンドルに含まれていた。動的importに切り替えたところ、初期ロードのJSサイズが300バイトまで落ちた。ページを開いた瞬間の体感速度が目に見えて変わった。
Google Fonts非同期化
<link rel="preload">とfont-display: swapを組み合わせ、フォント読み込みが描画をブロックしないようにした。
SSL証明書検証修正
開発環境でSSL証明書の検証をスキップしていた設定を本番では有効化するよう修正。
ESLint導入
Nuxt 4推奨のESLint flat configを導入。既存コードのlintエラーを一括修正。
セキュリティヘッダー追加
X-Content-Type-Options、X-Frame-Options、Strict-Transport-SecurityなどのヘッダーをNitroのミドルウェアで追加。
ヘルスチェックエンドポイント
/api/health エンドポイントを実装。デプロイ後の死活監視に使う。
エラーページ(error.vue)
Nuxt標準のerror.vueを実装し、404やサーバーエラー時にユーザーに適切なメッセージを表示するようにした。
事業計画の整理
月額サブスクリプションの導入を検討し、ユーザー登録の導線をProgressive Engagement方式で設計した。最初は無料で問題を解ける状態から始め、利用が進むにつれて登録を促す段階的なアプローチ。具体的な実装はまだ先だが、設計の方向性を固めた。
今日の学び
- Cloudflare配下のサーバーからFTPで直接ファイルを取るのは通らない場合がある。VPSを中継する方法を引き出しに入れておく
- JSONの動的importは手軽なのに効果が大きい。305KBが300バイトに変わったとき、Lighthouseのスコアが跳ね上がった
- レイアウトシフト防止は「要素のサイズを先に確定させる」が基本。色が変わるだけならサイズは変えない
- セキュリティヘッダーは忘れがちだが、Nitroのミドルウェアで一括追加すれば手間はほぼゼロ
- テストを先に書いておくと、パフォーマンス改善でリグレッションが出てもすぐ気づける
次のステップ
- サブスクリプション基盤の技術選定(Stripe統合)
- ユーザー登録フローのプロトタイプ実装
- 残りの章の問題データ移行
- 本番デプロイとCloudflareの設定