2024年5月、株式会社ゆめみのインターン・新卒本選考に用いられていたフロントエンドコーディング試験に挑戦しました。提出したのが、RESASの都道府県別人口データを選び、推移を同じグラフ上で比較できるこのWebアプリケーションです。
企画やデザインを分担したチーム制作ではありません。要件の読み解きからFigmaでの画面設計、技術選定、実装、テスト、CI、ドキュメントまで、6日間、約30時間ですべて一人でつくりました。この作品でゆめみパスポートのSS認定を受け、賞金10万円を受領しました。
課題ではなく、小さなプロダクトとしてつくる
課題の中心は、都道府県を選ぶと人口構成の推移をグラフで比較できる機能です。ただし、実際に使える画面にするには、複数選択の分かりやすさ、時系列グラフの読みやすさ、通信中やエラー時の表示、モバイルでの操作性まで考える必要があります。
そこで私は、仕様どおりに動く画面を提出するだけではなく、アクセシビリティ、デザインと実装の一貫性、テスト可能性、レビューする人が再現できる開発環境まで含め、一つの小さなプロダクトとして完成させることを目標にしました。
制作したのは、現在のようなcoding agentが開発現場へ普及する前です。使ったAI支援はGitHub CopilotのTab補完モデルだけで、要件の解釈や設計をAIへ委ねるのではなく、すべての判断と実装に自分で責任を持ちました。
技術スタックをどう組み合わせたか
- Next.js 14 App Router / React Server Components: RESAS APIへのアクセスとデータ整形をサーバー側に置き、APIキーをブラウザへ渡さない構成にしました。
- TypeScript / Zod: URLパラメーター、都道府県コード、統計種別、外部APIレスポンスを実行時にも検証し、不正なデータをグラフまで流さない境界をつくりました。
- Figma Variables / Panda CSS: ライト・ダーク両テーマの色を役割ごとのトークンとして設計し、Figmaと実装で同じ考え方を使いました。
- Recharts: 都道府県ごとに線の色を割り当て、年次データを比較できるレスポンシブな折れ線グラフを実装しました。
- Vitest / Storybook / Playwright: データ変換、コンポーネント、実際の利用経路を別々の層で検証しました。
- Turborepo / GitHub Actions: モノレポ内のビルド、Lint、Unit Test、Storybook Test、E2E TestをPull Requestごとに自動実行しました。
実装でこだわったこと
APIキーを隠すだけでなく、外部データを検証する
RESAS APIへのfetchはServer Componentから呼ばれるサーバー側のモジュールへ集約しました。APIキーを環境変数からヘッダーへ渡し、レスポンスは24時間キャッシュします。
const response = await fetch(endpoint, {
headers: {
"X-API-KEY": env.RESAS_API_KEY,
},
next: {
revalidate: 3600 * 24,
},
})
const result = rawFetchResultSchema.parse(await response.json())大切にしたのは、取得したJSONを信用してそのまま描画しないことです。Zodでステータス、人口値、割合、年、統計ラベルまで検証し、日本語の統計ラベルをアプリ内の型へ変換してからRechartsへ渡しました。これにより、APIの異常をグラフの表示崩れとして発見するのではなく、データ境界で明示的に扱えます。
URLそのものを比較条件にする
選択中の都道府県と統計種別は、画面内だけの状態にせずURLへ反映しました。
/all?prefCodes=8,12,13このURLを開けば、茨城県、千葉県、東京都の総人口を比較した状態をそのまま再現できます。ページタイトルとOpen Graph情報も同じ条件から生成するため、URLを共有した相手にも「何を比較しているページか」が伝わります。
サーバー側ではstatLabelとprefCodesをZodで検証し、都道府県名を含むタイトルを組み立てます。表示状態、URL、メタデータを同じ入力からつくることで、共有時だけ内容が食い違う状態を避けました。
Figmaと実装で同じデザイントークンを使う
ライト・ダーク両テーマは、Figma Variablesで背景、文字、境界、操作状態の役割を定義し、CSS VariablesとPanda CSSのtoken・recipeへ対応させました。個々のコンポーネントへ色を直接書かないため、テーマが変わってもコントラストと状態表現を同じ規則で確認できます。
読み込み中は47都道府県分のSkeletonを表示し、グラフ部分はSuspenseで切り分けました。狭い画面でも選択操作を続けられるよう、選択数とクリア操作を示すバーはヘッダーの下へ追従させています。READMEに残した計測では、PageSpeed InsightsのAccessibilityスコア100を記録しました。
テストごとに役割を分ける
テストは数を増やすのではなく、失敗したときに原因が分かるよう役割を分けました。
- Vitestでは、APIレスポンスの変換、統計種別ごとのデータ抽出、都道府県名を使ったタイトル生成を検証
- Storybookでは、Checkbox、Select、Chart、ナビゲーションなどの見た目と操作を単独で確認
- Playwrightでは、都道府県の選択がURLへ反映されること、共有URLから4本のグラフが表示されること、クリア操作で選択を解除できることをブラウザで検証
GitHub Actionsでは、Build、Lint、Unit Test、Storybook Test、Playwright E2Eを独立したジョブとして実行しました。README、開発コンテナー、バージョン指定も用意し、レビュワーが同じ手順で動作を確かめられる状態までを提出物に含めています。
レビューで得た評価
提出後のレビューでは、独自の画面設計、キャッシュ、エラーとローディングの扱い、コンポーネント分割、テスト、CI、APIキーの管理、semantic HTMLなどがGood項目に挙げられました。特に印象に残っているのは、次の原文です。
「極めて高レベルな対応を 30 時間という短い時間で成し遂げられており」
「レビュワー一同、非常に好評価でした。」
単に機能要件を満たしたことではなく、限られた時間の中で設計、テスト、文書化まで一貫して仕上げた過程を評価していただけたと受け止めています。
Issue #186のコーディングチェックには、公開リポジトリを改めて確認した結果が次のように記録されています。
- 総合評価: S
- スコア: 28.5 / 33.5点
- 必須項目: 13/13 (100%)
- Good項目: 32/41 (78%)
- 改善項目: 2件
このチェックでも、Server Componentsを使った構成、24時間キャッシュ、複数レベルのテスト、UI・UX、APIキーの管理が評価されました。一方で、チェックボックスのlabelにクリック可能であることを示すcursorがないこと、トップページで選択しても表示内容が変わらないことは改善点として残りました。機能があるだけでなく、操作の結果が迷わず伝わるUIにする必要があると学びました。
最終的に、このコーディング試験でゆめみパスポートのSS認定を受けました。当時の募集ページでは、SSを「既にゆめみのプロフェッショナル職位として実戦で通用するレベル」と位置づけ、賞金を10万円としていました。認定により、コーディング試験を再受験せず新卒本選考の一次面接へ進める資格も得ました。

