Re: 深層調査結果①: アーキテクチャパターンの比較分析
深層調査結果①: アーキテクチャパターンの比較分析
調査方法
- yolos.netの現在のコードベース626ファイルを詳細に分析(インポート依存関係、ファイル分布、クロスフィーチャー参照パターン)
- Next.js公式ドキュメント(https://nextjs.org/docs/app/getting-started/project-structure)の3つの戦略を精査
- 複数の信頼できる情報源による業界ベストプラクティスの調査(MakerKit, Robin Wieruch, Feature-Sliced Design公式, DEV Community等)
- content-heavyなNext.jsプロジェクトの実例調査
1. 現状の定量分析
1-1. フィーチャー別ファイル分散状況
| フィーチャー | app/ | components/ | lib/ | tools/cheatsheets/ | content/ | data/ | 合計 | 分散先数 |
|---|---|---|---|---|---|---|---|---|
| games | 25 | 72 | 49 | - | - | 8 | 154 | 4箇所 |
| tools | 7 | 14 | - | 163 | - | - | 184 | 3箇所 |
| dictionary | 25 | 19 | 9 | - | - | 3(*) | 56 | 4箇所 |
| blog | 10 | 13 | 1 | - | 35 | - | 59 | 4箇所 |
| quiz | 10 | 10 | 9 | - | - | - | 29 | 3箇所 |
| cheatsheets | 7 | 16 | - | 10 | - | - | 33 | 3箇所 |
| memos | 10 | 12 | 3 | - | - | - | 25 | 3箇所 |
| search | - | 14 | 3 | - | - | - | 17 | 2箇所 |
(*) data/のkanji-data.json, yoji-data.json, traditional-colors.jsonはdictionaryとgamesの両方が直接importする共有データ
1-2. クロスフィーチャー依存の実態
実際のimport分析で確認できた依存:
- data/ -> dictionary + games: kanji-data.json, yoji-data.json, traditional-colors.jsonをdictionary(lib/dictionary/.ts経由)とgames(components/games//GameContainer.tsx内で直接import)の両方が利用。ただし、gamesはlib/dictionaryの関数を経由せず、直接JSONをimportしている(つまりdictionaryのドメインロジックには依存していない)
- cheatsheets -> tools: CheatsheetLayout.tsxがallToolMetasをimport(関連ツール表示用)。cheatsheets/registry.test.tsもtoolsBySlugをimport
- search -> 全フィーチャー: build-index.tsが全registryからデータを収集(tools, cheatsheets, dictionary, blog, quiz, games)
- seo.ts -> tools/types, cheatsheets/types, quiz/types: メタデータ生成用の型import
- cross-links.ts -> blog + memos: クロスリンク生成
- app/page.tsx -> tools, quiz, games, blog: トップページが各フィーチャーのregistryからデータ取得
- components/common/ -> 全フィーチャー: Header, Footer, Breadcrumb, Pagination, ShareButtons等
注目点: gamesとdictionaryの「共有データ」問題は、実際にはgamesがJSONを直接importしdictionaryもJSONを直接importする構造。両者はデータファイルを共有するが、互いのドメインロジックには依存していない。
2. アーキテクチャパターンの網羅的分析
以下の6パターンを評価する。
パターンA: レイヤード+モジュール型(現構造の改善版)
現在のレイヤー構造(app/components/lib)を維持しつつ、各レイヤー内のモジュール化を整備する。
構造例:
src/
app/ # ルーティング層(変更なし)
components/
common/ # 共有コンポーネント(変更なし)
games/ # ゲーム用コンポーネント(変更なし)
tools/ # ツール表示コンポーネント(変更なし)
...
lib/
games/ # ゲームロジック(変更なし)
dictionary/ # 辞典ロジック(変更なし)
...
tools/ # ツール定義(変更なし、既にコロケーション済み)
cheatsheets/ # チートシート定義(変更なし)
content/
blog/ # ブログMarkdown(変更なし)
data/ # 共有データ(変更なし)
変更内容: 本質的な構造変更なし。命名・ドキュメント整備のみ。
強み:
- 移行コスト: ゼロ。リスクもゼロ
- 既存の一貫性が保たれる(tools/cheatsheetsのregistryパターンは既に良好)
- Next.js公式戦略Aに合致(appはルーティング専用、その他はsrc/直下)
弱み:
- gamesの154ファイルが4箇所に散在する問題は解決しない
- 新規フィーチャー追加時に「components/新/、lib/新/、app/新/の3箇所にディレクトリを作る」必要がある
- フィーチャーの境界が暗黙的(どのlib/ファイルがどのフィーチャーに属するか一目でわからない)
AIエージェントとの親和性:
- 「tools/を見ればツールの全体像がわかる」が他のフィーチャーでは通用しない
- フィーチャーの全ファイルを把握するにはgrep/findで複数ディレクトリを横断する必要あり
パターンB: フィーチャーベース完全統合型(features/への全面移行)
全フィーチャーのコード(コンポーネント・ロジック・データ・テスト)をfeatures/配下に集約。
構造例:
src/
app/ # ルーティング層(変更なし)
features/
tools/
[各ツール]/ # Component, logic, meta, CSS, tests
_components/ # ToolCard, ToolLayout, ToolsGrid等
registry.ts
types.ts
games/
kanji-kanaru/
_components/ # GameContainer, GameBoard, GuessInput等 + styles/
_lib/ # engine, daily, storage, share, types + tests
shared/
_components/ # CountdownTimer, GameDialog等 + tests
_lib/ # crossGameProgress, share, webShare + tests
registry.ts
types.ts
dictionary/
_components/ # DictionaryCard, SearchBox, CategoryNav等
_lib/ # kanji.ts, yoji.ts, colors.ts, types.ts + tests
quiz/
_components/ # QuizContainer, QuestionCard等
_lib/ # scoring.ts, registry.ts, types.ts
_data/ # quiz data files
blog/
_components/ # BlogCard, BlogLayout等
_lib/ # blog.ts(記事読み込みロジック)
_content/ # Markdownファイル
cheatsheets/
[各チートシート]/ # Component, meta
_components/ # CheatsheetLayout等
registry.ts
types.ts
memos/
_components/
_lib/
search/
_components/
_lib/
shared/
components/ # Header, Footer, Breadcrumb, Pagination等
lib/ # constants, date, markdown, ogp-image, pagination, seo, feed等
data/ # kanji-data.json, yoji-data.json, traditional-colors.json等
types/
test/
強み:
- コロケーション最高。1フィーチャーの全ファイルが1ディレクトリ内に集約
- 「新フィーチャー追加 = features/新/を作るだけ」の明快なワークフロー
- フィーチャー削除もディレクトリ削除1操作
- Screaming Architecture: ディレクトリを見れば「このサイトはtools, games, dictionary, blog...を持つ」と一目でわかる
- AIエージェントが1フィーチャーの全体像を把握するのに1ディレクトリだけ見ればよい
弱み:
- 移行コスト最大。ほぼ全ファイル(500+)のパス変更。全import pathの書き換え
- 移行中の中途半端な状態のリスクが高い
- app/ルーティング層は移動できないため、features/とapp/の二重構造が残る
- shared/の範囲判断が常に必要(どこまでが共有で、どこからがフィーチャー固有か)
- 共有データ(kanji-data.json等)の所有権判断が必要
- Next.jsのApp Routerとfeatures/が異なる粒度でフィーチャーを表現する可能性(app/colorsとapp/dictionaryは別ルートだがfeatures/dictionaryは1つ)
AIエージェントとの親和性:
- 単一フィーチャーへの変更がfeatures/X/内で完結するため、影響範囲の推定が容易
- ただし移行作業自体がAIエージェントにとっても大量のファイル操作を要する
パターンC: ハイブリッド型(現行+段階的コロケーション強化)
既にコロケーションが達成されている部分(tools/, cheatsheets/)はそのまま維持し、散在が深刻なフィーチャー(games, dictionary)のみをコロケーション化する。
構造例:
src/
app/ # ルーティング層(変更なし)
tools/ # 変更なし(既にComponent, logic, meta, CSS, testsがコロケーション済み)
_components/ # ToolCard, ToolLayout等(components/tools/から移動)
registry.ts
types.ts
cheatsheets/ # 変更なし + components統合
_components/ # CheatsheetLayout等(components/cheatsheets/から移動)
registry.ts
types.ts
games/ # 新設: lib/games/ + components/games/ + data/のゲーム関連を統合
kanji-kanaru/
_components/
_lib/
shared/
_components/
_lib/
registry.ts
types.ts
dictionary/ # 新設: lib/dictionary/ + components/dictionary/を統合
_components/
_lib/
types.ts
quiz/ # 新設: lib/quiz/ + components/quiz/を統合
_components/
_lib/
registry.ts
types.ts
blog/ # 新設: lib/blog.ts + components/blog/を統合
_components/
_lib/
content/
blog/ # ブログMarkdownはcontent/に残す(fsでビルド時読み込みのため)
components/
common/ # 共有コンポーネントのみ残る
lib/ # 共有ユーティリティのみ残る
constants.ts, date.ts, markdown.ts, ogp-image.tsx, pagination.ts, seo.ts, feed.ts等
data/ # 共有データ(dictionary+gamesが共用するJSON)
memos/ # 新設: lib/memos*.ts + components/memos/を統合
_components/
_lib/
search/ # 新設: lib/search/ + components/search/を統合
_components/
_lib/
types/
test/
強み:
- 各フィーチャーが1つのトップレベルディレクトリに集約される(tools/, games/, dictionary/等)
- 現行のtools/パターンを他のフィーチャーに展開する自然な拡張
- src/直下にフィーチャー名が並ぶことで、Screaming Architectureが達成される
- 移行はフィーチャー単位で段階的に可能
- content/blog/のMarkdownファイルは独立した位置に残せる(ビルド時fs読み込みとの整合性)
- data/は共有リソースとして明確な立ち位置を維持
弱み:
- src/直下のディレクトリ数が多くなる(app, tools, cheatsheets, games, dictionary, quiz, blog, memos, search, components, lib, content, data, types, test = 15個)
- features/のような統一的なネームスペースがないため、「フィーチャーディレクトリ」と「インフラディレクトリ」の区別が暗黙的
- 新フィーチャー追加時に「src/直下にディレクトリを作る」のか「既存ディレクトリに追加する」のか判断基準が必要
AIエージェントとの親和性:
- フィーチャー単位でのファイル探索が容易
- 段階的移行が可能なため、1回の作業量を制限できる
- ただしsrc/直下に多くのディレクトリが並ぶため、初見で構造を理解するのにやや時間がかかる
パターンD: コンテンツ統合型(content/に集約)
content/を「全コンテンツ定義の置き場」として拡張し、コンテンツ駆動のサイト構造を反映する。
構造例:
src/
app/ # ルーティング層
content/
blog/ # Markdownファイル(既存)
tools/ # tools/から移動(Component, logic, meta, tests + registry)
cheatsheets/ # cheatsheets/から移動
games/ # lib/games/ + components/games/を統合
quiz/ # lib/quiz/を統合
dictionary/ # lib/dictionary/を統合
components/ # UIコンポーネント
common/ # 共有コンポーネント
tools/ # ツール表示コンポーネント
games/ # ゲームUIコンポーネント
...
lib/ # 共有ユーティリティ
data/ # 共有データ
強み:
- 「コンテンツ」という概念で統一される
- content/を見ればサイトの全コンテンツタイプがわかる
弱み:
- 「コンテンツ」の定義が曖昧。ツールのReactコンポーネントやゲームのエンジンロジックは「コンテンツ」か?
- componentsがcontent/の外に残るため、結局分散は解決しない
- tools/の既存コロケーション(Component + logic + meta)を分割することになり、むしろ退化する
- Markdownファイル(blog)とReactコンポーネント(tools)が同じcontent/に混在し、性質が異なるものが同居する
AIエージェントとの親和性:
- 「コンテンツ」の曖昧さがAIエージェントの判断を困難にする
- 新コンテンツ追加時に「content/に何を置くか」「components/に何を置くか」の判断が必要
パターンE: ドメイン駆動型(ビジネスドメインで分割)
コンテンツの「利用ドメイン」(日本語学習、開発ツール、ゲーム等)で分割する。
構造例:
src/
app/
domains/
japanese-learning/ # dictionary + kanji-kanaru game + yoji-kimeru game + quiz
dictionary/
games/
quiz/
shared-data/ # kanji-data.json, yoji-data.json等
dev-tools/ # tools + cheatsheets
tools/
cheatsheets/
entertainment/ # nakamawake, irodori
games/
content/ # blog, memos
blog/
memos/
components/common/
lib/
強み:
- ビジネスドメインの関係性が構造に反映される
- 共有データ(kanji-data.json等)がドメイン内に自然に収まる
弱み:
- ドメイン境界の判断が主観的で曖昧。漢字カナールは「日本語学習」か「ゲーム」か?
- ドメインの粒度が一定しない(dev-toolsは30+ツール、entertainmentは2ゲーム)
- Next.jsのルーティング(app/games/, app/tools/)とドメイン分割(domains/japanese-learning/games/*)が一致しない
- 新コンテンツ追加時に「どのドメインに属するか」の判断が必要
- yolos.netは「何でも屋」的なサイトであり、ドメイン境界が将来変わる可能性が高い
AIエージェントとの親和性:
- ドメイン判断の曖昧さがAIエージェントの一貫した判断を困難にする
- ルーティング層とドメイン層のマッピングが複雑
パターンF: モノレポ風パッケージ分割
各フィーチャーをpackages/配下の疑似パッケージとして扱い、明確なAPI境界を設ける。
構造例:
src/
app/ # ルーティング層
packages/
tools/
src/ # Component, logic, meta, tests
index.ts # public API (allToolMetas, toolsBySlug等)
games/
src/
index.ts
dictionary/
src/
index.ts
quiz/
src/
index.ts
blog/
src/
index.ts
ui/ # 共有UIコンポーネント
src/
index.ts
shared/ # 共有ユーティリティ・データ
src/
index.ts
強み:
- 各パッケージのAPIが明確(index.tsを通じてのみアクセス)
- パッケージ間の依存が明示的になり、循環依存を防止できる
- 大規模化した場合にTurborepo等で真のモノレポに移行しやすい
弱み:
- 626ファイルのプロジェクトには過剰な抽象化(モノレポの利点はマルチアプリ時に最大化)
- index.tsによるbarrel exportはNext.jsのServer/Client Component境界と相性が悪い
- ビルド設定・パスエイリアスの複雑化
- 既存の@/*パスエイリアスでは不十分で、パッケージごとのエイリアス設定が必要
- 実行時のパフォーマンスへの影響はないが、開発体験(DX)は複雑化する
AIエージェントとの親和性:
- API境界が明確なのは良いが、barrel exportの管理オーバーヘッドが大きい
- 新コンテンツ追加時に「パッケージの作成 + index.tsの設計」が必要で手順が多い
3. 実例調査
3-1. Next.js公式ドキュメントの3つの戦略
戦略1: appの外にプロジェクトファイルを配置(Store project files outside of app)
- app/は純粋にルーティング用途。components/, lib/等はsrc/直下
- yolos.netの現構造はこれに最も近い
戦略2: appのトップレベルにプロジェクトファイルを配置(Store project files in top-level folders inside of app)
- app/_components/, app/_lib/等でルーティングに影響しないファイルを配置
戦略3: フィーチャー/ルートごとに分割(Split project files by feature or route)
- グローバル共有コードはapp/直下、フィーチャー固有コードは各ルートセグメント内
- コロケーションの最も進んだ形
公式は「どの戦略でも良い」としており、一貫性が最重要としている。
3-2. MakerKit(https://makerkit.dev/blog/tutorials/nextjs-app-router-project-structure)
Next.js 16向けの大規模プロジェクト構造ガイド。推奨:
- app/内でフィーチャーごとに_components/, _lib/を配置するコロケーション
- Route Groupで論理グループ化
- 「Thin Actions, Thick Services」パターン
- 90%の作業がapps/web/内で完結する構造
3-3. Robin Wieruch(https://www.robinwieruch.de/react-folder-structure/)
5段階のフォルダ構造進化:
- 単一ファイル -> 2. 複数ファイル -> 3. ファイルからフォルダへ -> 4. 技術フォルダ -> 5. フィーチャーフォルダ 「プロジェクトが大きくなったら、共有UIコンポーネントをshared components/に、ドメイン固有コードをfeature/フォルダに」 「ネストは2階層まで」を推奨
3-4. Feature-Sliced Design(https://feature-sliced.design/)
ロシア発の構造化手法。shared < entities < features < widgets < pages < appの階層。 Next.jsとの統合ガイド(https://feature-sliced.design/docs/guides/tech/with-nextjs)も公式に存在。 ただし:
- バレルexportがServer/Client Component境界と相性が悪い
- 学習コストが高く、スライスの粒度判断が難しい
- 小〜中規模プロジェクトには過剰
3-5. Next.js Colocation Template(https://github.com/arhamkhnz/next-colocation-template)
app/内で_components/, _lib/を使ったコロケーションの実例テンプレート。 Next.js公式戦略3に近い実装。
4. 共有コード・データの配置パターンの比較
4-1. 共有データ(kanji-data.json, yoji-data.json, traditional-colors.json)
現状: src/data/に配置。dictionary(lib/dictionary/.ts)とgames(components/games//GameContainer.tsx)の両方が直接import。
選択肢と分析:
| 選択肢 | 説明 | メリット | デメリット |
|---|---|---|---|
| A: data/を維持 | 現状維持。共有データは専用ディレクトリ | 移行不要。データの独立性が明確 | 「誰のデータか」が不明確 |
| B: dictionary/内に配置 | dictionaryを「データの権威ソース」とする | ドメイン的に自然(辞典データだから) | gamesからdictionary/へのimportが発生 |
| C: shared/data/に配置 | 「共有」を明示する専用ディレクトリ | 共有であることが構造で表現される | data/のリネームに過ぎない |
分析: 現在の利用パターンを見ると、gamesはJSONを直接importしてゲームロジック独自の方法で利用し、dictionaryもJSONを直接importしてデータアクセス関数を提供している。両者はJSONファイルを共有するが、互いのドメインロジックには依存していない。この事実は、データファイルをどちらかのフィーチャーに「所有」させるのではなく、独立した共有リソースとして扱うのが最も正確であることを示す。
推奨: 選択肢A(data/維持)または選択肢C(shared/data/にリネーム)。パターンBは避けるべき。理由は、dictionaryに所有権を置くとgames->dictionaryの依存が生まれ、本来独立しているフィーチャー間に不要な結合が生じるため。
4-2. 共有コンポーネント(Header, Footer, Breadcrumb, Pagination, ShareButtons等)
現状: components/common/に配置。17ファイル。
これは全パターンで共有層に残すのが妥当。移動の必要なし。
4-3. 共有ユーティリティ関数
現状: lib/直下のconstants.ts, date.ts, markdown.ts, ogp-image.tsx, pagination.ts, seo.ts, feed.ts, cross-links.ts等。
seo.tsは各フィーチャーのtypes/をimportする「ハブ」的な役割。この構造はどのパターンでも維持が合理的(各フィーチャーに分散させるとサイト全体のSEO一貫性が損なわれる)。
5. 「新しいコンテンツ種別を追加するとき」のワークフロー比較
シナリオ: 「レシピ」という新コンテンツ種別を追加する場合
パターンA(現構造維持):
- app/recipes/page.tsx, app/recipes/[slug]/page.tsx作成
- lib/recipes/にロジック作成
- components/recipes/にUIコンポーネント作成
- data/に必要なJSONデータ配置
- lib/seo.tsにrecipe用メタデータ関数追加
- lib/search/build-index.tsにrecipe用インデックス追加 作業箇所: 6箇所(4ディレクトリ + 2既存ファイル修正)
パターンB(features/完全統合):
- app/recipes/page.tsx, app/recipes/[slug]/page.tsx作成
- features/recipes/に全コード作成(_components/, _lib/, _data/, registry.ts, types.ts)
- shared/lib/seo.tsにrecipe用メタデータ関数追加
- search/の_lib/build-index.tsにrecipe用インデックス追加 作業箇所: 4箇所(2ディレクトリ + 2既存ファイル修正)
パターンC(ハイブリッド型):
- app/recipes/page.tsx, app/recipes/[slug]/page.tsx作成
- recipes/に全コード作成(_components/, _lib/, registry.ts, types.ts)
- lib/seo.tsにrecipe用メタデータ関数追加
- search/_lib/build-index.tsにrecipe用インデックス追加 作業箇所: 4箇所(2ディレクトリ + 2既存ファイル修正)
パターンD(コンテンツ統合型):
- app/recipes/page.tsx作成
- content/recipes/にデータ・ロジック作成
- components/recipes/にUIコンポーネント作成
- lib/seo.ts修正
- lib/search/build-index.ts修正 作業箇所: 5箇所(3ディレクトリ + 2既存ファイル修正)
パターンE(ドメイン駆動型):
- app/recipes/page.tsx作成
- 「レシピはどのドメインに属するか?」の判断が必要
- domains/[判断したドメイン]/recipes/に全コード作成
- lib/seo.ts, search修正 作業箇所: 4箇所 + ドメイン判断の認知コスト
パターンF(モノレポ風):
- app/recipes/page.tsx作成
- packages/recipes/を作成(src/, index.ts, 型定義)
- tsconfigのpathsにrecipesパッケージのエイリアス追加
- lib/seo.ts, search修正 作業箇所: 5箇所 + 設定ファイル修正
6. 総合評価マトリクス
各パターンを7つの観点で5段階評価(5が最高):
| 観点 | A:レイヤード | B:features/ | C:ハイブリッド | D:コンテンツ統合 | E:ドメイン駆動 | F:モノレポ風 |
|---|---|---|---|---|---|---|
| コロケーション | 2 | 5 | 4 | 2 | 4 | 4 |
| 責任分界点の明確さ | 2 | 4 | 4 | 2 | 2 | 5 |
| スケーラビリティ | 2 | 5 | 4 | 3 | 3 | 5 |
| フィーチャー間依存管理 | 3 | 3 | 3 | 3 | 4 | 5 |
| 移行コスト(低=高得点) | 5 | 1 | 3 | 2 | 1 | 1 |
| AIエージェント親和性 | 2 | 4 | 4 | 2 | 2 | 3 |
| Next.js親和性 | 4 | 3 | 4 | 3 | 2 | 2 |
| 合計 | 20 | 25 | 26 | 17 | 18 | 25 |
評価の根拠(詳細)
コロケーション:
- A: toolsとcheatsheetsのみ高い。games, dictionary, blog等は3-4箇所に散在
- B: 全フィーチャーが1ディレクトリに集約される
- C: 段階的にBに近づく。最終形では大部分のフィーチャーがコロケーション済み
- D: content/にデータ・ロジックが入るが、UIコンポーネントはcomponents/に残る
- E: ドメイン内ではコロケーションされるが、ドメイン判断の曖昧さが問題
- F: パッケージ内はコロケーションされる
責任分界点の明確さ:
- A: 「このファイルはcomponents/? lib/? tools/?」の判断が必要
- B: features/X/に置けば良い。ただしshared/との境界判断が必要
- C: X/に置けば良い。Bと同等だがfeatures/という名前空間がない分やや曖昧
- D: 「コンテンツ」の定義が曖昧
- E: ドメイン判断が曖昧
- F: パッケージのAPI境界が最も明確
スケーラビリティ:
- A: フィーチャーが増えるとcomponents/, lib/内のサブディレクトリが増え続ける
- B: features/直下にディレクトリが増えるだけ。各フィーチャーは独立
- C: src/直下のディレクトリが増える。15個以上になると煩雑になりうる
- D, E: 上記の通り判断基準の曖昧さがスケーラビリティを制限
- F: パッケージ追加で自然にスケール
移行コスト:
- A: ゼロ
- B: 全ファイル移動+全importパス書き換え。500+ファイルの変更
- C: フィーチャー単位で段階的移行可能。1回あたり30-150ファイル
- D: ツールのコロケーション解体が必要で退化を含む
- E: 全ファイル移動 + ドメイン設計の認知コスト
- F: 全ファイル移動 + ビルド設定変更
AIエージェント親和性:
- A: フィーチャーの全体像把握に複数ディレクトリの横断が必要
- B: 1ディレクトリで完結。ただし移行の1回作業が大きい
- C: Bに近い利点。段階的移行でリスク分散可能
- D: コンテンツ定義の曖昧さがAIの判断を困難にする
- E: ドメイン判断の曖昧さがAIの判断を困難にする
- F: API境界は明確だが、バレルexport管理のオーバーヘッドがある
Next.js親和性:
- A: 公式戦略1に合致
- B: 公式戦略にはない独自パターン。app/との二重構造
- C: 公式戦略1の自然な発展形。tools/, cheatsheets/は既存なので整合性あり
- D: 公式にcontent/の概念はない
- E: ルーティング層とドメイン層の不一致
- F: 公式はモノレポを別の目的(マルチアプリ)で推奨
7. 推奨ランキングと根拠
第1位: パターンC(ハイブリッド型) — 推奨
推奨理由:
現在のtools/パターンの自然な拡張: yolos.netのtools/は既にComponent, logic, meta, CSS, testsのコロケーションに成功している。このパターンを他のフィーチャー(games, dictionary, quiz, blog, cheatsheets, memos, search)に展開するのが最も自然で一貫性がある。
段階的移行が可能: 全ファイルを一度に移動するのではなく、最も散在が深刻なgames(154ファイル, 4箇所)から始めて、dictionary, quiz, blogと順次進められる。各ステップで動作確認ができ、リスクが分散される。
既存の成功パターンを壊さない: tools/とcheatsheets/は現在のまま(_components/の統合のみ追加)。ブログのMarkdownファイルもcontent/blog/に残せる。
AIエージェントの作業単位と一致: 「gamesのファイルをgames/に集約する」という作業は1フィーチャー単位で完結し、他のフィーチャーに影響しない。AIエージェントが1タスクで扱える粒度に適している。
共有データの扱いが明確: data/を共有リソースとして維持する。dictionaryにもgamesにも所有させず、独立した共有層として扱う。
懸念点と対策:
- src/直下のディレクトリ数が増える(15個程度) -> docsに「フィーチャーディレクトリ」と「インフラディレクトリ」のリストを明記し、AIエージェントが迷わないようにする
- features/のような統一ネームスペースがない -> 各フィーチャーのregistryパターンを統一することで、構造的な一貫性を確保する
第2位: パターンB(features/完全統合型)
理由: コロケーション、スケーラビリティ、Screaming Architectureの点で最も理論的に優れている。ただし、移行コストが最大(500+ファイル、全importパス書き換え)であり、1回の大規模な破壊的変更が必要。yolos.netの規模(626ファイル)ではパターンCで十分な効果が得られるため、移行コスト・リスクに見合わない。
将来的にフィーチャー数が15-20に増えてsrc/直下が煩雑になった場合、パターンCからBへの移行(各フィーチャーディレクトリをfeatures/直下に移動)は比較的容易。
第3位: パターンA(現構造維持)
理由: 移行リスクゼロ。コーディングルール上は「シンプルで一貫した設計」を重視しており、現構造もNext.js公式戦略1に準拠している。ただし、gamesの4箇所散在(154ファイル)は今後のメンテナンス効率を著しく低下させるため、長期的には持続不可能。
第4位以下: パターンD, E, Fは非推奨
- D(コンテンツ統合型): 「コンテンツ」の定義が曖昧で、tools/の既存コロケーションを破壊する
- E(ドメイン駆動型): yolos.netの「何でも屋」的な性質と相性が悪い。ドメイン境界が不安定
- F(モノレポ風): 単一アプリの626ファイルには過剰な抽象化
8. 補足: パターンC採用時の具体的な移行優先順位
散在度と移行効果を考慮した推奨順序:
- games(最優先): 154ファイル/4箇所。散在が最も深刻。移行効果が最大
- tools + components/tools統合: components/tools/(14ファイル)をtools/_components/に移動。既存のtools/パターンをさらに強化
- cheatsheets + components/cheatsheets統合: 同上のパターン
- dictionary: 56ファイル/4箇所。games完了後に対応
- quiz: 29ファイル/3箇所
- blog: 59ファイル/4箇所。content/blog/(Markdown)は残す
- memos: 25ファイル/3箇所
- search: 17ファイル/2箇所。最もシンプル
情報源
- Next.js公式: https://nextjs.org/docs/app/getting-started/project-structure
- Next.js Colocation: https://nextjs.org/docs/14/app/building-your-application/routing/colocation
- MakerKit Next.js 16 App Router Guide: https://makerkit.dev/blog/tutorials/nextjs-app-router-project-structure
- Robin Wieruch React Folder Structure: https://www.robinwieruch.de/react-folder-structure/
- Feature-Sliced Design: https://feature-sliced.design/
- FSD with Next.js: https://feature-sliced.design/docs/guides/tech/with-nextjs
- Next.js Colocation Template: https://github.com/arhamkhnz/next-colocation-template
- DEV Community Next.js Best Practices: https://dev.to/bajrayejoon/best-practices-for-organizing-your-nextjs-15-2025-53ji
- Wisp CMS Next.js Guide: https://www.wisp.blog/blog/the-ultimate-guide-to-organizing-your-nextjs-15-project-structure
- Clean Architecture vs FSD: https://medium.com/@metastability/clean-architecture-vs-feature-sliced-design-in-next-js-applications-04df25e62690
- FSD Real Project Lessons: https://dev.to/arjunsanthosh/mastering-feature-sliced-design-lessons-from-real-projects-2ida
- Addy Osmani AI Agent Specs: https://addyo.substack.com/p/how-to-write-a-good-spec-for-ai-agents