アーキテクチャ概要(全体像)
関連ソースファイル
このページの内容は以下のソースファイルに基づいて生成されています:
- src/app/layout.tsx
- src/lib/store.ts
- src/types/index.ts
- src/contexts/NotificationContext.tsx
- next.config.js
- src/lib/utils.ts
- src/app/page.tsx
- src/app/not-found.tsx
- src/lib/tool-config.ts
- postcss.config.js
- package.json
- .spec-workflow/templates/design-template.md
- next-env.d.ts
- tailwind.config.js
- src/data/tools.ts
- src/hooks/useTextMerger.ts
- src/components/ToolCard.tsx
- src/components/MediaInput.tsx
- src/hooks/useVoiceRecorder.ts
- src/components/Notification.tsx
本プロジェクトは、Next.js App Routerを基盤としたゲーミフィケーション要素を取り入れた作文学習プラットフォームである。六年级(小学6年生)の児童を対象に、ゲームのような体験を通じて作文スキルを段階的に習得できるよう設計されている。アーキテクチャは、モダンなReactパターンとTypeScriptによる型安全性を組み合わせ、Zustandによる状態管理、Context APIによる通知システム、カスタムフックによるロジック再利用を実現している。
技術スタックとフレームワーク構成
基盤技術
プロジェクトはNext.js 13以降のApp Routerアーキテクチャを採用し、サーバーコンポーネントとクライアントコンポーネントを適切に分離している。ルートレイアウトは src/app/layout.tsx:2-30 で定義され、NotificationProvider による通知コンテキストをアプリケーション全体に提供している。メタデータ設定では、アプリケーションタイトル「六年级作文成长手册」と説明文「游戏化作文学习平台 - 在规则内说真话」が定義されている。
Next.js設定は next.config.js:1-20 で管理され、reactStrictMode: true による開発時の品質保証、swcMinify: true による高速なバンドル最適化が有効化されている。また、Vercelデプロイ時の互換性確保のため、画像最適化を無効化し、.mjs ファイルの処理設定を追加している。
スタイリングシステム
Tailwind CSSによるユーティリティファーストなスタイリングを採用し、 tailwind.config.js:1-277 で詳細なカスタムテーマを定義している。特徴的なのは「モランディカラー」システムで、morandi-gray、morandi-beige、morandi-blue、morandi-green などの落ち着いた色調パレットを提供している。アニメーション設定では accordion-down / accordion-up のカスタムアニメーションと、tailwindcss-animate プラグインによるトランジション効果を実装している。
javascript1// tailwind.config.js の主要なカラーパレット定義 2colors: { 3 primary: { '50': '#f8f9fa', ..., '900': '#212529' }, 4 morandi: { 5 gray: { '100': '#f5f5f5', '200': '#e5e5e5', ... }, 6 beige: { '100': '#faf8f5', '200': '#f0ebe3', ... }, 7 blue: { '500': '#7c9eb2', '600': '#5a7a8c', ... }, 8 green: { '500': '#8faa8f', '600': '#6b8e6b', ... } 9 } 10}
TypeScript型システム
TypeScriptによる厳格な型定義は src/types/index.ts:2-99 で集中管理されている。主要な型定義には、WritingTool(ライティングツール)、LevelProgress(進捗管理)、DailyChallenge(毎日の課題)、Achievement(実績)、HabitTracker(習慣追跡)などが含まれる。特に WritingTool 型は、ツールの階層構造(subTools)、アンロック条件(unlockConditions)、理解度テスト(comprehensionTest)を含む複雑な構造を持つ。
状態管理とデータフローアーキテクチャ
グローバル状態管理
Zustandを用いたグローバル状態管理は src/lib/store.ts:6-45 で実装されている。AppState インターフェースは以下の主要な状態カテゴリを定義している:
- 学生進捗管理:
progress、setProgress、completeLevel、unlockNextLevel、passTest - AI設定:
aiConfig、setAIConfig、setAvailableModels - 作文管理:
essays、addEssay、updateEssay、deleteEssay、addEssayVersion、updateEssayVersion - 習慣追跡:
setDailyChallenge、updateHabitTracker、addAchievement - ツール習熟度:
updateToolMastery
typescript1// src/lib/store.ts の主要インターフェース構造 2interface AppState { 3 // 学生進捗 4 progress: StudentProgress; 5 setProgress: (progress: StudentProgress) => void; 6 completeLevel: (toolId: string, score: number) => void; 7 passTest: (toolId: string) => void; 8 9 // 作文管理 10 essays: Essay[]; 11 addEssay: (essay: Omit<Essay, 'id' | 'createdAt'>) => string; 12 addEssayVersion: (essayId: string, content: string, feedback?: string, ...) => void; 13 14 // 習慣追跡 15 setDailyChallenge: (challenge: DailyChallenge) => void; 16 addAchievement: (achievement: Omit<Achievement, 'id' | 'earnedAt'>) => void; 17}
通知コンテキストシステム
Context APIによる通知システムは src/contexts/NotificationContext.tsx:14-54 で実装されている。NotificationProvider コンポーネントは3種類の通知メソッド(showSuccess、showError、showWarning)を提供し、通知の種類に応じた自動非表示機能(duration パラメータ)を実装している。通知UIは固定位置(fixed top-4 right-4 z-50)で表示され、複数通知のスタック表示に対応している。
typescript1// 通知コンテキストの使用例 2const { showSuccess, showError, showWarning } = useNotificationContext(); 3 4showSuccess('操作が完了しました', 3000); // 3秒後に自動非表示 5showError('エラーが発生しました');
データフロー図
正在加载图表渲染器...
図の説明:
- UI層のコンポーネントは状態管理層のStoreとContextに依存
- カスタムフックはStoreを通じてグローバル状態を更新
- データ層の型定義がすべての層で共有される依存関係を示す
- 矢印は依存の方向(データフローではない)を表現
コンポーネント設計とUI構造
機能別コンポーネント分割
コンポーネントアーキテクチャは機能単位で明確に分割されている。ToolCard コンポーネントは src/components/ToolCard.tsx:1-39 で定義され、ツールの状態(isUnlocked、isCompleted)に応じた視覚的フィードバックを提供する。完了状態では緑のグラデーション背景、アンロック状態では青のボーダー、ロック状態ではグレーアウト表示を実装している。
MediaInput コンポーネントは src/components/MediaInput.tsx:1-60 で、画像キャプチャと音声録音の統合インターフェースを提供する。AudioCaptureResult インターフェースは音声データとトランスクリプト結果をカプセル化し、非同期処理(onImageCapture、onAudioCapture)による親コンポーネントとの連携を実現している。
カスタムフックによるロジック再利用
useVoiceRecorder フックは src/hooks/useVoiceRecorder.ts:3-176 で、セグメント化された音声録音機能を実装している。主要な特徴は:
- セグメント録音: 20秒ごとの自動セグメント分割と2秒のオーバーラップ
- 状態管理:
isRecording、isPaused、recordingTime、segmentsの包括的な管理 - MediaRecorder API: 5秒間隔でのデータ保存による信頼性向上
typescript1// useVoiceRecorder のセグメント設定 2const SEGMENT_DURATION = 20000; // 20秒 3const OVERLAP_DURATION = 2000; // 2秒オーバーラップ 4 5interface VoiceSegment { 6 id: string; 7 startTime: number; 8 endTime: number; 9 duration: number; 10 audioBlob: Blob | null; 11 transcript: string; 12 isProcessed: boolean; 13}
useTextMerger フックは src/hooks/useTextMerger.ts:8-164 で、AIを活用したテキスト結合機能を提供する。OpenAI APIとの統合により、音声認識テキストの重複除去と自然な結合を実現している。エラー時は mergeTextSegments 関数へのフォールバック処理を実装し、システムの堅牢性を確保している。
コンポーネント間のデータフロー
正在加载图表渲染器...
図の説明:
- ユーザー操作からストア保存までのエンドツーエンドのフローを示す
- 20秒セグメントと2秒オーバーラップによる連続性確保の仕組み
- AI API失敗時のフォールバック処理による堅牢性確保
ツールシステムと学習コンテンツ構造
DAG構造によるツール依存関係
ツールシステムは src/data/tools.ts:1-850 で定義され、DAG(有向非巡回グラフ)構造による柔軟な依存関係管理を実現している。コメントにある通り、「工具之间的关系是DAG(有向无环图)结构,不是树状结构」として、同一サブツールが複数の親ツールにマウント可能な設計となっている。
トップレベルツール設定は src/lib/tool-config.ts:1-85 で管理され、8つのカテゴリ(作文步骤、思路整理法、框架搭建法、表达美化技能、深度思考能力、文章润色技能、方法组合工具、最后检查工具)に分類されている。subToolToParentMap による逆引きマッピングで、サブツールから親ツールへの効率的なアクセスを実現している。
typescript1// src/lib/tool-config.ts のツール分類構造 2export const topLevelToolsConfig = [ 3 { 4 id: 'writing-steps', 5 name: '作文步骤', 6 icon: 'FileText', 7 subTools: ['tool-1', 'tool-4', 'tool-6', ...] 8 }, 9 { 10 id: 'tool-40', 11 name: '思路整理法', 12 icon: 'Brain', 13 subTools: ['tool-7', 'tool-8', 'tool-21'] 14 }, 15 // ... 8つのカテゴリ 16];
アンロック条件と学習進捗制御
各ツールは unlockConditions プロパティにより段階的なアンロック機構を実装している。src/types/index.ts:27-40 で定義される条件には以下が含まれる:
- 前提ツール要件 (
prerequisiteTools): 特定ツールの完了が必要 - 最低習熟度 (
minMasteryLevel): 0-100の習熟度スコア - 練習回数 (
minPracticeCount): 最小練習回数 - 連続執筆日数 (
minWritingStreak): 習慣形成の促進 - パスワード (
password): 教師による制御可能なアンロック
ツールの利用可能性判定は src/app/page.tsx:21-69 の getAvailableToolsForChallenge 関数で実装されている。free-writing ツールは常に利用可能とし、その他は testPassed ステータスに基づいて判定する。
typescript1// src/app/page.tsx のツール可用性判定 2const getAvailableToolsForChallenge = () => { 3 return writingTools.filter(tool => { 4 if (tool.id === 'free-writing') return true; 5 const level = progress.levels.find(l => l.toolId === tool.id); 6 return !!level?.testPassed; 7 }); 8};
デイリーチャレンジ生成システム
デイリーチャレンジは src/app/page.tsx:31-44 の generateDailyChallenge 関数で動的に生成される。利用可能なツールからランダムに選択し、ツールの exercises 配列から課題を抽出する。連続記録(streak)は前回のチャレンジから継承され、習慣形成を促進する設計となっている。
チャレンジ完了時の処理は src/app/page.tsx:47-69 で実装され、連続日数に応じた実績アンロック(1日目「写作新手」、7日目「周周坚持」など)を実行する。
ユーティリティとインフラストラクチャ
共通ユーティリティ関数
src/lib/utils.ts:3-18 では、cn 関数(クラス名結合)と getActualEndpoint 関数(API エンドポイント正規化)を提供している。getActualEndpoint は、ベースURLのプロトコル追加(https://)とパス正規化(/v1 サフィックス)を自動処理し、AI API設定の柔軟性を確保している。
typescript1// src/lib/utils.ts のエンドポイント正規化 2export const getActualEndpoint = (baseURL?: string): string => { 3 if (!baseURL) return 'https://api.openai.com/v1'; 4 let url = baseURL.trim(); 5 if (!/^https?:\/\//i.test(url)) { 6 url = 'https://' + url; 7 } 8 if (!/\/v1\/?$/.test(url)) { 9 url = url.endsWith('/') ? url + 'v1' : url + '/v1'; 10 } 11 return url; 12};
エラーハンドリングと404ページ
src/app/not-found.tsx:1-33 では、カスタム404ページを実装している。モランディカラーのグラデーション背景とカードベースのUIで、ユーザーフレンドリーなエラー体験を提供する。「返回首页」ボタンによるホームへのナビゲーションを実装している。
CSS処理パイプライン
postcss.config.js:1-6 では、Tailwind CSSとAutoprefixerによるCSS処理パイプラインを定義している。シンプルな構成ながら、クロスブラウザ互換性と最新CSS機能の利用を可能にしている。
モジュール依存関係
正在加载图表渲染器...
図の説明:
- アプリケーション層からデータ層への依存の方向性を示す
types/index.tsがすべてのモジュールから参照される共通型定義- ContextとStoreによる状態管理の中核的な役割を可視化
設計上の重要な決定事項
アーキテクチャパターンの選択理由
-
Zustand vs Redux: 軽量なZustandを選択し、ボイラープレートコードを削減。学習プラットフォームとしての要件(進捗管理、設定管理)に対して十分な機能を提供
-
App Router採用: Next.js 13以降のApp Routerにより、サーバーコンポーネントとクライアントコンポーネントの適切な分離を実現。SEO対策とパフォーマンス最適化を両立
-
DAG構造のツール依存: ツール間の柔軟な関係性を表現するため、ツリー構造ではなくDAGを採用。同一ツールの複数カテゴリへの所属を可能にし、学習コンテンツの再利用性を向上
-
セグメント化音声録音: 長時間録音の信頼性確保とAI処理の効率化のため、20秒セグメント+2秒オーバーラップの設計を採用
技術選定の根拠
| 技術 | 用途 | 選定理由 | 代替案 |
|---|---|---|---|
| Next.js | フレームワーク | App Router、SSR、Vercel統合 | Remix, Nuxt |
| Zustand | 状態管理 | 軽量、TypeScript親和性、シンプルなAPI | Redux, Jotai |
| Tailwind CSS | スタイリング | ユーティリティファースト、カスタマイズ性 | CSS Modules, Styled Components |
| TypeScript | 型システム | 型安全性、IDE支援、リファクタリング容易性 | JavaScript, Flow |
| Mermaid | ドキュメント図 | Markdown統合、バージョン管理容易 | PlantUML, Draw.io |
| MediaRecorder API | 音声録音 | ブラウザ標準、セグメント録音対応 | Web Audio API直接使用 |
既知の制約事項
-
画像最適化無効化: Vercelデプロイ時の互換性確保のため
images.unoptimized: true設定が必要。パフォーマンスへの影響は軽微だが、将来的な最適化の余地あり -
クライアントサイドAI処理: テキスト結合処理がクライアントサイドで実行されるため、APIキーの安全な管理とレート制限への対応が必要
-
ブラウザ互換性: MediaRecorder APIのブラウザサポートに依存するため、古いブラウザではフォールバック機能の実装が必要
セキュリティ考慮事項
AI APIキーは aiConfig としてクライアントサイドで管理されている。本番環境では、APIルート経由でのプロキシ実装により、APIキーのサーバーサイド管理への移行が推奨される。現在の実装はプロトタイプ/教育用途を想定しており、本格的な商用展開にはセキュリティ強化が必要である。
