# Contributing a battery

> The contract on one page: the folder shape, the gate every battery must pass, and the commands that are the whole review.

A plugin is a folder. You can add a battery, a design or a preset without
touching a line of generator code. The whole review is a few commands you run
on your own machine.

This page gets you oriented. The full documents live in the repo:

- `CONTRIBUTING.md`: the full
  contract, three reference batteries to copy, and a step-by-step walkthrough.
- `docs/architecture/CONTRACT.md`:
  manifests, frontmatter formats, tokens, slots, merge rules, determinism.
- `packages/core/src/types.ts`: the pinned types. Import them. Never redefine
  them.

## The folder

```
registry/<stacks|batteries|designs>/<id>/
  manifest.yaml            required
  template/                copied into the generated repo
  agent/
    rules/*.md             path-scoped conventions
    skills/*.md            slash commands
    agents/*.md            subagents
    hooks/*.md             hook definition plus its inline script
    solutions/*.md         long-form docs, published at /cookbook/<id>/<doc>
  design.yaml              designs only: the token set
  DESIGN.md                designs only
```

`template/` paths are relative to the generated repo's root:
`template/src/lib/email/postmark.ts` lands at `src/lib/email/postmark.ts`.

Start by copying the reference battery closest to yours. There are three, and
between them they cover every mechanism the registry has: Stripe (the common
case), Better Auth (slot injection) and Neon (a hook).

## The gate: no config, no battery

A battery isn't accepted until it ships:

1. **Rules**: at least one, scoped to the paths your battery owns.
2. **At least one skill**: a real slash command for work people repeat.
3. **At least five solution docs**: the mistakes, in advance.

This isn't bureaucracy. People pick this generator over other kits because the
agent editing `src/lib/billing/**` already knows to verify the webhook
signature. A folder of files without that knowledge is what we compete against,
not what we build.

Write solution docs for a stranger. Every one is published as a public page in
[the cookbook](/cookbook). So no "as discussed above", no repo-internal
references, no "we" about your team. Good ones answer what someone types into a
search box: "idempotent Stripe webhooks", "Neon connection pooling on Vercel".
Bad ones restate the vendor's quickstart.

The gate covers three of the six parts of
[the agentic layer](/docs/the-agentic-layer). Agents, hooks and MCP servers are
optional. Ship them when your battery needs them: Neon ships a hook and an
agent, PostHog ships an agent, and 9 batteries ship an MCP server.

## Two rules that trip people up

**Never ship a merger-owned file in `template/`.** Two plugins writing the same
path is a validation error. These eight are built by the mergers, and you add to
them through `manifest.yaml` instead (`contributes.dependencies`, `.scripts`,
`.env`, `.mcp`, `.gitignore`, `.files`):

`package.json` · `tsconfig.json` · `.mcp.json` · `.claude/settings.json` ·
`CLAUDE.md` · `README.md` · `.env.example` · `.gitignore`

**Plug into the app through slots, never by editing its pages.** A page in
the signed-in app gets its sidebar entry from the `app-nav` slot and its
dashboard card from `dashboard-cards`. A landing section goes in
`landing-sections`, and a vendor that receives user data adds itself to the
privacy policy through `legal-processors`. The full slot table is in
`registry/README.md`.

**Never hard-code a package manager or a colour.** Use `{{pm}}`, `{{pmx}}`,
`{{pmDlx}}`, `{{pmRun}}` and `{{pmAdd}}` in every template file, script value
and markdown body. `{{pmx}}` runs a binary the repo installed. `{{pmDlx}}`
fetches a one-off tool. Use design tokens for anything visual. The template
lint fails on both. See [the token contract](/docs/designs).

## The commands

There is no CI here and none in generated repos. That's a choice. These run on
your machine, and they are the whole review. Please actually run them.

This repo pins Bun (`packageManager: bun@1.3.5`) and its scripts call `bun`
directly, so unlike a generated repo, these are Bun only:


```sh
bun run validate
```


Manifest schema, path collisions, slots, the template lint and the battery
gate. Fast enough to run after every edit.


```sh
bun run combos --battery=<id>
```


Generates your battery alone and in every pair it can join, in memory. Then it
checks the output: packages nothing installs, imports that point nowhere, tokens
and slots left unfilled, env vars nothing declares. Takes seconds. Add
`--tier=coupled` for the full product of the categories that share modules.


```sh
bun run matrix --battery <id> --pairs --build --add-tested
```


Runs your battery alone, in every pair it can join, and in any preset or
curated combo that has it. For each one: install, typecheck, lint, unit tests, `next build` with no env
set, then boot the app and load every static route. Pairs that pass go into
`registry/tested.yaml`. Leave out `--pairs` and no pair runs, so nothing new
gets certified.

If your battery touches sign-in, billing, the database or the admin pages, run
the lanes too:


```sh
bun run matrix --battery <id> --browser
```


Each combo gets a fresh database on local Postgres, the repo's own migrations
and seeds, a build with that env, and then the repo's own Playwright specs:
sign-in, the app shell, checkout and the admin pages. `--db` alone stops before
the browser. See [how the generator works](/docs/how-it-works).

**Never hand-edit `tested.yaml`.** A pair in that file claims the combination
was installed, checked, built and booted. The resolver believes it completely,
so a line added by hand is how a stranger ends up with a repo that doesn't boot.


```sh
bun run snapshot
```


Regenerates every preset and compares hashes. If a preset that doesn't include
your battery changed, you touched something shared. Look hard at the diff
before you explain it away.

`bun run release-check` runs `validate`, `combos`, `snapshot` and
`matrix --build` in order.

## Designs and presets

A **design** ships `design.yaml`, a light and a dark palette, its own five core
components, three preview screens and a `DESIGN.md` written for an agent. Nirali reviews design pull requests. See
[designs](/docs/designs).

A **preset** is `registry/presets/<id>.json`, matching the `Preset` type.
Presets become pages, so `description` is two to three real paragraphs and
`highlights` four to six concrete bullets. The matrix runs every preset as a
whole.

## Ownership

Every manifest has an `owner`: your GitHub handle. It says who decides whether a
change to the plugin is right, and who the maintainers go to first when the
vendor ships a breaking change. Handing a plugin over means changing `owner` in
the same pull request. A stale owner is worse than none.

Nothing pings the owner automatically yet. If you open an issue about a
plugin, tag its owner.

Ravi reviews core, the CLI and agent-layer quality. Expect the review to be
mostly about the six layers, because that is where the product is.


---

Agentic Boilerplate: A Next.js repo your agent already knows. Free during launch, then $99 once.

- Site map for agents: https://agenticboilerplate.com/llms.txt
- Public API: https://agenticboilerplate.com/openapi.json
- Contact: agenticstudio@gmail.com
