Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions .claude/skills/writing-provider-guides/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
---
name: writing-provider-guides
description: Use when creating or updating an Ampersand provider (connector) guide in src/provider-guides/ — adding a new connector doc, extending an existing guide with deep connector support (Read/Write/Subscribe), or fixing a guide's structure, headings, or wording.
---

# Writing Provider Guides

## Overview

Every provider guide in `src/provider-guides/*.mdx` follows one canonical structure with exact, fixed wording. Older guides drifted (title-case headings, unlinked object names, paraphrased sentences) — never imitate an arbitrary existing guide. Copy sentences from [templates.md](templates.md) **verbatim** and fill only the `<angle-bracket>` slots.

**Core principle: the guide is assembled from fixed templates, not written.** Your judgment goes into gathering accurate provider facts, not into phrasing.

## Workflow

1. **Gather required inputs.** Ask the user for any of these you cannot derive:
- Provider display name + slug (slug = folder/file name in the [amp-labs/connectors](https://github.com/amp-labs/connectors) repo, and the mdx filename)
- Connector type: proxy-only or deep
- Auth type: `oauth2_authorization_code` | `oauth2_client_credentials` | `api_key` | `basic_auth` | custom
- Capabilities: subset of read / write / subscribe / proxy
- Base URL (preserve placeholders like `{{.workspace}}`)

Optional (proceed with `<!-- TODO: ... -->` comments if missing): object lists + upstream API reference URLs, dynamic-token explanations, credential-creation steps, screenshots.

2. **Inspect the connectors repo** to confirm/derive the inputs — see "Data gathering" in templates.md. Never fabricate objects, scopes, endpoints, or URLs; prefer a TODO comment over a guess.

3. **Classify the incremental-read pattern** (A: none, B: ≤5 objects, C: all, D: >5 objects) — this selects the exact Read Actions sentence. Only claim incremental support with evidence from code; otherwise use Pattern A plus a TODO.

4. **Assemble the MDX** in the canonical section order from templates.md, choosing the auth-type variants. For **updates to an existing guide**: bring headings/wording of the sections you touch up to the canonical templates; keep factual content (credential steps, screenshots) as-is; move any non-template sections (e.g. "API documentation", "Rate limits") to the end of the file unchanged.

5. **Register navigation** (new guides only): add `"provider-guides/<slug>"` to the "Provider guides" group in `src/generate-docs.ts`, keeping the list alphabetically sorted case-insensitively. Then run `pnpm run gen` (or tell the user to).

6. **Run the verification checklist** below before declaring the guide done.

## Non-negotiable rules

- **Every object bullet is a markdown link**: `- [<objectName>](<upstream API reference URL>)`. If no URL is found after searching the provider's API docs, write `- <objectName> <!-- TODO: Add API reference link -->`. A bare object name with no link and no TODO is a defect.
- **Headings are exact strings** from templates.md — sentence case (`## What's supported`, `### Supported actions`, `## Before you get started`), never title case.
- **Action bullet order**: Read → Subscribe → Write → Proxy. Only supported actions appear. Each bullet ends with a period. The Proxy bullet always carries the base URL in backticks.
- **Fixed URLs**: Ampersand OAuth redirect `https://api.withampersand.com/callbacks/v1/oauth`; dashboard `https://dashboard.withampersand.com`; samples `https://github.com/amp-labs/samples/blob/main/<slug>/amp.yaml`.
- **Example integration is conditional on an observable fact**: if the samples-repo `amp.yaml` for the slug exists (check with `curl -s -o /dev/null -w "%{http_code}" https://raw.githubusercontent.com/amp-labs/samples/main/<slug>/amp.yaml` → 200), use the one-line samples-link template; otherwise use the inline-manifest template. Never emit a samples link you haven't verified.
- **Each dynamic token** (`{{.workspace}}`, `{{.region}}`, …) is explained once under "Before you get started": what it is and where the customer finds it.
- Inline code (backticks) for object names, field names, tokens, and URLs-as-values; `[text](url)` for every navigable link — no raw URLs in prose.
- Imperative voice ("Create…", "Click…"); no future tense; "GitHub" spelled with capital H.
- For deep connectors, treat Read and Write as enabled when implementation files exist in `providers/<slug>/`, even if `Support` flags in the catalog say otherwise.

## Verification checklist (run every time)

```bash
F=src/provider-guides/<slug>.mdx
grep -n "^#" $F # headings match templates.md exactly (sentence case)
sed -n '/### Supported objects/,/### Example integration/p' $F | grep "^- " | grep -v "\[.*\](" | grep -v "TODO" # unlinked object bullets — must output nothing
grep -n "Proxy Actions" $F # base URL present in backticks
grep -c "{{\." $F # every token also explained in Before you get started
```

Then confirm by eye:
- [ ] Section order matches the skeleton in templates.md
- [ ] Read Actions sentence is byte-identical to pattern A/B/C/D
- [ ] amp.yaml example (if inline) contains only supported capabilities
- [ ] "a"/"an" correct before provider name in Example integration line
- [ ] Auth intro + prompt lines match the auth-type table
- [ ] Samples link verified with curl (200) if used
- [ ] New guide registered alphabetically in `src/generate-docs.ts`
- [ ] No fabricated objects, scopes, or URLs; TODOs mark every unknown

## Common mistakes

| Mistake | Fix |
|---|---|
| Copying heading case from an old guide (`## What's Supported`) | Use templates.md headings, not existing guides |
| Object bullets without links | Every bullet: `[name](url)` or name + `<!-- TODO: Add API reference link -->` |
| Paraphrasing the Read Actions sentence | Copy pattern A/B/C/D byte-for-byte, fill slots only |
| Linking samples repo without checking it exists | curl the raw amp.yaml URL first; 404 → inline manifest |
| `## Add <Provider> App Details in Ampersand` as H2 / rephrased | `### Add your <Provider> app info to Ampersand`, nested under "Before you get started" |
| Provider-app instructions for non-OAuth-auth-code providers | Only OAuth2 Authorization Code needs a Provider App; others get the "no Provider App" intro line |
| Forgetting navigation registration | New slug goes into `src/generate-docs.ts`, alphabetical, then `pnpm run gen` |
305 changes: 305 additions & 0 deletions .claude/skills/writing-provider-guides/templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
# Provider Guide Templates

**Copy fixed text verbatim. Fill only `<angle-bracket>` slots. Do not rephrase, reorder, or "improve" fixed sentences.**

## Page skeleton (canonical section order)

```markdown
---
title: "<Provider Display Name>"
---

<optional 1–2 sentence intro — ONLY when the provider needs disambiguation,
e.g. GoTo covering GoToWebinar + GoToMeeting. Most guides have no intro.>

## What's supported

### Supported actions

### Notes ← optional; only when real caveats exist

### Supported objects ← deep connectors only

### Example integration

## Before you get started

### <credential subsections — see auth-type variants below>

## Using the connector

<extra provider-specific sections (API documentation, rate limits, credential
format quirks) — always LAST, after "Using the connector">
```

---

## Supported actions

```markdown
### Supported actions

This connector supports:

- <Read bullet — exactly one of patterns A–D below>
- [Subscribe Actions](/subscribe-actions).
- [Write Actions](/write-actions).
- [Proxy Actions](/proxy-actions), using the base URL `<base URL>`.
```

Rules: order is Read → Subscribe → Write → Proxy; include only supported actions; every bullet ends with a period; Proxy bullet always carries the base URL in backticks (placeholders preserved, e.g. `` `https://rest.{{.restInstanceId}}.braze.com` ``).

### Read bullet — Pattern A: no incremental read

```markdown
- [Read Actions](/read-actions), including full historic backfill. Please note that incremental read is not supported, a full read of the <Provider> instance will be done for each scheduled read.
```

### Read bullet — Pattern B: incremental for ≤5 objects (list inline)

```markdown
- [Read Actions](/read-actions), including full historic backfill. Please note that incremental read is supported only for `<object1>`, `<object2>` and `<object3>` currently. For all other objects, a full read of the <Provider> instance will be done per scheduled read.
```

### Read bullet — Pattern C: incremental for all objects

```markdown
- [Read Actions](/read-actions), including full historic backfill and incremental read for all supported objects.
```

### Read bullet — Pattern D: incremental for >5 objects (annotate object list)

```markdown
- [Read Actions](/read-actions), including full historic backfill. Incremental reading is supported for the objects listed below. For all other objects, a full read of the <Provider> instance will be done per scheduled read.
```

With Pattern D, append ` (supports incremental read)` to each supporting bullet in the read-objects list.

If a Subscribe action needs provider-specific setup, extend its bullet:
```markdown
- [Subscribe Actions](/subscribe-actions). Please note that [special set up](#set-up-subscribe-actions) is needed for <Provider>.
```

---

## Supported objects (deep connectors)

```markdown
### Supported objects

The <Provider> connector supports reading from the following objects:

- [<objectName>](<upstream API reference URL>)
- [<objectName>](<upstream API reference URL>)

The <Provider> connector supports writing to the following objects:

- [<objectName>](<upstream API reference URL>)
```

Rules:
- **REQUIRED:** every bullet is `[name](url)` linking to the provider's API reference for that object. Unknown URL → `- <objectName> <!-- TODO: Add API reference link -->`. Never a bare name.
- Alphabetical order within each list.
- Object names exactly as used in `amp.yaml` (e.g. `email/hard_bounces`, `user/keys`).
- Pattern D: append ` (supports incremental read)` to supporting read bullets.
- If read + write lists are long, `#### Read objects` / `#### Write objects` subheadings may replace the intro sentences (see procore.mdx).
- If the object list is known to be incomplete:
```markdown
> Note: The list below may be incomplete. <!-- TODO: Confirm supported objects -->
```
- Proxy-only connectors: omit this section, or use short prose pointing at the provider's API docs:
```markdown
### Supported objects

<Provider> is supported through Proxy Actions only. Use the proxy to call any [<Provider> API](<api docs URL>) endpoint, for example `GET /v1/projects`.
```

---

## Example integration

**First check** (observable predicate — do not skip):
```bash
curl -s -o /dev/null -w "%{http_code}" https://raw.githubusercontent.com/amp-labs/samples/main/<slug>/amp.yaml
```

**HTTP 200 → samples-link form:**
```markdown
### Example integration

For an example manifest file of a <Provider> integration, visit our [samples repo on GitHub](https://github.com/amp-labs/samples/blob/main/<slug>/amp.yaml).
```
Use "an" instead of "a" when the provider name starts with a vowel sound ("an Outplay integration", "an Asana integration").

**Otherwise → inline-manifest form** (action blocks only for supported capabilities):
```markdown
### Example integration

To define an integration for <Provider>, create a manifest file that looks like this:

```YAML
# amp.yaml
specVersion: 1.0.0
integrations:
- name: <slug>Integration
displayName: My <Provider> Integration
provider: <slug>
read:
objects:
- objectName: <object1>
destination: <destinationName>
write:
objects:
- objectName: <object1>
proxy:
enabled: true
```
```
Proxy-only connectors: keep only the `proxy` block.

---

## Before you get started — auth-type variants

### OAuth2 Authorization Code (Provider App required)

```markdown
## Before you get started

To integrate <Provider> with Ampersand, you will need a [<Provider> account](<signup URL>).

Once your account is created, you'll need to create a <Provider> app and obtain the following credentials from it:

- Client ID
- Client Secret

You will then use these credentials to connect your application to Ampersand.

### Creating a <Provider> app

1. Log in to the [<Provider> developer portal](<URL>).
2. <provider-specific steps…>
3. Set the redirect/callback URL to: `https://api.withampersand.com/callbacks/v1/oauth`
4. <steps to obtain Client ID and Client Secret…>

### Add your <Provider> app info to Ampersand

1. Log in to your [Ampersand Dashboard](https://dashboard.withampersand.com).

2. Select the project where you want to create a <Provider> integration.

![Ampersand Project Selection](/images/provider-guides/<image>)

3. Select **Provider Apps**.

4. Select **<Provider>** from the **Provider** list.

5. Enter the **Client ID** and **Client Secret** obtained from your <Provider> app.

6. Click **Save Changes**.
```

Notes: scopes bullet list goes under "Creating a <Provider> app" if the provider requires selecting scopes. Only reference images that actually exist in `src/images/provider-guides/`; otherwise omit the image line (no fabricated paths).

### API Key / Basic Auth / OAuth2 Client Credentials (no Provider App)

```markdown
## Before you get started

To connect <Provider> with Ampersand, you will need a [<Provider> account](<signup URL>).

### Creating <Provider> credentials

1. <steps to generate the API key / client credentials…>
2. <where to copy each value…>
```

- Section title options: `### Creating an API key for <Provider>`, `### Creating <Provider> credentials` — pick what fits the credential.
- **Each dynamic token gets explained here.** Example (from outplay.mdx): "Note your workspace identifier - this is the subdomain in your <Provider> URL (e.g., if your URL is `https://mycompany-api.outplayhq.com`, your workspace is `mycompany`)."
- Nonstandard Basic Auth mapping (e.g. API key as username, blank password) gets stated explicitly and linked to the provider's auth docs, plus this sentence: "The UI components will display this link, so that your users can successfully provide their credentials." For extensive quirks, add a `## Credential format for <Provider>` section at the end of the file (see connectWise.mdx).

---

## Using the connector

```markdown
## Using the connector

<auth intro line — see table; omitted entirely for OAuth2 Authorization Code>

To start integrating with <Provider>:

- Create a manifest file like the [example above](#example-integration).
- Deploy it using the [amp CLI](/cli/overview).
- If you are using Read Actions, create a [destination](/destinations).
- Embed the [InstallIntegration](/embeddable-ui-components#install-integration) UI component. <auth prompt line — see table>
- Start using the connector!
- If your integration has [Read Actions](/read-actions), you'll start getting webhook messages.
- If your integration has [Write Actions](/write-actions), you can start making API calls to our Write API.
- If your integration has [Proxy Actions](/proxy-actions), you can start making Proxy API calls.
```

Rules:
- Include the destination bullet only if Read is supported.
- Include only the "Start using" sub-bullets for supported actions.
- If Subscribe is supported, the first sub-bullet becomes: `If your integration has [Read Actions](/read-actions) or [Subscribe Actions](/subscribe-actions), you'll start getting webhook messages.`

### Auth intro / prompt lines

| Auth type | `<auth intro line>` | `<auth prompt line>` |
|---|---|---|
| OAuth2 Authorization Code | *(omit)* | The UI component will prompt the customer for OAuth authorization. |
| OAuth2 Client Credentials | This connector uses OAuth2 Client Credentials grant type, which means that you do not need to set up a Provider App before getting started. (Provider apps are only required for providers that use OAuth2 Authorization Code grant type.) | The UI component will prompt the customer for their credentials. |
| API Key | This connector uses API Key auth, which means that you do not need to set up a Provider App before getting started. (Provider apps are only required for providers that use OAuth2 Authorization Code grant type.) | The UI component will prompt the customer for their API key. |
| Basic Auth | This connector uses Basic Auth, which means that you do not need to set up a Provider App before getting started. (Provider apps are only required for providers that use OAuth2 Authorization Code grant type.) | The UI component will prompt the customer for their username and password. |

If the customer must also supply dynamic tokens, extend the prompt line, e.g. "…for their API credentials and workspace location."

### Proxy-only ending variant

For proxy-only connectors, replace the last two bullets ("Embed…", "Start using…") with:

```markdown
- Embed the [InstallIntegration](/embeddable-ui-components#install-integration) UI component. <auth prompt line>
- Start making [Proxy Calls](/proxy-actions), and Ampersand will automatically attach the correct header required by <Basic Auth/API Key auth>. Please note that this connector's base URL is `<base URL>`.
```

For OAuth (either grant type) proxy-only connectors, the last bullet is instead:
```markdown
- Start making [Proxy Calls](/proxy-actions), and Ampersand will automatically handle the authentication with <Provider>.
```

---

## Data gathering — amp-labs/connectors repo

### Catalog entry (all connectors)

Fetch `https://raw.githubusercontent.com/amp-labs/connectors/main/providers/<slug>.go` and read the `SetInfo(<Const>, ProviderInfo{...})` block:
- `DisplayName` → guide title
- `AuthType` (+ `Oauth2Opts.GrantType`) → auth-type variant
- `BaseURL` → Proxy bullet (preserve `{{.placeholders}}`)
- `Support` flags → proxy-only capabilities
- `Metadata` / `PostAuthentication` fields → dynamic tokens to document

If the file is missing on `main`, ask the user for the feature branch and note at the top of the draft: `<!-- Draft based on branch: <branch>; update links after merge -->`

### Deep connectors (folder pattern)

Explore `https://github.com/amp-labs/connectors/tree/main/providers/<slug>`:
- `support.go` / `supports.go`, `schemas.json` → object lists
- read/write handler files → capabilities. **Presence of implementation files wins over `Support` flags** — flags lag behind.
- Incremental cues: `SupportsIncremental` / `IncrementalObjects` maps, or handlers filtering on timestamps (`since`, `updated_at`, `modifiedDate`). Mention the cursor field only if explicitly named in code.
- Objects in code override `schemas.json`; note conflicts with a TODO.

### Upstream API reference links

For each object, find the provider's API reference page for that resource (try `developers.<domain>`, `docs.<domain>`, `developer.<domain>`). Link the closest resource-level page. Nothing found → `<!-- TODO: Add API reference link -->`. Never invent URL paths.

---

## Navigation registration (new guides)

1. In `src/generate-docs.ts`, find the `group: "Provider guides"` block.
2. Insert `"provider-guides/<slug>",` keeping case-insensitive alphabetical order; one entry per line, double quotes, trailing comma.
3. Run `pnpm run gen`. If the user asked for no build, remind them to run it later.
1 change: 1 addition & 0 deletions src/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@
"provider-guides/snapchatAds",
"provider-guides/snowflake",
"provider-guides/solarwindsServiceDesk",
"provider-guides/square",
"provider-guides/stripe",
"provider-guides/superSend",
"provider-guides/surveyMonkey",
Expand Down
Loading
Loading