A collection groups entries with shared metadata. Export your collections from contentgraph.config.ts at the application root.
Define a collection
import { defineCollection } from "contentgraph";
import { schema } from "contentgraph/schema";
export const collections = {
posts: defineCollection({
source: "./content/posts",
schema: schema.object({
title: schema.string(),
draft: schema.boolean().default(false),
}),
}),
};
Validation and types
ContentGraph includes Zod-backed builders through contentgraph/schema; no separate Zod installation is needed. The schema namespace supplies object, string, number, boolean, bigint, date, array, enum, literal, union, record, and unknown, plus primitive coercion through schema.coerce.
Returned schemas support Zod's chaining methods, including .optional(), .nullable(), .default(), .refine(), and .transform(). Nested composition follows Zod's rules. Provider-level parsing utilities, error classes, and configuration are outside the namespace.
Schemas follow Standard Schema V1, so other compatible validators also work for collection metadata and computed fields. Validation runs during preparation, and validated outputs determine the query types. Async validation is supported. Generated runtime JavaScript imports neither schemas nor Zod.
Use schema.input<Validator> for the input type and schema.output<Validator> or schema.infer<Validator> for validated output. These type helpers accept any Standard Schema V1 provider:
const postSchema = schema.object({
title: schema.string(),
draft: schema.boolean().default(false),
});
type PostInput = schema.input<typeof postSchema>; // draft is optional.
type Post = schema.infer<typeof postSchema>; // draft is boolean.
Each entry has a top-level id. Keep id out of the metadata schema, and use distinct names for source fields, computed fields, and relationships.
Choose exactly one of source or loader. See sources and loaders for input formats.