mcpField
C
content-collections

content-collections

github.com/jackspace开发1667 次安装15 周前更新
代码仓库

关于 content-collections

content-collections 将本地 Markdown 和 MDX 文件转换为经过验证、具备类型的 TypeScript 数据,适用于内容丰富的网站。它在构建时生成可导入模块,并支持模式校验和数据转换。

主要功能

  1. 01解析 Markdown 和 MDX
  2. 02构建时校验数据模式
  3. 03生成带类型的 TypeScript 模块
  4. 04集合数据转换
  5. 05集成 Vite 插件
  6. 06支持编译 MDX

适用场景

  1. 01构建带类型的博客文章集合
  2. 02在构建时校验 frontmatter
  3. 03在 Vite 网站中使用本地内容
  4. 04在 React 中渲染 MDX 内容

安装

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

$npx skills add https://github.com/jackspace/claudeskillz --skill content-collections

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

附带文件README.mdSKILL.json

详细介绍

内容集合

状态:已可用于生产环境 ✅ 最后更新:2025-11-07 依赖项:无 最新版本:@content-collections/[email protected]、@content-collections/[email protected]、[email protected]


什么是 Content Collections?

Content Collections 会将本地内容文件(Markdown/MDX)转换为类型安全的 TypeScript 数据,并在构建时自动进行验证。

解决的问题:手动解析内容、缺少类型安全,以及无效 frontmatter 导致的运行时错误。

工作原理:

  1. 在 content-collections.ts 中定义集合(名称、目录、Zod 架构)
  2. CLI/插件扫描文件系统、解析 frontmatter,并根据架构进行验证
  3. 在 .content-collections/generated/ 中生成 TypeScript 模块
  4. 导入集合:import { allPosts } from "content-collections"

适用于:博客、文档站点,以及使用 Cloudflare Workers、Vite、Next.js 的内容密集型应用。


快速开始(5 分钟)

1. 安装依赖项
pnpm add -D @content-collections/core @content-collections/vite zod
2. 配置 TypeScript 路径别名

添加到 tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "content-collections": ["./.content-collections/generated"]
    }
  }
}
  1. 配置 Vite 插件

添加到 vite.config.ts:

import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import contentCollections from "@content-collections/vite";

export default defineConfig({
  plugins: [
    react(),
    contentCollections(), // MUST come after react()
  ],
});
4. 更新 .gitignore
.content-collections/
5. 创建集合配置

在项目根目录中创建 content-collections.ts:

import { defineCollection, defineConfig } from "@content-collections/core";
import { z } from "zod";

const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "*.md",
  schema: z.object({
    title: z.string(),
    date: z.string(),
    description: z.string(),
    content: z.string(),
  }),
});

export default defineConfig({
  collections: [posts],
});
6. 创建内容目录
mkdir -p content/posts

创建 content/posts/first-post.md:

---
title: My First Post
date: 2025-11-07
description: Introduction to Content Collections
---

# My First Post

Content goes here...
7. 导入并使用
import { allPosts } from "content-collections";

console.log(allPosts); // Fully typed!

结果:内容具有类型安全、自动补全、验证和 HMR。


重要规则

✅ 务必执行:
  1. 向 tsconfig.json 添加路径别名 - 导入正常工作所必需
  2. 将 .content-collections 添加到 .gitignore - 生成的文件不应提交
  3. 使用 Standard Schema 验证器 - 支持 Zod、Valibot、ArkType
  4. 在架构中包含 content 字段 - 解析 frontmatter 所必需
  5. 在转换中等待 compileMDX - MDX 编译是异步的
  6. 在 Vite 中将 contentCollections() 放在 react() 后面 - 插件顺序很重要
❌ 切勿执行:
  1. 提交 .content-collections 目录 - 此目录始终由程序生成,切勿提交
  2. 使用非标准验证器 - 必须支持 StandardSchema 规范
  3. 更改配置后忘记重启开发服务器 - 新集合生效所必需
  4. 在同步转换中执行异步操作 - 转换必须是异步的
  5. 重复包装路径别名 - 使用 content-collections,而非 ./content-collections
  6. 从错误的包导入 - 配置使用 @content-collections/core,数据使用 content-collections

预防已知问题

问题 #1:找不到模块:'content-collections'

错误:Cannot find module 'content-collections' or its corresponding type declarations

原因:缺少 TypeScript 路径别名配置。

预防方法:

添加到 tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "content-collections": ["./.content-collections/generated"]
    }
  }
}

在 VS Code 中重启 TypeScript 服务器:Cmd+Shift+P → "TypeScript: Restart TS Server"

来源:常见用户错误


问题 #2:Vite 不断重启循环

错误:开发服务器持续重启,陷入无限循环。

原因:Vite 正在监视 .content-collections 目录的更改,从而触发重新生成。

预防方法:

  1. 添加到 .gitignore:
.content-collections/
  1. 如果问题仍然存在,添加到 vite.config.ts:
export default defineConfig({
  server: {
    watch: {
      ignored: ["**/.content-collections/**"],
    },
  },
});

来源:GitHub Issue #591(TanStack Start)


问题 #3:转换后的类型未体现

错误:TypeScript 类型与转换后的文档不匹配。

原因:TypeScript 不会自动推断转换函数的返回类型。

预防方法:

为转换函数的返回值显式指定类型:

const posts = defineCollection({
  name: "posts",
  // ... schema
  transform: (post): PostWithSlug => ({ // Type the return!
    ...post,
    slug: post._meta.path.replace(/\.md$/, ""),
  }),
});

type PostWithSlug = {
  // ... schema fields
  slug: string;
};

来源:GitHub Issue #396


问题 #4:文件更改后集合未更新

错误:新内容文件未出现在集合中。

原因:Glob 模式不匹配,或需要重启开发服务器。

预防方法:

  1. 确认 Glob 模式与文件匹配:
include: "*.md"        // Only root files
include: "**/*.md"     // All nested files
include: "posts/*.md"  // Only posts/ folder
  1. 在监视范围之外添加新文件后,重启开发服务器
  2. 检查文件是否已保存(留意编辑器问题)

来源:常见用户错误


问题 #5:使用 Shiki 时出现 MDX 类型错误

错误:esbuild errors with shiki langAlias 或编译失败。

原因:Shiki 与 Content Collections 的版本不兼容。

预防措施:

使用兼容的版本:

{
  "devDependencies": {
    "@content-collections/mdx": "^0.2.2",
    "shiki": "^1.0.0"
  }
}

升级 Shiki 前,请查看文档中的官方兼容性矩阵。

来源:GitHub Issue #598(Next.js 15)


问题 #6:MDX 导入中的自定义路径别名失效

错误:MDX 导入中的 @ 别名无法解析。

原因:MDX 编译器不支持 tsconfig 路径别名。

预防措施:

在 MDX 导入中使用相对路径:


import Component from "@/components/Component"


import Component from "../../components/Component"

或者配置 files appender(高级用法,参见 references/transform-cookbook.md)。

来源:GitHub Issue #547


问题 #7:验证错误消息不明确

错误:晦涩的 Zod 验证错误,例如“Expected string, received undefined”。

原因:Zod 错误没有针对内容场景进行格式化。

预防措施:

为 schema 添加自定义错误消息:

schema: z.object({
  title: z.string({
    required_error: "Title is required in frontmatter",
    invalid_type_error: "Title must be a string",
  }),
  date: z.string().refine(
    (val) => !isNaN(Date.parse(val)),
    "Date must be valid ISO date (YYYY-MM-DD)"
  ),
})

来源:GitHub Issue #403


问题 #8:Ctrl+C 无法停止进程

错误:开发进程退出时卡住,需要执行 kill -9。

原因:文件监视器未能正确清理。

预防措施:

这是文件监视器的已知问题。可采用以下变通方法:

  1. 卡住时使用 kill -9 <pid>
  2. 单独运行 content-collections watch(而非使用插件),以便更好地控制
  3. 在 vite.config.ts 中添加清理处理程序(高级用法)

来源:GitHub Issue #546


配置模式

基本博客集合
import { defineCollection, defineConfig } from "@content-collections/core";
import { z } from "zod";

const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "*.md",
  schema: z.object({
    title: z.string(),
    date: z.string(),
    description: z.string(),
    tags: z.array(z.string()).optional(),
    content: z.string(),
  }),
});

export default defineConfig({
  collections: [posts],
});

多集合设置
const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "*.md",
  schema: z.object({
    title: z.string(),
    date: z.string(),
    description: z.string(),
    content: z.string(),
  }),
});

const docs = defineCollection({
  name: "docs",
  directory: "content/docs",
  include: "**/*.md", // Nested folders
  schema: z.object({
    title: z.string(),
    category: z.string(),
    order: z.number().optional(),
    content: z.string(),
  }),
});

export default defineConfig({
  collections: [posts, docs],
});

转换函数(计算字段)
const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "*.md",
  schema: z.object({
    title: z.string(),
    date: z.string(),
    content: z.string(),
  }),
  transform: (post) => ({
    ...post,
    slug: post._meta.path.replace(/\.md$/, ""),
    readingTime: Math.ceil(post.content.split(/\s+/).length / 200),
    year: new Date(post.date).getFullYear(),
  }),
});

使用 React 组件的 MDX
import { compileMDX } from "@content-collections/mdx";

const posts = defineCollection({
  name: "posts",
  directory: "content/posts",
  include: "*.mdx",
  schema: z.object({
    title: z.string(),
    date: z.string(),
    content: z.string(),
  }),
  transform: async (post) => {
    const mdx = await compileMDX(post.content, {
      syntaxHighlighter: "shiki",
      shikiOptions: {
        theme: "github-dark",
      },
    });

    return {
      ...post,
      mdx,
      slug: post._meta.path.replace(/\.mdx$/, ""),
    };
  },
});

React 组件集成

在 React 中使用集合
import { allPosts } from "content-collections";

export function BlogList() {
  return (
    <ul>
      {allPosts.map((post) => (
        <li key={post._meta.path}>
          <h2>{post.title}</h2>
          <p>{post.description}</p>
          <time>{post.date}</time>
        </li>
      ))}
    </ul>
  );
}

渲染 MDX 内容
import { MDXContent } from "@content-collections/mdx/react";

export function BlogPost({ post }: { post: { mdx: string } }) {
  return (
    <article>
      <MDXContent code={post.mdx} />
    </article>
  );
}

部署到 Cloudflare Workers

Content Collections 非常适合 Cloudflare Workers,因为它:

  • 仅在构建时运行(运行时无需访问文件系统)
  • 输出静态 JavaScript 模块
  • 生成的代码不依赖 Node.js
部署模式
Local Dev → content-collections build → vite build → wrangler deploy
wrangler.toml
name = "my-content-site"
compatibility_date = "2025-11-07"

[assets]
directory = "./dist"
binding = "ASSETS"
构建脚本

package.json:

{
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "deploy": "pnpm build && wrangler deploy"
  }
}

注意:Vite 插件会自动处理 content-collections build!


使用打包资源

模板(templates/)

可直接复制粘贴使用的配置文件:

  • content-collections.ts - 基本博客设置
  • content-collections-multi.ts - 多个集合
  • content-collections-mdx.ts - 带语法高亮的 MDX
  • tsconfig.json - 完整的 TypeScript 配置
  • vite.config.ts - Vite 插件设置
  • blog-post.md - 示例内容文件
  • BlogList.tsx - React 列表组件
  • BlogPost.tsx - React MDX 渲染组件
  • wrangler.toml - Cloudflare Workers 配置
参考资料(references/)

有关高级主题的深入文档:

  • schema-patterns.md - 常见的 Zod schema 模式
  • transform-cookbook.md - 转换函数示例
  • mdx-components.md - MDX + React 集成
  • deployment-guide.md - Cloudflare Workers 设置

何时加载:需要了解基本设置之外的高级模式时,Claude 应加载这些文件。

脚本(scripts/)
  • init-content-collections.sh - 一键自动设置

依赖项

必需
{
  "devDependencies": {
    "@content-collections/core": "^0.12.0",
    "@content-collections/vite": "^0.2.7",
    "zod": "^3.23.8"
  }
}
可选(MDX)
{
  "devDependencies": {
    "@content-collections/markdown": "^0.1.4",
    "@content-collections/mdx": "^0.2.2",
    "shiki": "^1.0.0"
  }
}

官方文档


软件包版本(已于 2025-11-07 验证)

软件包版本状态
@content-collections/core0.12.0✅ 最新稳定版
@content-collections/vite0.2.7✅ 最新稳定版
@content-collections/mdx0.2.2✅ 最新稳定版
@content-collections/markdown0.1.4✅ 最新稳定版
zod3.23.8✅ 最新稳定版

故障排除

问题:TypeScript 找不到 'content-collections'

解决方案:在 tsconfig.json 中添加路径别名,然后重启 TS 服务器。


问题:Vite 不断重启

解决方案:将 .content-collections/ 添加到 .gitignore 和 Vite 的监视忽略列表中。


问题:更改未生效

解决方案:重启开发服务器,检查 glob 模式,并确认文件已保存。


问题:MDX 编译错误

解决方案:检查 Shiki 版本兼容性,并验证 MDX 语法。


问题:验证错误不明确

解决方案:为 Zod 架构添加自定义错误消息。


完整设置清单

  • 已安装 @content-collections/core 和 @content-collections/vite
  • 已安装用于架构验证的 zod
  • 已在 tsconfig.json 中添加路径别名
  • 已将 contentCollections() 添加到 vite.config.ts(位于 react() 之后)
  • 已将 .content-collections/ 添加到 .gitignore
  • 已在项目根目录创建 content-collections.ts
  • 已创建内容目录(例如 content/posts/)
  • 已使用 Zod 架构定义集合
  • 已创建带有 frontmatter 的首个内容文件
  • 已在 React 组件中导入集合
  • 已验证类型正常工作(自动补全)
  • 已测试热重载(更改内容文件)

有疑问?遇到问题?

  1. 查看 references/ 目录中的深入说明
  2. 验证 tsconfig.json 中的路径别名
  3. 检查 Vite 插件顺序(位于 react() 之后)
  4. 查看上述已知问题
  5. 查看官方文档:https://www.content-collections.dev/docs

评论

支持 Markdown