> ## Documentation Index
> Fetch the complete documentation index at: https://docs.deploybaseline.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Adding a provider

> Scaffold a new emulator package, wire it into the CLI, and meet the provider definition of done.

Prefer depth over breadth. A provider that handles the real flows of its official SDK beats one that answers CRUD. Before starting, open a [provider request](https://github.com/deploybaseline/cli/issues/new?template=provider-request.yml) so the scope is agreed.

## Scaffold

**1. Generate the package**

```bash theme={null}
make new-provider NAME=acme
# equivalent to
pnpm new:provider acme
```

The name must be lowercase letters and digits. Pass `--label "Acme API"` to `pnpm new:provider` to set the display label (it defaults to the capitalized name).

**2. Install and build**

```bash theme={null}
pnpm install
pnpm --filter @deploybaseline/acme build test
```

Commit the updated `pnpm-lock.yaml`.

**3. Copy the checklist**

The script prints the provider definition of done. Paste it into your pull request body.

To undo the most recent scaffold, run `pnpm new:provider acme --remove`. It only removes the last provider in the registry, and refuses providers that shipped in 0.14.0, because removing any other slot would shift later ports.

### What the scaffold creates

**Package**

`packages/@deploybaseline/acme/` with:

* `package.json`, `tsconfig.json`, `tsup.config.ts` (entries `src/index.ts`, `src/manifest.ts`, and `src/provider.ts`), `vitest.config.ts` using `providerTestConfig`
* `README.md`, `LICENSE`, `THIRD_PARTY_NOTICES.md`
* `src/manifest.ts`, `src/entities.ts`, `src/store.ts`, `src/index.ts`
* `src/provider.ts`, the process entry the CLI forks: one call to core's `runProvider(manifest)`
* `src/routes/items.ts` (sample routes) and `src/routes/inspector.ts`
* `src/__tests__/coverage.ts` (matrix), `coverage.test.ts` (gate 1), `coverage.setup.ts` (gate 2, in `fail` mode)
* `src/__tests__/acme.sdk.test.ts`, a test skeleton including a `restartService` check and an inspector check

**Wiring**

* Appends a new last slot, with its default range, to `packages/cli/src/registry.ts`
* Runs `pnpm provider-metadata`, which writes the package's `baseline` field and `init.json` and adds it to `packages/cli/src/catalog.generated.json`
* Adds `@deploybaseline/acme` as a `workspace:*` dev dependency of `packages/cli/package.json`, so the CLI in the repository runs the workspace copy (a published CLI pulls it from npm)
* Adds a section to `baseline.config.example.json` (`configuration.test.ts` checks that every service is listed)
* Formats the touched files with Biome and runs `pnpm conformance`

**Docs**

* `docs/acme.mdx`, appended to the Providers group in `docs/docs.json`, including the generated conformance snippet
* `skills/acme/SKILL.md`
* A row in the `README.md` provider table

## Provider definition of done

This is the checklist `scripts/new-provider.mjs` prints:

* [ ] Routes match the vendor's API: paths, shapes, status codes, and error bodies
* [ ] Tests drive the emulator with the official SDK, pinned to an exact version
* [ ] Coverage matrix lists every route; the gate passes in fail mode
* [ ] All state lives in the store; a `restartService` test shows reads match after a restart
* [ ] Seed config documented; `initConfig` in `src/manifest.ts` is a useful starter
* [ ] Inspector page uses the shared UI in core `ui.ts`
* [ ] Docs: README row, `docs/acme.mdx` and its `docs.json` entry, `skills/acme/SKILL.md`, CLI `--help` if it adds flags
* [ ] Vendored specs or schemas have a license check and a `THIRD_PARTY_NOTICES.md` entry
* [ ] npm first publish bootstrap for `@deploybaseline/acme` (a new package name needs a placeholder publish and a trusted publisher, see [Bootstrapping package names](/contributing/releasing.md#bootstrapping-package-names))

> [!NOTE]
>
> The last item is a maintainer task. The release workflow refuses to run while any workspace package is missing from npm. See [Releasing](/contributing/releasing.md).

## Anatomy of a finished provider

`@deploybaseline/resend` is a compact, complete example:

| File | Role |
| - | - |
| `src/manifest.ts` | Cheap metadata; `load()` dynamically imports `./index.js`. Run `pnpm provider-metadata` after changing it |
| `package.json` `baseline`, `init.json` | Generated from the manifest by `pnpm provider-metadata` |
| `src/index.ts` | `resendPlugin` (registers auth middleware and route groups), `seedFromConfig`, the seed config type |
| `src/store.ts` | `getResendStore(store)` returning namespaced, indexed collections (`resend.emails`, `resend.domains`) |
| `src/routes/*.ts` | One file per resource; `inbox.ts` renders the UI with the shared design system |
| `src/__tests__/sdk.e2e.test.ts` | The `resend` SDK, pinned in `devDependencies`, against the emulator over HTTP |
| `src/__tests__/state-restart.test.ts` | Saves and restores a running service and checks reads, idempotency keys, and webhooks |
| `src/__tests__/coverage.ts` | Every registered route with its status |
| `src/__tests__/coverage.setup.ts` | Route gate and spec gate, both in `fail` mode |
| `src/__tests__/spec-allow.ts` | Known differences from the vendored spec, each with a reason |
| `spec/openapi.json` | Trimmed vendor OpenAPI document |

## State rules

* Keep every piece of state in the store: collections, or `store.setData` for maps and flags. Never in module variables or closures inside `register`.
* Namespace collection names with the provider (`resend.emails`).
* Every provider has a `state-restart` test: run a main flow, call `restartService` from `@deploybaseline/testing` (save, then start a fresh instance from the saved JSON on the same port), and check that reads match and tokens still work.
* Bump `stateVersion` in `src/manifest.ts` when an entity shape changes in a way older saved state cannot load.
* Changes to how a runtime saves or loads state must keep the shared contract in `tests/contracts/persistence.js` passing for `createEmulator` and the `start` runner.

## Webhooks and UI

* Sign deliveries with the core helpers (`svixSignature`, `hmacSha256Hex`, and the rest), or a provider's own `signing.ts` for a scheme no other provider uses. See [Architecture](/contributing/architecture.md#webhooks).
* Build inspector, OAuth, and checkout pages with the render functions in `core/src/ui.ts`. See [Shared UI](/contributing/architecture.md#shared-ui).

## GraphQL providers

* Serve the endpoint with `graphqlEndpoint` and build the schema with `buildSchema` from `@deploybaseline/graphql`.
* Start from the vendor's published SDL. `node scripts/vendor-graphql-schema.mjs <name>` fetches it and writes `src/graphql/schema.generated.ts` (descriptions trimmed for size). Add the source to that script with its license, and add a `THIRD_PARTY_NOTICES.md` entry.
* The coverage matrix lists every root field in the schema (`Query.issues`, `Mutation.issueCreate`) next to the routes. A root field without a resolver stays `not_started` and answers "not emulated".

## Composed providers

For several APIs behind one port and seed key, build the plugin with `composeService` (see [Composed services](/contributing/architecture.md#composed-services)):

* Each module registers its routes and declares the namespaced collections it owns.
* Put each module's matrix under its name in `src/__tests__/coverage.ts`: `export const modules = { gmail: [...], drive: [...] }`.
* Check it with `checkModuleCoverage` and pass `modules` to `coverageGate`. A route listed under the wrong module fails, the CI job summary gets one row per module, and `pnpm conformance` publishes per-API counts.
* `node scripts/generate-coverage-matrix.mjs <name>` writes the module layout.

## Before opening the pull request

```bash theme={null}
pnpm --filter "@deploybaseline/acme..." build
node scripts/generate-coverage-matrix.mjs acme   # refresh the matrix from registered routes
make test-provider P=acme
make conformance
make api-reference
make state-fixtures   # save its default state; the CLI tests restore it
make check
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.