はじめに
「Claude CodeにNext.jsのコンポーネントを生成させると、なぜか全部にuse clientが付いてくる」という経験がある人は多いはずだ。App Routerが登場して以来、Server ComponentsとClient Componentsの使い分けは現代のNext.js開発における核心的な設計判断になった。ところがClaude Codeは指示がないと旧パターンを選びやすく、気づかずに使い続けるとパフォーマンスとセキュリティの両方に問題が出る。
App RouterでClaude Codeが間違えやすい3つのパターン
use clientの過剰追加
Claude Codeはデフォルトでuse clientを多用する。その結果、Server Componentで動かすべきデータ取得コンポーネントがクライアント側に移動し、不要なバンドルサイズとウォーターフォールが生まれる。
// Claude Codeが出しやすい旧パターン(use client + useEffectでfetch)
"use client"
import { useEffect, useState } from "react"
export default function ProductList() {
const [products, setProducts] = useState([])
useEffect(() => {
fetch("/api/products").then(r => r.json()).then(setProducts)
}, [])
return
{products.map(p => - {p.name}
)}
}
// 正しいパターン(Server Componentで直接DB取得)
import { db } from "@/lib/db"
export default async function ProductList() {
const products = await db.query.products.findMany()
return
{products.map(p => - {p.name}
)}
}
use clientもAPIルートも不要だ。CLAUDE.mdに「デフォルトはServer Component」「use clientは葉ノードのインタラクティブ要素のみ」と書くだけで、この誤りが出なくなる。
APIルートとServer Actionsの混用
フォーム送信や更新処理にServer Actionsを使うのがApp Routerの現代的なパターンだが、指示がなければClaude Codeは従来型の/api/route.tsを生成しやすい。
// 旧パターン(app/api/todos/route.ts)
export async function POST(req: Request) {
const { title } = await req.json()
await db.insert(todos).values({ title })
return Response.json({ success: true })
}
// Server Actionsパターン(app/actions.ts)
"use server"
import { auth } from "@clerk/nextjs/server"
export async function createTodo(title: string) {
const { userId } = await auth()
if (!userId) throw new Error("Unauthorized")
await db.insert(todos).values({ title, userId })
}
Server ActionはUIコンポーネントのすぐそばにコロケーションできる。APIルートはWebhook受信や外部サービス連携だけに絞るとアーキテクチャが整理される。
キャッシング戦略の無指定
App Routerのデフォルトは静的レンダリングで、Claude Codeはキャッシング指定を省略しやすい。ユーザー固有データが静的キャッシュに載るとセキュリティリスクになるため、cache: 'no-store'を明示する。
const res = await fetch(/api/users/${userId}, { cache: 'no-store' })
CLAUDE.mdでApp Routerのルールを明文化する
# Next.js App Router プロジェクト
技術スタック
Next.js 15 / TypeScript / Tailwind CSS + shadcn/ui / Drizzle ORM + Neon / Clerk
コンポーネント設計
- デフォルト: Server Component(use clientなし)
- use clientは useState/useEffect/onClick が必要な葉ノードのみ
- データ取得はServer Componentで直接DBクエリを実行
データ取得 & キャッシング
- 静的コンテンツ: デフォルト(指定不要)
- 定期更新コンテンツ: export const revalidate = 60
- ユーザー固有データ: cache: 'no-store' を必ず指定
サーバー処理
- ミューテーションはServer Actions(use server)を使う
- APIルート(/api/)はWebhook・外部サービス連携のみ
- Server Action冒頭では必ず auth() で認証・userId検証
禁止パターン
- Server Componentに use client を不要につける
- Client Componentから直接DBアクセス
- Server Actionで認証チェックを省略
- ユーザー固有データに cache: 'no-store' を付けない
このCLAUDE.mdをリポジトリにコミットすれば、チーム全員が同じルールでClaude Codeを使える。App RouterのServer/Client Componentは入門者が特に混乱しやすいので、CLAUDE.mdに書いておくとオンボーディングでもそのまま使える。
実践:2時間SaaS構築の内訳(指示1時間45分・実装15分)
Qiita(kawabe0201, 2026年)に、Next.js 15 + Clerk + Neon + DrizzleでメモアプリSaaSを2時間で構築した記録がある(単一の実践報告として参考にしてほしい)。
| 作業 | 時間 |
|---|---|
| CLAUDE.md作成・指示設計 | 1時間45分 |
| 実際のコード実装 | 15分 |
「コードを書く時間より指示を設計する時間のほうが長い」という逆転が起きている。この事例はClaude Code活用の「指示が9割」という感覚を数字で示している。
実際の作業で押さえておくと良いワークフローを紹介する。
/initコマンド: 既存コードを分析してCLAUDE.md草案を自動生成(公式確認済み)。ゼロから書かずに済む。- Planモード(Shift+Tab): 「UserDashboardをServer ComponentでDB取得し、Clientのチャートへpropsで渡す設計で」と伝えると、ファイル構成とコンポーネント分割計画を先に出してくれる。承認してから実装に入れる。
@ファイルパス参照: 「@app/todos/page.tsxと同じパターンでapp/notes/page.tsxを作って」と伝えると既存コードをベースに一貫したコードが出る。
EM視点──チームのApp Router開発を整える
Claude Codeが生成したコードのレビューは「アーキテクチャの選択が正しいか」を先に見ると効率的だ。
use clientが本当に必要な場所だけについているか- Server Actionの冒頭に認証チェックがあるか
- ユーザー固有データに
cache: 'no-store'が付いているか
CLAUDE.mdにこれらを明記しておけば、Claude Code自身が誤りを避けるようになりレビューコストも下がる。
まとめ
use clientの過剰追加、APIルートとServer Actionsの混用、キャッシング無指定。この3パターンはCLAUDE.mdの設定で防げる。最初に/initでCLAUDE.md草案を生成して、本記事のテンプレートを参考に「コンポーネント設計」「キャッシング戦略」「禁止パターン」を追記するところから始めてほしい。

コメント