nuxt-content について
nuxt-content は、Nuxt プロジェクトでファイルベースのコンテンツを扱うためのスキルです。ブログやドキュメントサイトなどの構築に向け、コレクション、型安全なクエリ、SQL ストレージを案内します。
主な機能
- 01コレクションと検証の設定
- 02型安全なコンテンツクエリ
- 03Markdown、YAML、JSON、CSV の管理
- 04ナビゲーションと全文検索の生成
- 05MDC によるコンポーネント描画
活用シーン
- 01ブログやドキュメントサイトの構築
- 02スキーマによる構造化コンテンツの検証
- 03コンテンツからナビゲーションを生成
- 04コンテンツへの全文検索の追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill nuxt-contentインストール後、Claude Code で/nuxt-contentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/blog-collection.example.tscontent.config.example.tsdocs-collection.example.tsnuxt.config.example.tsreferences/collection-examples.mddeployment-checklists.mderror-catalog.mdmdc-syntax-reference.mdquery-operators.mdstudio-setup-guide.mdscripts/deploy-cloudflare.shdeploy-vercel.shsetup-nuxt-content.shsetup-studio.shtemplates/blog-collection-setup.ts詳細
Nuxt Content v3
ステータス:本番環境で利用可能 最終更新日:2025-01-10 依存関係:なし 最新バージョン:@nuxt/content@^3.0.0, nuxt-studio@^0.1.0-alpha, zod@^4.3.6, valibot@^0.42.0, better-sqlite3@^11.0.0
概要
Nuxt Content v3は、Markdown、YAML、JSON、CSVファイルを通じてコンテンツを管理する、Nuxtプロジェクト向けの強力なGitベースのCMSです。コンテンツファイルを、型安全なクエリ、自動検証、最適なパフォーマンスを実現するSQLベースのストレージを備えた構造化データに変換します。
v3の新機能
主な改善点:
- コンテンツコレクション:型安全なクエリ、自動検証、高度なクエリビルダーを備えた構造化データの整理
- SQLベースのストレージ:本番環境ではSQLを使用し(v2の大きなバンドルサイズを解消)、クエリを最適化し、あらゆる環境(サーバー/サーバーレス/エッジ/静的)に対応
- TypeScriptとの完全な統合:すべてのコレクションとAPIの型を自動生成
- パフォーマンスの強化:アダプターベースのSQLシステムによる超高速なデータ取得
- Nuxt Studioとの統合:GitHub同期に対応した、本番環境でのセルフホスト可能なコンテンツ編集
このスキルを使う場面
以下の場合に、このスキルを使用してください:
- ブログ、ドキュメントサイト、またはコンテンツ中心のアプリケーションを構築するとき
- Markdown、YAML、JSON、CSVファイルでコンテンツを管理するとき
- Gitベースのコンテンツワークフローを実装するとき
- 型安全なコンテンツクエリを作成するとき
- Cloudflare(Pages/Workers)またはVercelにデプロイするとき
- Nuxt Studioを使って本番環境でのコンテンツ編集を設定するとき
- 全文検索で検索可能なコンテンツを構築するとき
- コンテンツ構造からナビゲーションシステムを作成するとき
クイックスタート(10分)
1. Nuxt Contentをインストールする
# Bun (recommended)
bun add @nuxt/content better-sqlite3
# npm
npm install @nuxt/content better-sqlite3
# pnpm
pnpm add @nuxt/content better-sqlite3
これが重要な理由:
@nuxt/contentはCMSのコアモジュールですbetter-sqlite3は最適なパフォーマンスを実現するSQLストレージを提供します- 基本的な使い方では設定は不要です
2. モジュールを登録する
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/content']
})
重要:
- モジュールは
buildModulesではなく、modules配列に追加する必要があります - 基本的な設定に追加の設定は必要ありません
3. 最初のコレクションを作成する
// content.config.ts
import { defineContentConfig, defineCollection } from '@nuxt/content'
import { z } from 'zod'
export default defineContentConfig({
collections: {
content: defineCollection({
type: 'page',
source: '**/*.md',
schema: z.object({
tags: z.array(z.string()).optional(),
date: z.date().optional()
})
})
}
})
コンテンツファイルを作成します:
---
title: Hello World
description: My first Nuxt Content page
tags: ['nuxt', 'content']
---
# Welcome to Nuxt Content v3
This is my first content-driven site!
4. コンテンツをクエリして表示する
<script setup>
const route = useRoute()
const { data: page } = await useAsyncData(route.path, () =>
queryCollection('content').path(route.path).first()
)
</script>
<template>
<ContentRenderer v-if="page" :value="page" />
</template>
完全なテンプレートはこちら:templates/blog-collection-setup.ts
重要なルール
必ず行うこと
- クエリを実行する前に、
content.config.tsでコレクションを定義する - ISO 8601の日付形式を使用する:
2024-01-15または2024-01-15T10:30:00Z content.config.tsを変更した後は開発サーバーを再起動する- 特定のフィールドを選択するには**
.only()を使用する**(パフォーマンス向上) - MDCコンポーネントを
components/content/ディレクトリに配置する - 数値順に並べるにはゼロ埋めしたプレフィックスを使用する:
01-、02- - データベースコネクタをインストールする:
better-sqlite3が必要です - シンタックスハイライトのために、コードブロックに言語を指定する
- 抜粋を区切るために、コンテンツ内で**``を使用する**
- Cloudflareでは、D1のバインディング名を**「DB」にする**(大文字と小文字を区別)
絶対に行わないこと
content.config.tsでコレクションを定義する前にクエリを実行しない- ISO形式以外の日付形式を使用しない(例:「January 15, 2024」)
- 設定変更後に開発サーバーを再起動し忘れない
- 必要なフィールドが一部だけの場合にすべてのフィールドをクエリしない(
.only()を使用する) - コンポーネントを
components/content/以外に配置しない - 1桁のプレフィックスを使用しない(
1-ではなく01-を使用する) - データベースコネクタのインストールを省略しない
- コードフェンス内で言語の指定を忘れない
- ``区切りなしで抜粋が表示されると期待しない
- D1に別のバインディング名を使用しない(「DB」にする必要があります)
コンテンツコレクション
コレクションを定義する
コレクションは、共通の設定を持つ関連コンテンツを整理します:
// content.config.ts
import { defineCollection, defineContentConfig } from '@nuxt/content'
import { z } from 'zod'
export default defineContentConfig({
collections: {
blog: defineCollection({
type: 'page',
source: 'blog/**/*.md',
schema: z.object({
title: z.string(),
date: z.date(),
tags: z.array(z.string()).default([])
})
}),
authors: defineCollection({
type: 'data',
source: 'authors/*.yml',
schema: z.object({
name: z.string(),
bio: z.string()
})
})
}
})
コレクションの種類
Page型(type: 'page')
用途:URLに対応するコンテンツ
機能:
- ファイル構造からパスを自動生成
- 組み込みフィールド:
path、title、description、body、navigation - 最適な用途:ブログ、ドキュメント、マーケティングページ
パスマッピング:
content/index.md → /
content/about.md → /about
content/blog/hello.md → /blog/hello
データ型(type: 'data')
用途:URL を含まない構造化データ
特徴:
- スキーマを完全に制御できます
- パスは自動生成されません
- 次の用途に最適です:著者、製品、設定
スキーマの検証
Zod v4 を使用(推奨)
bun add -D zod@^4.3.6
# or: npm install -D zod@^4.3.6
import { z } from 'zod'
schema: z.object({
title: z.string(),
date: z.date(),
published: z.boolean().default(false),
tags: z.array(z.string()).optional(),
category: z.enum(['news', 'tutorial', 'update'])
})
Valibot を使用(代替)
bun add -D valibot@^0.42.0
# or: npm install -D valibot@^0.42.0
import * as v from 'valibot'
schema: v.object({
title: v.string(),
date: v.date(),
published: v.boolean(false),
tags: v.optional(v.array(v.string()))
})
コンテンツのクエリ
基本的なクエリ
// Get all posts
const posts = await queryCollection('blog').all()
// Get single post by path
const post = await queryCollection('blog').path('/blog/hello').first()
// Get post by ID
const post = await queryCollection('blog').where('_id', '=', 'hello').first()
フィールドの選択
// Select specific fields (performance optimization)
const posts = await queryCollection('blog')
.only(['title', 'description', 'date', 'path'])
.all()
// Exclude fields
const posts = await queryCollection('blog')
.without(['body'])
.all()
条件指定
// Single condition
const posts = await queryCollection('blog')
.where('published', '=', true)
.all()
// Multiple conditions
const posts = await queryCollection('blog')
.where('published', '=', true)
.where('category', '=', 'tutorial')
.all()
// Operators: =, !=, <, <=, >, >=, in, not-in, like
const recent = await queryCollection('blog')
.where('date', '>', new Date('2024-01-01'))
.all()
const tagged = await queryCollection('blog')
.where('tags', 'in', ['nuxt', 'vue'])
.all()
並べ替えとページネーション
// Sort by field
const posts = await queryCollection('blog')
.sort('date', 'DESC')
.all()
// Pagination
const posts = await queryCollection('blog')
.sort('date', 'DESC')
.limit(10)
.offset(0)
.all()
件数の取得
// Count results
const total = await queryCollection('blog')
.where('published', '=', true)
.count()
サーバーサイドクエリ
// server/api/posts.get.ts
export default defineEventHandler(async (event) => {
const posts = await queryCollection('blog')
.where('published', '=', true)
.sort('date', 'DESC')
.all()
return { posts }
})
ナビゲーション
コンテンツ構造からナビゲーションツリーを自動生成します:
const navigation = await queryCollectionNavigation('blog').all()
階層構造を返します:
[
{
title: 'Getting Started',
path: '/docs/getting-started',
children: [{ title: 'Installation', path: '/docs/getting-started/installation' }]
}
]
高度なパターン(フィルター、並べ替え、カスタム構造)については、references/collection-examples.md を参照してください。
MDC 構文(Markdown コンポーネント)
基本的なコンポーネント構文
::my-alert
This is an alert message
::
::my-card
#title
Card Title
#default
Card content here
::
コンポーネント:
<template>
<div class="alert">
<slot />
</div>
</template>
Props
::my-button{href="/docs" type="primary"}
Click me
::
コンポーネント:
<script setup>
defineProps<{
href: string
type: 'primary' | 'secondary'
}>()
</script>
全文検索
// Search across all content
const results = await queryCollectionSearchSections('blog', 'nuxt content')
.where('published', '=', true)
.all()
返される内容:
[
{
id: 'hello',
path: '/blog/hello',
title: 'Hello World',
content: '...matching text...'
}
]
デプロイ
Cloudflare Pages + D1
bun add -D @nuxthub/core
bunx wrangler d1 create nuxt-content
bun run build && bunx wrangler pages deploy dist
wrangler.toml:
[[d1_databases]]
binding = "DB" # Must be exactly "DB" (case-sensitive)
database_name = "nuxt-content"
database_id = "your-database-id"
重要:D1 バインディングの名前は必ず DB にしてください(大文字と小文字を区別します)。
参照先:トラブルシューティングを含む Cloudflare の完全なデプロイガイドについては、references/deployment-checklists.md を参照してください。
Vercel
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/content'],
routeRules: {
'/blog/**': { prerender: true }
}
})
vercel deploy
参照先:Vercel の完全な設定とプリレンダリング戦略については、references/deployment-checklists.md を参照してください。
Nuxt Studio との統合
Studio を有効にする
bun add -D nuxt-studio@alpha
# or: npm install -D nuxt-studio@alpha
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/content', 'nuxt-studio'],
studio: {
enabled: true,
gitInfo: {
name: 'your-name',
email: '[email protected]'
}
}
})
OAuth の設定
- GitHub OAuth App を作成します
- 認可コールバック URL に
https://yourdomain.com/api/__studio/oauth/callbackを設定します - クライアント ID とシークレットを環境変数に追加します
重要:コールバック URL は本番ドメインと完全に一致させる必要があります(https:// を含む)。
特に重要な問題トップ 5
問題 #1:コレクションが見つからない
エラー:Collection 'xyz' not found
解決方法:content.config.ts でコレクションを定義し、開発サーバーを再起動します
rm -rf .nuxt && bun dev
問題 #2:日付の検証に失敗する
エラー:Validation error: Expected date, received string
解決方法:ISO 8601 形式を使用します:
---
date: 2024-01-15 # ✅ Correct
# NOT: "January 15, 2024" # ❌ Wrong
---
問題 #3:D1 バインディングが見つからない(Cloudflare)
エラー:DB is not defined
解決方法:Cloudflare ダッシュボードで、D1 バインディング名を正確に DB に設定してください(大文字と小文字を区別します)。
問題 #4:MDC コンポーネントがレンダリングされない
エラー:コンポーネントがテキストのまま表示される
解決方法:コンポーネント名と完全に一致する名前のファイルを components/content/ に配置します:
::my-alert
Content
::
問題 #5:ナビゲーションが更新されない
エラー:新しいコンテンツがナビゲーションに表示されない
解決方法:.nuxt キャッシュをクリアします:
rm -rf .nuxt && bun dev
18 件すべての問題を見る:references/error-catalog.md
参照ドキュメントを読み込むタイミング
次の場合は references/error-catalog.md を読み込みます:
- 上記のトップ5以外のエラーが発生した場合
- コレクションの検証、スキーマエラー、デプロイの問題をデバッグする場合
- 18件すべての解決方法と情報源を含む、エラーカタログ全体が必要な場合
次の場合は references/collection-examples.md を読み込みます:
- 高度なコレクションタイプ(data と page)をセットアップする場合
- 複雑なスキーマ検証パターンを実装する場合
- Zod v4 または Valibot スキーマの例が必要な場合
- 複数のコレクション設定を扱う場合
次の場合は references/query-operators.md を読み込みます:
- 基本的な例を超える複雑なクエリを作成する場合
- すべての演算子(=、!=、<、>、<=、>=、in、not-in、like)の完全なリファレンスが必要な場合
- ページネーション、ソート、またはフィールド選択を実装する場合
- クエリ構文エラーをトラブルシューティングする場合
次の場合は references/deployment-checklists.md を読み込みます:
- 特定のプラットフォーム(Cloudflare Pages、Cloudflare Workers D1、Vercel)にデプロイする場合
- 本番環境の設定を行う場合
- デプロイ固有のエラー(D1 バインディング、プリレンダリングルート)をトラブルシューティングする場合
- プラットフォーム固有の wrangler.toml または vercel.json の例が必要な場合
次の場合は references/mdc-syntax-reference.md を読み込みます:
- カスタム MDC(Markdown Components)を実装する場合
- コンポーネントのレンダリング問題をデバッグする場合
- props、slots、ネストに関する構文リファレンス全体が必要な場合
- 高度なコンテンツコンポーネントを作成する場合
次の場合は references/studio-setup-guide.md を読み込みます:
- 本番環境でのコンテンツ編集用に Nuxt Studio をセットアップする場合
- GitHub OAuth 認証を設定する場合
- GitHub 同期を使用したセルフホスト可能なコンテンツ編集を有効にする場合
- Studio 認証または Git 同期の問題をトラブルシューティングする場合
テンプレート(templates/):
blog-collection-setup.ts- コレクション、クエリ、ナビゲーション、検索、デプロイを含むブログの完全なセットアップ(334 行)
パフォーマンスのヒント
.only()を使用すると、特定のフィールドを選択できます- 本番環境ではキャッシュを有効にする
- 大規模なコレクションにはページネーションを使用する
- Vercel では静的ルートをプリレンダリングする
- 最適なパフォーマンスのためにSQL ストレージ(better-sqlite3)を使用する
ベストプラクティス
- クエリを実行する前に、必ずコレクションを定義する
- 型安全なクエリには TypeScript を使用する
- Zod または Valibot でスキーマを検証する
- MDC コンポーネントは
components/content/に配置する - ISO 8601 の日付形式を使用する
- 抜粋には `` を追加する
- コードブロックでは言語を指定する
- 設定を変更した後は
.nuxtをクリアする - Cloudflare では、D1 バインディング名を必ず「DB」にする
- 大規模なデータセットにはページネーションを使用する
他のスキルとの連携
このスキルは、以下のスキルと組み合わせて効果的に使用できます:
- nuxt-v4 → Nuxt のコアフレームワーク
- nuxt-ui-v4 → UI コンポーネントライブラリ
- cloudflare-worker-base → Cloudflare へのデプロイ
- tailwind-v4-shadcn → スタイリング
- drizzle-orm-d1 → データベースクエリの追加
- cloudflare-d1 → データベース連携
安全なインストール
CMS パッケージをインストールする際は、サプライチェーンセキュリティのベストプラクティスに従ってください:
- インストール後スクリプトをブロックする —
npm config set ignore-scripts true(または Bun:デフォルトで無効) - クールダウン期間 — 新しいパッケージバージョンがコミュニティによって審査されるまで、7 日間待つ
- インストール前に監査する —
socket package score npm <pkg>を実行するか、socket npm install <pkg>を使用してパッケージを確認する
Socket CLI 連携、クールダウン設定、ロックファイルの検証、CI での適用を含む、セキュリティ設定の全容については dependency-upgrade スキルを読み込んでください。
その他のリソース
公式ドキュメント:
- Nuxt Content ドキュメント:https://content.nuxt.com
- GitHub:https://github.com/nuxt/content
- Nuxt Studio:https://nuxt.studio
例:
本番環境でのテスト済み:ドキュメントサイト、ブログ、コンテンツプラットフォーム 最終更新日:2025-01-27 トークン削減量:約60%(コンテンツとエラードキュメントを削減)