Receber por email
← Voltar para o catálogo

content-collections

Production-tested setup for Content Collections - a TypeScript-first build tool that transforms local content files (Markdown/MDX) into type-safe data collections with automatic validation. Use when: building blogs, documentation sites, or content-heavy applications with Vite + React, setting up MDX content with React components, implementing type-safe content schemas with Zod, migrating from Cont

15estrelas
Atualizado há 11 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add jackspace/ClaudeSkillz

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/content-collections/svg)](https://www.skillteca.com.br/skills/content-collections)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Content Collections

Status: Production Ready ✅ Last Updated: 2025-11-07 Dependencies: None Latest Versions: @content-collections/core@0.12.0, @content-collections/vite@0.2.7, zod@3.23.8

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

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

Issue #4: Collection Not Updating on File Change

Error: New content files not appearing in collection.

Why it happens: Glob pattern doesn't match, or dev server needs restart.

Prevention:

  1. Verify glob pattern matches your files:
include: "*.md"        // Only root files
include: "**/*.md"     // All nested files
include: "posts/*.md"  // Only posts/ folder
  1. Restart dev server after adding new files outside watched patterns
  2. Check file actually saved (watch for editor issues)

Source: Common user error

Issue #5: MDX Type Errors with Shiki

Error: esbuild errors with shiki langAlias or compilation failures.

Why it happens: Version incompatibility between Shiki and Content Collections.

Prevention:

Use compatible versions:

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

Check official compatibility matrix in docs before upgrading Shiki.

Source: GitHub Issue #598 (Next.js 15)

Issue #6: Custom Path Aliases in MDX Imports Fail

Error: MDX imports with @ alias don't resolve.

Why it happens: MDX compiler doesn't respect tsconfig path aliases.

Prevention:

Use relative paths in MDX imports:

<!-- ❌ Won't work -->
import Component from "@/components/Component"

<!-- ✅ Works -->
import Component from "../../components/Component"

Or configure files appender (advanced, see references/transform-cookbook.md).

Source: GitHub Issue #547

Issue #7: Unclear Validation Error Messages

Error: Cryptic Zod validation errors like "Expected string, received undefined".

Why it happens: Zod errors aren't formatted for content context.

Prevention:

Add custom error messages to 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)"
  ),
})

Source: GitHub Issue #403

Issue #8: Ctrl+C Doesn't Stop Process

Error: Dev process hangs on exit, requires kill -9.

Why it happens: File watcher not cleaning up properly.

Prevention:

This is a known issue with the watcher. Workarounds:

  1. Use kill -9 <pid> when it hangs
  2. Use content-collections watch separately (not plugin) for more control
  3. Add cleanup handler in vite.config.ts (advanced)

Source: GitHub Issue #546

Configuration Patterns

Basic Blog Collection

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

const posts = defineC
Compartilhar X LinkedIn