mcpField
N
nuxt-content

nuxt-content

github.com/secondsky开发245223 次安装6 周前更新
代码仓库

关于 nuxt-content

nuxt-content 技能为 Nuxt 项目提供基于文件的内容管理指导,适合构建博客、文档和内容型应用。内容集合、类型安全查询及 SQL 存储是其重点。

主要功能

  1. 01配置内容集合与验证
  2. 02编写类型安全内容查询
  3. 03管理 Markdown、YAML、JSON 和 CSV
  4. 04生成内容导航与全文搜索
  5. 05使用 MDC 渲染组件

适用场景

  1. 01构建博客或文档站点
  2. 02按 schema 验证结构化内容
  3. 03从内容目录生成导航
  4. 04为内容添加全文搜索

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/secondsky/claude-skills --skill nuxt-content

安装后在 Claude Code 中输入/nuxt-content确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
blog-collection.example.ts
content.config.example.ts
docs-collection.example.ts
nuxt.config.example.ts
references/
collection-examples.md
deployment-checklists.md
error-catalog.md
mdc-syntax-reference.md
query-operators.md
studio-setup-guide.md
scripts/
deploy-cloudflare.sh
deploy-vercel.sh
setup-nuxt-content.sh
setup-studio.sh
templates/
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 是一款功能强大的基于 Git 的 Nuxt 项目 CMS,可通过 Markdown、YAML、JSON 和 CSV 文件管理内容。它能将内容文件转换为结构化数据,并提供类型安全的查询、自动验证和基于 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']
})

重要提示:

  • 必须将模块添加到 modules 数组中(而不是 buildModules)
  • 基本设置无需其他配置
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


关键规则

务必做到
  1. 定义集合:查询前先在 content.config.ts 中定义集合
  2. 使用 ISO 8601 日期格式:2024-01-15 或 2024-01-15T10:30:00Z
  3. 重启开发服务器:更改 content.config.ts 后重启
  4. 使用 .only() 选择特定字段(提升性能)
  5. 将 MDC 组件放在 components/content/ 目录中
  6. 使用零填充前缀进行数字排序:01-、02-
  7. 安装数据库连接器:必须安装 better-sqlite3
  8. 在代码块中指定语言以启用语法高亮
  9. 在内容中使用 `` 分隔摘要
  10. D1 绑定名称必须为 "DB"(区分大小写),用于 Cloudflare
切勿这样做
  1. 不要在定义集合之前查询:应先在 content.config.ts 中定义集合
  2. 不要使用非 ISO 日期格式(例如 "January 15, 2024")
  3. 不要忘记重启:更改配置后重启开发服务器
  4. 只需部分字段时,不要查询所有字段(使用 .only())
  5. 不要将组件放在 components/content/ 之外
  6. 不要使用个位数前缀(使用 01-,而不是 1-)
  7. 不要跳过数据库连接器的安装
  8. 不要忘记在代码围栏中指定语言
  9. 没有 `` 分隔符时,不要期待生成摘要
  10. 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()
      })
    })
  }
})

集合类型
页面类型(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()

Where 条件
// 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(区分大小写)。

参见:references/deployment-checklists.md,了解完整的 Cloudflare 部署指南和故障排除方法。


Vercel
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/content'],
  routeRules: {
    '/blog/**': { prerender: true }
  }
})
vercel deploy

参见:references/deployment-checklists.md,了解完整的 Vercel 配置和预渲染策略。


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 设置
  1. 创建 GitHub OAuth App
  2. 设置授权回调 URL:https://yourdomain.com/api/__studio/oauth/callback
  3. 将客户端 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:

  • 用户遇到上述 Top 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 组件)
  • 调试组件渲染问题
  • 需要 props、slots、嵌套的完整语法参考
  • 创建高级内容组件

遇到以下情况时,加载 references/studio-setup-guide.md:

  • 设置 Nuxt Studio,以便在生产环境中编辑内容
  • 配置 GitHub OAuth 身份验证
  • 启用通过 GitHub 同步的可自托管内容编辑
  • 排查 Studio 身份验证或 Git 同步问题

模板(templates/):

  • blog-collection-setup.ts - 完整的博客设置,涵盖集合、查询、导航、搜索和部署(334 行)

性能提示

  1. 使用 .only() 选择特定字段
  2. 启用缓存,用于生产环境
  3. 使用分页处理大型集合
  4. 在 Vercel 上预渲染静态路由
  5. 使用 SQL 存储(better-sqlite3)以获得最佳性能

最佳实践

  1. 查询前始终先定义集合
  2. 使用 TypeScript 编写类型安全的查询
  3. 使用 Zod 或 Valibot 验证架构
  4. 将 MDC 组件放在 components/content/ 中
  5. 使用 ISO 8601 日期格式
  6. 添加 `` 作为摘要
  7. 在代码块中指定语言
  8. 更改配置后清除 .nuxt
  9. 对于 Cloudflare:D1 绑定必须为 "DB"
  10. 对大型数据集使用分页

与其他技能集成

此技能可与以下技能良好配合:

  • 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> 检查软件包

加载 dependency-upgrade 技能,以获取完整的安全配置,包括 Socket CLI 集成、冷却期设置、锁文件验证和 CI 强制执行。

其他资源

官方文档:

示例:


生产环境测试:文档站点、博客、内容平台 最后更新:2025-01-27 Token 节省:约 60%(减少内容和错误文档)

评论

支持 Markdown