Owned primitives
Add ready-made features, such as comments, as code you own and can edit.
You want comments on your blog. You could write the collection, the functions to post and moderate, and the access rules yourself, or you could start from one that already works.
Graft ships ready-made features like this as source code you copy into your project, the way shadcn/ui ships components. We call them primitives. There is no plugin system and no package to keep updated: once added, the code is yours to read and change.
See what is available
graft add
| Primitive | What you get | Needs |
|---|---|---|
comments | A comments collection, plus functions to post, list, moderate, and delete | Postgres |
commerce | Products as content, orders as runtime data, plus functions to place, list, update, and cancel orders | Postgres |
scoped-access | Named permission scopes and helpers for access rules | Either engine |
seo | SEO fields to add to any collection | Either engine |
faq | Structured FAQ fields and a block to render them | Either engine |
callout | A callout content block and its MDX component | Either engine |
Agents can browse the same list with the list_registry and describe_item
MCP tools.
Add one
Preview what it will create, then add it:
graft add comments --dry-run # show the files, change nothing
graft add comments
This copies the primitive's TypeScript into your graft/ folder, along with
anything it depends on, such as scoped-access. It also updates
graft/index.ts, a file that re-exports everything in graft/.
Connect it to your config
Your config combines your own collections with everything in graft/, using
mergePrimitives. Projects created with graft init already do this:
import { mergePrimitives } from "@usegraft/core";
import * as primitives from "./graft";
export const { collections, functions } = mergePrimitives([
{ collections: { pages }, functions: {} },
primitives,
]);Run graft compile, and the new collection and functions are live. If a
primitive's name clashes with one of yours, the config stops loading with
CONFIG_INVALID instead of silently replacing either.
Change it
The files in graft/ are yours. Rename fields, change the moderation rules,
or delete functions you do not need. Graft does not overwrite them: running
graft add again refuses to replace a file you changed, unless you pass
--overwrite. If you need to undo your changes, Git has the original.
Where primitives come from
Primitives ship inside the @usegraft/registry package, versioned with the rest
of Graft and tested with it. Each one is a small manifest: a content block, a
set of fields, access rules, or a bundle of those. Third-party registries are
not supported yet. The format is designed so they can be added later.
Next steps
- Schema covers combining collections.
- Operational data explains the runtime data that
commentsandcommerceuse. - Functions & access covers the functions they add.