mcpField
C
content-collections

content-collections

github.com/secondskyDevelopment240128 installsUpdated 5w ago
Repository

About content-collections

Content Collections turns local Markdown and MDX files into typed TypeScript data and validates them against schemas at build time. It is intended for blogs, documentation sites, and content-heavy applications.

Key features

  1. 01Scans files and parses frontmatter
  2. 02Validates content with Zod and other schemas
  3. 03Generates typed TypeScript modules
  4. 04Supports Markdown and MDX workflows
  5. 05Provides a Vite plugin and hot reloading

Use cases

  1. 01Build a collection of blog posts for app imports
  2. 02Validate local content for a documentation site
  3. 03Render MDX content through React components
  4. 04Generate type-safe content in a Vite project

Install

Copy the command and run it in a terminal.

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

After installing, type/content-collectionsin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

assets/
example-template.txt
references/
advanced-troubleshooting.md
deployment-guide.md
mdx-components.md
schema-patterns.md
transform-cookbook.md
scripts/
example-script.sh
init-content-collections.sh
templates/
blog-post.md
BlogList.tsx
BlogPost.tsx
content-collections-mdx.ts
content-collections-multi.ts
content-collections.ts
tsconfig.json
vite.config.ts
wrangler.toml

Details

From the project README

Content Collections

Status: Production Ready ✅ Last Updated: 2025-11-07 Dependencies: None Latest Versions: @content-collections/[email protected], @content-collections/[email protected], [email protected]


What is Content Collections?

Content Collections transforms local content files (Markdown/MDX) into type-safe TypeScript data with automatic validation at build time.

Problem it solves: Manual content parsing, lack of type safety, runtime errors from invalid frontmatter.

How it works:

  1. Define collections in content-collections.ts (name, directory, Zod schema)
  2. CLI/plugin scans filesystem, parses frontmatter, validates against schema
  3. Generates TypeScript modules in .content-collections/generated/
  4. Import collections: import { allPosts } from "content-collections"

Perfect for: Blogs, documentation sites, content-heavy apps with Cloudflare Workers, Vite, Next.js.


Quick Start (5 Minutes)

1. Install Dependencies
# Bun (recommended)
bun add -d @content-collections/core @content-collections/vite zod

# npm
npm install -D @content-collections/core @content-collections/vite zod

# pnpm
pnpm add -D @content-collections/core @content-collections/vite zod
2. Configure TypeScript Path Alias

Add to tsconfig.json:

{
  "compilerOptions": {
    "paths": {
      "content-collections": ["./.content-collections/generated"]
    }
  }
}
  1. Configure Vite Plugin

Add to 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. Update .gitignore
.content-collections/
5. Create Collection Config

Create content-collections.ts in project root:

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. Create Content Directory
mkdir -p content/posts

Create 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 and Use
import { allPosts } from "content-collections";

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

Result: Type-safe content with autocomplete, validation, and HMR.


Critical Rules

✅ Always Do:
  1. Add path alias to tsconfig.json - Required for imports to work
  2. Add .content-collections to .gitignore - Generated files shouldn't be committed
  3. Use Standard Schema validators - Zod, Valibot, ArkType supported
  4. Include content field in schema - Required for frontmatter parsing
  5. Await compileMDX in transforms - MDX compilation is async
  6. Put contentCollections() after react() in Vite - Plugin order matters
❌ Never Do:
  1. Commit .content-collections directory - Always generated, never committed
  2. Use non-standard validators - Must support StandardSchema spec
  3. Forget to restart dev server after config changes - Required for new collections
  4. Use sync transforms with async operations - Transform must be async
  5. Double-wrap path alias - Use content-collections not ./content-collections
  6. Import from wrong package - @content-collections/core for config, content-collections for data

Known Issues Prevention

Issue #1: Module not found: 'content-collections'

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

Why it happens: Missing TypeScript path alias configuration.

Prevention:

Add to tsconfig.json:

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

Restart TypeScript server in VS Code: Cmd+Shift+P → "TypeScript: Restart TS Server"

Source: Common user error


Issue #2: Vite Constant Restart Loop

Error: Dev server continuously restarts, infinite loop.

Why it happens: Vite watching .content-collections directory changes, which triggers regeneration.

Prevention:

  1. Add to .gitignore:
.content-collections/
  1. Add to vite.config.ts (if still happening):
export default defineConfig({
  server: {
    watch: {
      ignored: ["**/.content-collections/**"],
    },
  },
});

Source: GitHub Issue #591 (TanStack Start)


Issue #3: Transform Types Not Reflected

Error: TypeScript types don't match transformed documents.

Why it happens: TypeScript doesn't automatically infer transform function return type.

Prevention:

Explicitly type your transform return:

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;
};

Source: GitHub Issue #396


Issues #4-8: Advanced Troubleshooting

Additional issues covered in references/advanced-troubleshooting.md:

IssueErrorQuick Fix
#4Collection not updatingVerify glob pattern, restart dev server
#5MDX/Shiki errorsUse compatible versions (shiki ^1.0.0)
#6MDX path aliases failUse relative paths in MDX imports
#7Unclear validation errorsAdd custom Zod error messages
#8Ctrl+C doesn't stopUse kill -9 or separate watch command

Configuration Patterns

PatternUse CaseTemplate
Basic BlogSingle collection, Markdown onlytemplates/content-collections.ts
Multi-CollectionPosts + Docs, nested folderstemplates/content-collections-multi.ts
Transform FunctionsComputed fields (slug, readingTime)See references/transform-cookbook.md
MDX + ReactSyntax highlighting, React componentstemplates/content-collections-mdx.ts

For detailed schema patterns (dates, tags, validation), load references/schema-patterns.md.


React Component Integration

Using Collections in 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>
  );
}

Rendering MDX Content
import { MDXContent } from "@content-collections/mdx/react";

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

Cloudflare Workers Deployment

Content Collections is perfect for Cloudflare Workers (build-time only, no runtime filesystem). Use template templates/wrangler.toml for config.

Pattern: vite build → wrangler deploy (Vite plugin handles content-collections automatically)

For detailed deployment guide, load references/deployment-guide.md.


Bundled Resources

Templates (9 copy-paste files)

content-collections.ts, content-collections-multi.ts, content-collections-mdx.ts, tsconfig.json, vite.config.ts, BlogList.tsx, BlogPost.tsx, blog-post.md, wrangler.toml

Scripts

init-content-collections.sh - One-command automated setup


Dependencies

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

Official Documentation


Package Versions (Verified 2025-11-07)

PackageVersionStatus
@content-collections/core0.12.0✅ Latest stable
@content-collections/vite0.2.7✅ Latest stable
@content-collections/mdx0.2.2✅ Latest stable
@content-collections/markdown0.1.4✅ Latest stable
zod3.23.8✅ Latest stable

Quick Troubleshooting

ProblemSolution
TypeScript can't find moduleAdd path alias to tsconfig.json, restart TS server
Vite keeps restartingAdd .content-collections/ to .gitignore
Changes not reflectingRestart dev server, verify glob pattern
MDX compilation errorsCheck Shiki version compatibility
Validation errors unclearAdd custom Zod error messages

When to Load References

ReferenceLoad When...
schema-patterns.mdSetting up complex schemas, date validation, optional fields
transform-cookbook.mdAdding computed fields, async transforms, slugs
mdx-components.mdIntegrating React components in MDX, syntax highlighting
deployment-guide.mdDeploying to Cloudflare Workers or other platforms
advanced-troubleshooting.mdIssues #4-8 (file watching, path aliases, process hanging)

Complete Setup Checklist

  • Installed @content-collections/core and @content-collections/vite
  • Installed zod for schema validation
  • Added path alias to tsconfig.json
  • Added contentCollections() to vite.config.ts (after react())
  • Added .content-collections/ to .gitignore
  • Created content-collections.ts in project root
  • Created content directory (e.g., content/posts/)
  • Defined collection with Zod schema
  • Created first content file with frontmatter
  • Imported collection in React component
  • Verified types work (autocomplete)
  • Tested hot reloading (change content file)

Comments

Markdown supported