import文を書き続けるClaude Codeを止める──Nuxt.js開発でCLAUDE.mdが必須な理由

はじめに

Claude CodeでNuxt.jsのコンポーネントを書かせると、import { ref } from 'vue'が毎回追加される。

$fetchとuseFetchの混同

サーバールートのNext.js的な書き方

Next.jsのpages/api/に慣れていると、export default function handler(req, res)という形式のコードをpages/api/に置いてしまう。Nuxtではこの形式は動かない。server/api/に配置し、ハンドラーはdefineEventHandlerで書く。

// ✅ Nuxt 3の正しいサーバールート
// server/api/hello.get.ts → GET /api/hello
export default defineEventHandler(async (event) => {
  const query = getQuery(event)
  return { message: 'Hello', query }
})

HTTPメソッド別にファイル名でルーティングする(hello.get.tshello.post.ts)。


Nuxt.js向けCLAUDE.md完全テンプレート

# CLAUDE.md - Nuxt 3(TypeScript strict / Pinia + useState / Tailwind / pnpm)

Auto-imports(必読)

Vue API(ref, computed, watch等)とNuxt API(useFetch, useState, useRouter等)およびcomponents/, composables/, utils/配下は自動インポート。import文は書かない。 明示インポートが必要な場合のみ import { xxx } from '#imports'

データ取得

  • 初期データ: await useFetch('/api/xxx')
  • ユーザー操作起因のみ: $fetch('/api/xxx', { method: 'POST', body: {} })
  • setup内での await $fetch() 直接利用は禁止
  • サーバールート(Nitro / h3)

  • server/api/xxx.get.ts → GET /api/xxx
  • export default defineEventHandler(async (event) => { ... })
  • export default function handler(req, res) はNext.js形式。禁止
  • 状態管理

  • ローカル状態: ref() / reactive()
  • コンポーネント間の共有状態: useState('key', () => initialValue)(SSRセーフ)
  • export const state = ref() をcomposablesでexportすることは禁止(リクエスト間リーク)
  • 複雑な状態(actions/getters必要): Pinia
  • composablesでモジュールレベルのrefをexportすると、SSR時にリクエスト間で状態が共有されメモリリークになる。


    PostToolUseフック──自動インポート違反を検出する

    #!/bin/bash
    # .claude/hooks/check-nuxt-imports.sh
    FILE=$(python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('tool_input',{}).get('file_path',''))")
    [[ "$FILE" != *.vue ]] && [[ "$FILE" != *.ts ]] && exit 0
    for p in "import { ref } from 'vue'" "import { useFetch } from '#app'" "import { useRouter } from 'vue-router'"; do
      grep -q "$p" "$FILE" && echo "⚠️  Nuxt自動インポート違反: ${p} は不要"
    done

    .claude/settings.jsonに追加する。

    {
      "hooks": {
        "PostToolUse": [{ "matcher": "Edit|Write", "hooks": [{ "type": "command", "command": "bash .claude/hooks/check-nuxt-imports.sh" }] }]
      }
    }

    Claude Codeが余分なimport文を追加するたびに即座に警告が出て、違反を人間のレビュー待ちなしに修正できる。


    EM視点──Next.jsとの選定基準とCLAUDE.md展開戦略

    NuxtとNext.jsの選定はチームスキルとプロジェクト特性で決まる。Vue.js経験者が中心のチームでコンテンツサイトを構築するならNuxtの方が開発速度が出る。大規模SaaSでReactエコシステムを使い続けたいチームはNext.jsを選ぶことになる。

    CLAUDE.mdはテックリードが本記事のテンプレートをベースに固有ルールを追加し、1〜2名でパイロット運用後にリポジトリにコミットする。Nuxt UIを使っているプロジェクトには公式でClaude Code向けスキルが提供されており(ui.nuxt.com/docs/getting-started/ai/skills)、組み合わせるとコンポーネント生成の精度が上がる。


    まとめ

    import { ref } from 'vue'が出てくる根本原因は、Nuxtの自動インポート設計がCLAUDE.mdで伝わっていないことだ。「Vue APIはimport不要」「setup内での$fetch直接利用禁止」「サーバールートはserver/api/に書く」の3行を追記してほしい。テンプレートをリポジトリにコミットすれば、チーム全員が規約に沿ったコードをClaude Codeで生成できる。

    コメント

    タイトルとURLをコピーしました