Upgrade Guide (v0.x -> v1.0)
ContentKit v1.0 introduces a new, more flexible configuration API. While the legacy configuration format is still supported for now, we strongly recommend upgrading to the new format to take advantage of improved type safety and developer experience.
Migration Steps
1. Update Imports
Replace the old ContentKitConfig type import with the new helper functions.
Old:
import type { ContentKitConfig } from "contentkit/types";
const config: ContentKitConfig = {
/* ... */
};
export default config;New:
import { defineConfig, defineCollection, fields } from "contentkit";
// ... collections definition
export default defineConfig({
collections: [
/* ... */
],
});2. Define Collections
Instead of a single documentTypes array, define each collection individually using defineCollection.
Old:
documentTypes: [
{
name: "Post",
filePathPattern: "posts/**/*.md",
fields: {
/* ... */
},
},
];New:
const posts = defineCollection({
name: "Post",
directory: "./content/posts", // Base directory for this collection
include: "**/*.md", // Glob pattern relative to directory
schema: {
/* ... */
},
});3. Update Field Definitions
Use the fields helper to define your schema. This provides better type inference and autocomplete.
Old:
fields: {
title: { type: "string", required: true },
tags: { type: "array", items: { type: "string" } },
author: {
type: "object",
required: true,
fields: {
name: { type: "string", required: true }
}
}
}New:
schema: {
title: fields.string(),
tags: fields.array(fields.string()).optional(), // or fields.list(...)
author: fields.object({
name: fields.string(),
}),
}Note: Fields are required by default. Use .optional() to make them optional.
4. Update Computed Fields
Computed fields are now defined using the .resolve() method on a field definition.
Old:
computedFields: {
slug: {
type: "string",
resolve: (doc) => doc.title.toLowerCase().replace(/\s+/g, "-"),
},
}New:
computedFields: {
slug: fields.string().resolve((doc) => doc.title.toLowerCase().replace(/\s+/g, "-")),
}5. Remove Global Options
outputFormat and generateTypes are now automatically detected from your project's package.json and tsconfig.json. You can remove them from your config unless you need to override the defaults.
Old:
export default {
contentDirPath: "content", // Now handled per-collection via `directory`
outputFormat: "esm", // Auto-detected
generateTypes: true, // Auto-detected
// ...
};New:
export default defineConfig({
collections: [posts],
});Full Example
Before:
import type { ContentKitConfig } from "contentkit/types";
const config: ContentKitConfig = {
contentDirPath: "content",
outputFormat: "esm",
generateTypes: true,
documentTypes: [
{
name: "Post",
filePathPattern: "posts/**/*.md",
fields: {
title: { type: "string", required: true },
date: { type: "date", required: true },
},
computedFields: {
slug: {
type: "string",
resolve: (doc) => doc._raw.sourceFileName.replace(/\.md$/, ""),
},
},
},
],
};
export default config;After:
import { defineConfig, defineCollection, fields } from "contentkit";
const posts = defineCollection({
name: "Post",
directory: "./content/posts",
include: "**/*.md",
schema: {
title: fields.string(),
date: fields.date(),
},
computedFields: {
slug: fields
.string()
.resolve((doc) => doc._raw.sourceFileName.replace(/\.md$/, "")),
},
});
export default defineConfig({
collections: [posts],
});