graft. docs

Schema

defineCollection and field builders — the single Zod layer for content and functions.

Define collections and fields in graft.config.ts (and under graft/ when you add primitives). The same definitions type the compiler, SDK reads, MCP tools, and function inputs.

defineCollection

import { defineCollection, field } from "@usegraft/core";

export const pages = defineCollection({
  name: "pages",
  description: "Marketing and site pages.",
  fields: {
    title: field.string({ description: "Headline and <title>." }),
    tagline: field.string({ optional: true }),
    description: field.string({ optional: true }),
    image: field.asset({ optional: true }),
  },
});
OptionPurpose
nameCollection id. Matches content/<name>/
descriptionShown to agents via describe_schema
fieldsMap of field.* builders
authorityOmit for file-authoritative. Set "db-authoritative" for operational rows

Field builders

BuilderStoresNotes
field.string()short stringFrontmatter scalars
field.text()long stringBodies and blurbs
field.number()number
field.boolean()boolean
field.datetime()ISO datetime
field.json()arbitrary JSONPrefer typed object/array when you can
field.asset(){ key, alt? }See Assets
field.object({ fields })nested objectRecursive in describe_schema
field.array({ of })listof is another field

All builders accept { optional: true, description: "…" }.

Nested example

faqs: field.array({
  of: field.object({
    fields: {
      question: field.string(),
      answer: field.string(),
    },
  }),
  optional: true,
}),

What a collection looks like once declared

This is the docs collection that renders the page you are reading, generated from its own schema rather than written out here. The same descriptor answers MCP's describe_schema and fills the Studio's schema view, so this table cannot drift from what the compiler enforces.

FieldTypeRequiredDescription
titlestringyesDoc page title (h1, sidebar label, <title>).
descriptionstringyesOne-line summary shown in listings and meta.
sectionstringyesSidebar group: "Start here", "Build", "Operate", or "Reference".
ordernumberSort order within the section.

Merge with primitives

graft add drops source under graft/. Merge your collections with the generated barrel:

import { mergePrimitives } from "@usegraft/core";
import * as primitives from "./graft";

export const { collections, functions } = mergePrimitives([
  { collections: { pages }, functions: { /* … */ } },
  primitives,
]);

Duplicate keys throw CONFIG_INVALID. Nothing is overridden silently.

Wire the config

Export collections (and functions when you define them). The CLI loads the file with jiti. Framework apps import the same module for typed reads.

Next steps