# Owned primitives

> Add ready-made features such as comments, SEO fields, or a product catalog as source code you own and can change.

*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

```sh
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:

```sh
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:

`graft.config.ts`:

```ts
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](/docs/schema) covers combining collections.
- [Operational data](/docs/operational-data) explains the runtime data that
  `comments` and `commerce` use.
- [Functions & access](/docs/functions-and-access) covers the functions they add.
