SKILL.md
アーキテクチャガードスキル
プロジェクト構造規約
Next.js App Router構成(推奨)
src/
├── app/ # ルーティング(App Router)
│ ├── (auth)/ # 認証が必要なルートグループ
│ │ ├── dashboard/
│ │ └── settings/
│ ├── (public)/ # 公開ルートグループ
│ │ ├── login/
│ │ └── register/
│ ├── api/ # API Routes
│ │ └── users/
│ │ └── route.ts
│ ├── layout.tsx # ルートレイアウト
│ └── page.tsx # トップページ
├── components/
│ ├── ui/ # 汎用UI(Button, Input等)
│ ├── features/ # 機能別コンポーネント
│ │ └── auth/
│ │ ├── LoginForm.tsx
│ │ └── index.ts
│ └── layouts/ # レイアウトコンポーネント
├── lib/ # ユーティリティ、設定、クライアント
│ ├── utils.ts
│ ├── prisma.ts
│ └── auth.ts
├── hooks/ # カスタムフック
│ └── useAuth.ts
├── services/ # APIクライアント、外部サービス連携
│ └── userService.ts
├── types/ # 型定義
│ └── user.ts
├── constants/ # 定数
│ └── routes.ts
└── styles/ # グローバルスタイル
└── globals.css
依存関係ルール(レイヤードアーキテクチャ)
依存の方向(上から下のみ許可)
app/
↓
components/
↓
hooks/
↓
services/
↓
lib/
↓
types/ & constants/
禁止される依存パターン
# 1. components/ → app/ への逆依存
grep -rn "from ['\"]@/app" src/components/ --include="*.ts" --include="*.tsx"
# 2. services/ → components/ への逆依存
grep -rn "from ['\"]@/components" src/services/ --include="*.ts"
# 3. lib/ → services/ への逆依存
grep -rn "from ['\"]@/services" src/lib/ --include="*.ts"
# 4. hooks/ → components/ への逆依存
grep -rn "from ['\"]@/components" src/hooks/ --include="*.ts"
コンポーネント設計規約
Container/Presentationalパターン
features/
└── user-profile/
├── UserProfileContainer.tsx # データ取得、状態管理
├── UserProfileView.tsx # 純粋なUI(props only)
├── useUserProfile.ts # カスタムフック
├── types.ts # 型定義
└── index.ts # 公開API(re-export)
index.ts の書き方
// features/user-profile/index.ts
export { UserProfileContainer as UserProfile } from './UserProfileContainer';
export type { UserProfileProps } from './types';
禁止パターン
1. UIコンポーネント内でのAPI呼び出し
// ❌ Bad: UIコンポーネント内でfetch
export function UserCard({ userId }: Props) {
const [user, setUser] = useState(null);
useEffect(() => {
fetch(`/api/users/${userId}`).then(/* ... */);
}, [userId]);
return <div>{user?.name}</div>;
}
// ✅ Good: カスタムフックに分離
export function UserCard({ userId }: Props) {
const { user, isLoading } = useUser(userId);
return <div>{user?.name}</div>;
}
2. 巨大ファイル(300行超)
# 検出コマンド
find src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 300 {print}'
3. 循環依存
# 検出コマンド
npx madge --circular src/
4. 未使用エクスポート
# 検出コマンド
npx ts-prune
5. 深いインポートパス
// ❌ Bad: 深い相対パス
import { Button } from '../../../components/ui/Button';
// ✅ Good: エイリアス使用
import { Button } from '@/components/ui/Button';
新機能追加時のガイドライン
Q: 新しいページを追加する場合
A: src/app/ 配下に配置
- 認証が必要:
src/app/(auth)/[page-name]/page.tsx - 公開ページ:
src/app/(public)/[page-name]/page.tsx
Q: 新しいコンポーネントを追加する場合
A: 用途に応じて配置
- 汎用UI:
src/components/ui/[ComponentName].tsx - 機能固有:
src/components/features/[feature-name]/ - レイアウト:
src/components/layouts/[LayoutName].tsx
Q: 新しいAPIを追加する場合
A: src/app/api/ 配下に配置
- REST規約に従う:
src/app/api/[resource]/route.ts - 動的パラメータ:
src/app/api/[resource]/[id]/route.ts
Q: 新しいフックを追加する場合
A: src/hooks/ に配置
- 命名:
use[PascalCase].ts - 例:
useAuth.ts,useLocalStorage.ts
Q: 新しい型定義を追加する場合
A: src/types/ に配置
- ドメインごとにファイル分割:
user.ts,product.ts - 共通型:
common.ts
違反検出コマンド集
# 全チェック実行
echo "=== 依存関係チェック ==="
grep -rn "from ['\"]@/app" src/components/ --include="*.ts" --include="*.tsx" || echo "OK: components → app 違反なし"
grep -rn "from ['\"]@/components" src/services/ --include="*.ts" || echo "OK: services → components 違反なし"
echo "=== ファイルサイズチェック ==="
find src -name "*.tsx" -o -name "*.ts" | xargs wc -l | awk '$1 > 300 {print "WARNING:", $2, "is", $1, "lines"}'
echo "=== 循環依存チェック ==="
npx madge --circular src/ 2>/dev/null || echo "madgeが未インストール"
echo "=== 未使用エクスポートチェック ==="
npx ts-prune 2>/dev/null | head -20 || echo "ts-pruneが未インストール"
出力フォーマット
## アーキテクチャ監査結果
### ✅ 準拠項目
- ディレクトリ構造: OK
- レイヤー依存関係: OK
- ファイルサイズ: OK
### ❌ 違反項目
| ファイル | 違反タイプ | 詳細 | 修正案 |
|---------|-----------|------|--------|
| UserProfile.tsx | サイズ超過 | 450行 | Container/View分割 |
| api.ts → Button | 逆依存 | services→components | インターフェース抽出 |
| A → B → A | 循環依存 | 相互参照 | 共通モジュール抽出 |
### 📝 推奨アクション
1. UserProfile.tsx を分割(優先度: 高)
2. 循環依存を解消(優先度: 高)
3. 未使用エクスポートを削除(優先度: 中)
リファクタリングパターン
巨大ファイルの分割
// Before: 1ファイル400行
// UserProfile.tsx (400行)
// After: 3ファイルに分割
// UserProfileContainer.tsx (80行) - データ取得
// UserProfileView.tsx (150行) - UI
// useUserProfile.ts (50行) - ロジック
// types.ts (20行) - 型定義
循環依存の解消
// Before: A → B → A の循環
// moduleA.ts imports from moduleB.ts
// moduleB.ts imports from moduleA.ts
// After: 共通モジュール抽出
// common.ts (共通の型・関数)
// moduleA.ts imports from common.ts
// moduleB.ts imports from common.ts