---
title: "Write a provider"
description: "Add a forge by declaring each operation once."
canonical_url: "https://forges.link/contributing/write-a-provider"
---
# Write a provider

> Add a forge by declaring each operation once.

If you want `forges` to support another forge, you write a provider for it. A provider is a single call to `defineForgeProvider()`, and you describe what the forge can do by declaring each operation once. You write `verb(support, run)` for an operation, or `perKind(kinds, run)` when support depends on the kind of thread. Each declaration produces two things at the same time, the method itself and its entry in the capabilities, so the two stay in sync.

The building blocks come from `forges/kit`, which the [provider kit](https://forges.link/contributing/provider-kit) lists in full. It includes `defineForgeProvider()`, `verb()` and `perKind()`, the helpers for fetching and pagination, normalisers for events, reactions, merge errors and file contents, builders for web links and the helpers for webhook signatures. Code that only uses providers imports from `forges` instead.

```ts
import { defineForgeProvider, perKind, verb } from 'forges/kit'
```

The following excerpt comes from the `setup()` of a provider. Reading issues isn't verified against the forge yet, and `getMany` isn't supported at all:

```ts
const threads = {
  get: perKind({ issue: 'unverified' }, getIssue),
  listPage: perKind({ issue: 'unverified' }, listIssues),
  getMany: verb(false, async () => []),
}
```

You only describe what is specific to the forge. `forges` adds the rest of the provider for you: `capabilities`, `can()`, the iterables (`list` from `listPage`, for example), `readOnly`, the handling of anonymous providers, and a `webhooks.ingest()` that verifies each delivery before it translates it.

## Declare operations

[`ProviderSpec`](https://forges.link/contributing/provider-kit#providerspec) lists every operation and marks the ones that are required. If your forge lacks a required operation, declare it with `verb(false, ...)`. Any other operation that you leave out is `false`, and so is any thread kind that you don't list.

For an example to read, [`src/pushin/index.ts`](https://github.com/danielroe/forges/blob/main/src/pushin/index.ts) is a short provider.

## Handle webhooks

The webhook handlers go in the `webhooks` field of the definition. If you want a Lite variant for browsers, define a second factory from the same definition without `webhooks`.

## Send requests

Send your requests with `ctx.fetcher` and not with `fetch` directly. It applies the base URL, the auth header, the user agent, the timeout and the `fetch` of the caller, and it maps rate limits and revoked tokens to the errors of `forges`.

## Finish the provider

After you change the capabilities of a provider, run the following command. It updates the [capability matrix](https://forges.link/reference/capability-matrix), the [providers index](https://forges.link/providers) and the table on each provider page:

```sh
pnpm capability-matrix
```

To see which capabilities your branch adds, removes or changes, compare it with `main`:

```sh
pnpm capability-diff
```

On a pull request, a workflow adds the same comparison to the description, between `<!-- forges:capabilities:start -->` and `<!-- forges:capabilities:end -->`, and keeps it up to date as you push. Its columns show each provider's logo from `assets/providers/<slug>.svg`, so add one for a new provider, with the same `<style>` as the others so that it shows in light and dark themes.

A capability can only be `true` once a test calls it, so the next step is to [record fixtures](https://forges.link/contributing/record-fixtures) for your forge. Because source files import each other with `.ts` extensions, you can also run any script with `node scripts/<name>.ts` without building first.


## Sitemap

See the full [sitemap](https://forges.link/sitemap.md) for all pages.
