nuxt-core について
Nuxt 4アプリケーションを開発する人向けの基礎ガイドです。プロジェクト構成、設定、ルーティング、SEO、エラー処理に加え、詳細資料や一般的な問題の解決方法も案内します。
主な機能
- 01Nuxt 4のプロジェクト構成と設定
- 02ファイルベースのルーティングとミドルウェア
- 03ページSEOとメタデータ
- 04ランタイム設定の管理
- 05エラー処理とトラブルシューティング
活用シーン
- 01Nuxt 4プロジェクトのセットアップ
- 02動的ルートとアクセス制御の実装
- 03ページの検索メタデータ設定
- 04ビルドとルーティングの問題解決
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill nuxt-coreインストール後、Claude Code で/nuxt-coreを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
templates/app.vueinit-nuxt-v4.shnuxt.config.ts詳細
Nuxt 4 のコア基礎
Nuxt 4 アプリケーションのプロジェクト設定、構成、ルーティング、SEO、エラー処理について説明します。
クイックリファレンス
バージョン要件
| パッケージ | 最小バージョン | 推奨バージョン |
|---|---|---|
| nuxt | 4.0.0 | 4.2.x |
| vue | 3.5.0 | 3.5.x |
| nitro | 2.10.0 | 2.12.x |
| vite | 6.0.0 | 6.2.x |
| typescript | 5.0.0 | 5.x |
主なコマンド
# Create new project
bunx nuxi@latest init my-app
# Development
bun run dev
# Build for production
bun run build
# Preview production build
bun run preview
# Type checking
bun run postinstall # Generates .nuxt directory
bunx nuxi typecheck
# Add a page/component/composable
bunx nuxi add page about
bunx nuxi add component MyButton
bunx nuxi add composable useAuth
安全なインストール
bunx nuxi init のようなスキャフォールディングツールは、リモートコードをダウンロードして実行します。実行する前に、サプライチェーンセキュリティのベストプラクティスに従ってください。
- インストール後のスクリプトをブロックする —
npm config set ignore-scripts true(Bun の場合はデフォルトで無効) - クールダウン期間を設ける — 新しいパッケージバージョンがコミュニティによって審査されるまで、7 日間待ちます
- インストール前に監査する —
socket package score npm <pkg>を実行するか、socket npm install <pkg>を使用してパッケージを確認します
Socket CLI との統合、クールダウンの設定、ロックファイルの検証、CI による適用など、セキュリティ設定の詳細については、dependency-upgrade スキルを読み込んでください。
ディレクトリ構成(Nuxt v4)
my-nuxt-app/
├── app/ # Default srcDir in v4
│ ├── assets/ # Build-processed assets (CSS, images)
│ ├── components/ # Auto-imported Vue components
│ ├── composables/ # Auto-imported composables
│ ├── layouts/ # Layout components
│ ├── middleware/ # Route middleware
│ ├── pages/ # File-based routing
│ ├── plugins/ # Nuxt plugins
│ ├── utils/ # Auto-imported utility functions
│ ├── app.vue # Main app component
│ ├── app.config.ts # App-level runtime config
│ ├── error.vue # Error page component
│ └── router.options.ts # Router configuration
│
├── server/ # Server-side code (Nitro)
│ ├── api/ # API endpoints
│ ├── middleware/ # Server middleware
│ ├── plugins/ # Nitro plugins
│ ├── routes/ # Server routes
│ └── utils/ # Server utilities
│
├── public/ # Static assets (served from root)
├── shared/ # Shared code (app + server)
├── content/ # Nuxt Content files (if using)
├── layers/ # Nuxt layers
├── modules/ # Local modules
├── .nuxt/ # Generated files (git ignored)
├── .output/ # Build output (git ignored)
├── nuxt.config.ts # Nuxt configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Dependencies
v4 の主な変更点:app/ ディレクトリがデフォルトの srcDir になりました。アプリのコードはすべて app/ に配置し、サーバーのコードは引き続き server/ に配置します。
リファレンスを読み込むタイミング
次の場合は references/configuration-deep.md を読み込んでください。
- 高度な nuxt.config.ts オプションを設定する場合
- モジュールやプラグインをセットアップする場合
- Vite または Nitro の構成をカスタマイズする場合
- 実験的な機能を設定する場合
次の場合は references/routing-advanced.md を読み込んでください。
- 複雑なルーティングパターンを実装する場合
- 認証を伴うルートミドルウェアを作成する場合
- キャッチオールルートやオプションのパラメーターを使用する場合
- ルーターのオプションを設定する場合
次の場合は references/plugins-architecture.md を読み込んでください。
- Nuxt プラグインを作成する場合
- グローバルユーティリティやコンポーザブルを注入する場合
- サードパーティーライブラリを統合する場合
- プラグインの実行順序を理解する場合
構成
基本的な nuxt.config.ts
export default defineNuxtConfig({
// Enable Nuxt 4 features
future: {
compatibilityVersion: 4
},
// Development tools
devtools: { enabled: true },
// Modules
modules: [
'@nuxt/ui',
'@nuxt/content',
'@nuxt/image'
],
// Runtime config (environment variables)
runtimeConfig: {
// Server-only (not exposed to client)
apiSecret: process.env.API_SECRET,
databaseUrl: process.env.DATABASE_URL,
// Public (client + server)
public: {
apiBase: process.env.API_BASE || 'https://api.example.com',
appName: 'My App'
}
},
// App config
app: {
head: {
title: 'My Nuxt App',
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
]
}
},
// Nitro config (server)
nitro: {
preset: 'cloudflare-pages'
},
// TypeScript
typescript: {
strict: true,
typeCheck: true
}
})
ランタイム設定の使用
// In composables or components
const config = useRuntimeConfig()
// Public values (client + server)
const apiBase = config.public.apiBase
// Server-only values (only in server/)
const apiSecret = config.apiSecret // undefined on client!
重要なルール:本番環境の環境変数には、process.env ではなく必ず useRuntimeConfig() を使用してください。
アプリ設定とランタイム設定の比較
| 特徴 | アプリ設定 | ランタイム設定 |
|---|---|---|
| 場所 | app.config.ts | nuxt.config.ts |
| ホットリロード | あり | なし |
| シークレット | なし | あり(サーバーのみ) |
| 用途 | UI 設定、テーマ | API キー、URL |
// app/app.config.ts - UI settings (hot-reloadable)
export default defineAppConfig({
theme: {
primaryColor: '#3490dc'
},
ui: {
rounded: 'lg'
}
})
// Usage
const appConfig = useAppConfig()
const color = appConfig.theme.primaryColor
ルーティング
ファイルベースルーティング
app/pages/
├── index.vue → /
├── about.vue → /about
├── users/
│ ├── index.vue → /users
│ └── [id].vue → /users/:id
└── blog/
├── index.vue → /blog
├── [slug].vue → /blog/:slug
└── [...slug].vue → /blog/* (catch-all)
動的ルート
<script setup lang="ts">
const route = useRoute()
// Get route params
const userId = route.params.id
// Reactive (updates when route changes)
const userId = computed(() => route.params.id)
// Fetch user data
const { data: user } = await useFetch(`/api/users/${userId.value}`)
</script>
<template>
<div>
<h1>{{ user?.name }}</h1>
</div>
</template>
ナビゲーション
<script setup>
const goToUser = (id: string) => {
navigateTo(`/users/${id}`)
}
const goBack = () => {
navigateTo(-1) // Go back in history
}
// With options
const goToLogin = () => {
navigateTo('/login', {
replace: true, // Replace current history entry
external: false // Internal navigation
})
}
</script>
<template>
<NuxtLink to="/about">About</NuxtLink>
<NuxtLink :to="`/users/${user.id}`">View User</NuxtLink>
<NuxtLink to="/dashboard" prefetch>Dashboard</NuxtLink>
<NuxtLink to="/admin" :prefetch="false">Admin</NuxtLink>
</template>
ルートミドルウェア
// app/middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
グローバルミドルウェア
// app/middleware/analytics.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
// Runs on every route change
if (import.meta.client) {
window.gtag?.('event', 'page_view', {
page_path: to.path
})
}
})
ページメタデータ
<script setup lang="ts">
definePageMeta({
title: 'Dashboard',
middleware: ['auth'],
layout: 'admin',
pageTransition: { name: 'fade' },
keepalive: true
})
</script>
SEO とメタタグ
useSeoMeta(推奨)
<script setup lang="ts">
useSeoMeta({
title: 'My Page Title',
description: 'Page description for search engines',
ogTitle: 'My Page Title',
ogDescription: 'Page description',
ogImage: 'https://example.com/og-image.jpg',
ogUrl: 'https://example.com/my-page',
twitterCard: 'summary_large_image',
twitterTitle: 'My Page Title',
twitterDescription: 'Page description',
twitterImage: 'https://example.com/og-image.jpg'
})
</script>
useHead(より細かく制御)
<script setup lang="ts">
useHead({
title: 'My Page Title',
meta: [
{ name: 'description', content: 'Page description' },
{ property: 'og:title', content: 'My Page Title' }
],
link: [
{ rel: 'canonical', href: 'https://example.com/my-page' }
],
script: [
{ src: 'https://example.com/script.js', defer: true }
]
})
</script>
動的メタタグ
<script setup lang="ts">
const { data: post } = await useFetch(`/api/posts/${route.params.slug}`)
useSeoMeta({
title: () => post.value?.title,
description: () => post.value?.excerpt,
ogImage: () => post.value?.image
})
</script>
タイトルテンプレート
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
titleTemplate: '%s | My App' // "Page Title | My App"
}
}
})
エラー処理
エラーページ
<script setup lang="ts">
import type { NuxtError } from '#app'
const props = defineProps<{
error: NuxtError
}>()
const handleError = () => {
clearError({ redirect: '/' })
}
</script>
<template>
<div class="error-page">
<h1>{{ error.statusCode }}</h1>
<p>{{ error.message }}</p>
<button @click="handleError">Go Home</button>
</div>
</template>
エラーバウンダリー(コンポーネント単位)
<template>
<NuxtErrorBoundary @error="handleError">
<template #error="{ error, clearError }">
<div class="error-container">
<h2>Something went wrong</h2>
<p>{{ error.message }}</p>
<button @click="clearError">Try again</button>
</div>
</template>
<MyComponent />
</NuxtErrorBoundary>
</template>
<script setup>
const handleError = (error: Error) => {
console.error('Component error:', error)
// Send to error tracking service
}
</script>
エラーのスロー
// In pages or components
throw createError({
statusCode: 404,
statusMessage: 'Page Not Found',
fatal: true // Shows error page, stops rendering
})
// Non-fatal error (shows inline)
throw createError({
statusCode: 400,
message: 'Invalid input'
})
API エラー処理
const { data, error } = await useFetch('/api/users')
if (error.value) {
// Handle error gracefully
showError({
statusCode: error.value.statusCode,
message: error.value.message
})
}
よくあるアンチパターン
ランタイム設定ではなく process.env を使用する
// WRONG - Won't work in production!
const apiUrl = process.env.API_URL
// CORRECT
const config = useRuntimeConfig()
const apiUrl = config.public.apiBase
ミドルウェアガードがない
// WRONG - No return, middleware continues
export default defineNuxtRouteMiddleware((to) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
navigateTo('/login') // Missing return!
}
})
// CORRECT
export default defineNuxtRouteMiddleware((to) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login') // Return stops middleware chain
}
})
リアクティブでないルートパラメーター
// WRONG - Not reactive
const userId = route.params.id
// CORRECT - Reactive
const userId = computed(() => route.params.id)
トラブルシューティング
ビルドエラー/型エラー:
rm -rf .nuxt .output node_modules/.vite && bun install && bun run dev
ルートが見つからない場合:
- ファイルが
app/pages/にあることを確認します(ルート直下のpages/ではありません) - ファイル拡張子が
.vueであることを確認します - 動的パラメーター
[id].vueに誤字がないか確認します
ミドルウェアが実行されない場合:
- グローバルミドルウェアの場合、ファイル名に
.global.tsのサフィックスが付いていることを確認します definePageMeta({ middleware: 'name' })がファイル名と一致していることを確認します- ミドルウェアが
navigateTo()または何も返さないことを確認します
メタタグが更新されない場合:
- リアクティブな値を使用します:
title: () => post.value?.title useSeoMetaが<script setup>内で呼び出されていることを確認します
関連スキル
- nuxt-data:コンポーザブル、データ取得、状態管理
- nuxt-server:サーバールート、API パターン、データベース統合
- nuxt-production:パフォーマンス、テスト、デプロイ
- nuxt-ui-v4:Nuxt UI コンポーネントライブラリ
利用可能なテンプレート
以下については、templates/ ディレクトリをご覧ください。
- 本番環境向けの
nuxt.config.ts - 適切な構造の
app.vue - ミドルウェアの例
バージョン: 4.0.0 | 最終更新日: 2025-12-28 | ライセンス: MIT