Files
vercel__chat/apps/docs/content/adapters/official/github.mdx
Ben Sabic 79227ae991 docs: refresh adapter pages with hand-authored MDX (#474)
## Summary

Refreshes the adapter docs end-to-end so every adapter — official,
vendor-official, and community — now ships hand-authored MDX, lives
under a clean URL structure, and renders on a polished
sidebar/right-rail layout dedicated to `/adapters` (the shared `/docs`
chrome is untouched).

```mermaid
flowchart LR
  subgraph Before
    direction TB
    OB[official] --> CB[community<br/>incl. 5 vendor pages]
  end
  subgraph After
    direction TB
    OA[official] --> VA[vendor-official<br/>5 pages] --> CA[community]
  end
  Before -.-> After
```

### Content & routing

- **New `/adapters/vendor-official/<slug>` route** for vendor-maintained
adapters (Beeper Matrix, Photon iMessage, Liveblocks, Resend, Zernio).
Sidebar gets a third labelled group ("Vendor-Official Adapters") between
Official and Community, with a top divider matching the existing
Community treatment.
- **All 13 vendor-official + community adapters migrated** from runtime
README fetching to hand-authored MDX with rich `features:` matrices and
full body content (install, quick start, configuration, auth,
gateway/streaming, troubleshooting). README fetch stays as a fallback
for any future community adapter that hasn't been migrated yet, gated by
a new `mdxBody: true` frontmatter flag.
- **Messenger filter pages removed** (`/adapters/for/<messenger>` + the
"Browse by messenger" chip row on `/adapters`). Existing URLs
308-redirect to `/adapters`.
- **Permanent redirects** from
`/adapters/community/{matrix,imessage,resend,zernio,liveblocks}` to
their new `/adapters/vendor-official/...` paths.
- **Fixed** `/docs/adapters` and `/docs/state` so the bare pages are
accessible again — the previous catch-all redirect (`:slug*`) was
swallowing them. Switched to `:slug+` so subpath URLs still 308 while
the bare pages render.

### Visual polish

- **Adapter-only sidebar variant** (`AdaptersDocsLayout` +
`AdaptersSidebar`) with uppercase eyebrow separators, tighter rows, and
a thin themed scrollbar utility class. The shared `/docs` sidebar is
untouched.
- **Restyled `AdapterHero`**: drops the badges row + packageName, sits
the title inline with the logo, larger 17 px tagline, horizontal divider
beneath the block.
- **Restyled `PackageInstall`** as a tabbed dark single-line snippet
with a `$` prompt prefix and a copy button — replaces the previous
multi-line `CodeBlock` layout.
- **New "Deploy your chat app on Vercel" upsell card** (`<Upsell />`)
replaces the old `EditSource / ScrollTop / Feedback / CopyPage` footer
cluster on every adapter detail page.
- **Listing & messenger pages**: align the H1 to a tighter `text-4xl
sm:text-[44px]`, and the section headers to `text-base font-medium
tracking-tight` with a one-line muted lede.

### Tooling & tests

- Added `mdxBody: true` opt-in to the adapter frontmatter schema
(`source.config.ts`), and updated both detail-page handlers
(`community/[slug]` and the new `vendor-official/[slug]`) to render the
MDX body when present, falling back to README fetch otherwise.
- Refactored both detail-page handlers to flatten the body-render
branches into a `renderBody()` helper, removing the nested ternaries
that were tripping `lint/style/noNestedTernary`.
- New test file
[`packages/integration-tests/src/docs-adapters.test.ts`](https://github.com/vercel/chat/blob/docs/refresh-adapters/packages/integration-tests/src/docs-adapters.test.ts)
— **220 new assertions** covering:
- Adapter MDX frontmatter completeness, slug ↔ filename consistency, and
`type ∈ {platform, state}`.
- Vendor-official invariants: exactly the expected slugs,
`vendorOfficial: true`, `community: true`, `author`, `mdxBody: true`,
`<FeatureSupport />` rendered.
- Community invariants: `community: true` (never vendor-official),
`mdxBody: true`, `<FeatureSupport />`.
- Official invariants: never flagged, `packageName` always under
`@chat-adapter/*`.
- `adapters.json` ↔ MDX sync on `packageName` / `type` / `community` /
`vendorOfficial`.
- Extended `VALID_DOC_PACKAGES` so `docs-content.test.ts` accepts the
new vendor-official + community packages, plus `@chat-adapter/web`,
`@chat-adapter/web/react`, and `@chat-adapter/messenger`.

### Per-package AGENTS.md

- Added `AGENTS.md` to every official adapter and state adapter (14
packages), each tailored to that adapter's surface — overview, directory
layout, build/test commands, public exports, thread ID format, webhook
flow, authentication, format conversion, cards/streaming, platform
quirks, testing approach, coding conventions, and release rules.
- Added a one-line `CLAUDE.md` (`@AGENTS.md`) beside each so Claude Code
picks up the same instructions through its built-in resolver — same
convention as the root.

### Web adapter copy

- Cleaned up the Web adapter tagline (removed inline backticks) and
dropped the now-redundant "v1 scope" section from the body.

---------

Co-authored-by: Ben Sabic <bensabic@users.noreply.github.com>
2026-05-12 16:01:19 +10:00

248 lines
6.6 KiB
Plaintext

---
title: GitHub
description: Respond to @mentions in PR and issue comment threads.
packageName: "@chat-adapter/github"
slug: github
type: platform
logo: github
tagline: Build bots that respond to pull request and issue comment threads. Treats issues and PRs as threads, comments as messages.
beta: true
features:
postMessage: yes
editMessage: yes
deleteMessage: yes
fileUploads: no
streaming:
status: partial
label: Buffered
scheduledMessages: no
cardFormat:
status: yes
label: GFM Markdown
buttons: no
linkButtons: no
selectMenus: no
tables:
status: yes
label: GFM
fields: yes
imagesInCards: yes
modals: no
slashCommands: no
mentions: yes
addReactions: yes
removeReactions:
status: partial
label: ""
typingIndicator: no
directMessages: no
ephemeralMessages: no
userLookup: yes
parentSubject: yes
nativeClient: yes
customApiEndpoint: yes
fetchMessages: yes
fetchSingleMessage: no
fetchThreadInfo: yes
fetchChannelMessages: yes
listThreads: yes
fetchChannelInfo: yes
postChannelMessage: no
---
## Install
<PackageInstall package="@chat-adapter/github" />
## Quick start
<Callout type="info">
The adapter auto-detects credentials from `GITHUB_TOKEN` (or `GITHUB_APP_ID`/`GITHUB_PRIVATE_KEY`), `GITHUB_WEBHOOK_SECRET`, and `GITHUB_BOT_USERNAME`.
</Callout>
```typescript title="lib/bot.ts" lineNumbers
import { Chat } from "chat";
import { createGitHubAdapter } from "@chat-adapter/github";
const bot = new Chat({
userName: "my-bot",
adapters: {
github: createGitHubAdapter(),
},
});
bot.onNewMention(async (thread, message) => {
await thread.post("Hello from GitHub!");
});
```
## Configuration
<TypeTable
type={{
token: {
type: "string",
description:
"Personal Access Token. Auto-detected from `GITHUB_TOKEN`.",
},
appId: {
type: "string | number",
description: "GitHub App ID. Auto-detected from `GITHUB_APP_ID`.",
},
privateKey: {
type: "string",
description:
"GitHub App private key (PEM). Auto-detected from `GITHUB_PRIVATE_KEY`.",
},
installationId: {
type: "number",
description:
"Installation ID. Omit for multi-tenant setups so the adapter resolves it from each webhook.",
},
webhookSecret: {
type: "string",
description:
"Webhook secret. Auto-detected from `GITHUB_WEBHOOK_SECRET`.",
},
userName: {
type: "string",
default: '"github-bot"',
description:
"Bot username for @mention detection. Auto-detected from `GITHUB_BOT_USERNAME`.",
},
apiUrl: {
type: "string",
description:
"Override the GitHub API base URL (e.g. for GitHub Enterprise Server).",
},
}}
/>
Either `token` or `appId`+`privateKey` is required, plus `webhookSecret`.
## Authentication
### Option A — Personal Access Token
Best for personal projects, testing, or single-repo bots.
1. Go to [Settings then Developer settings then Personal access tokens](https://github.com/settings/tokens).
2. Create a token with `repo` scope.
3. Set `GITHUB_TOKEN`.
```typescript
createGitHubAdapter({
token: process.env.GITHUB_TOKEN!,
});
```
### Option B — GitHub App (recommended)
Better rate limits, security, and supports multiple installations.
**Create the app:**
1. Go to [Settings then Developer settings then GitHub Apps then New GitHub App](https://github.com/settings/apps/new).
2. Set **Webhook URL** to `https://your-domain.com/api/webhooks/github`.
3. Set a **Webhook secret**.
4. Permissions: Issues — Read & write, Pull requests — Read & write, Metadata — Read-only.
5. Subscribe to events: Issue comment, Pull request review comment.
6. Click **Create GitHub App** and generate a private key.
**Install the app:**
1. From your app's settings click **Install App** and choose repositories.
2. Note the **Installation ID** in the URL: `https://github.com/settings/installations/12345678`.
**Single-tenant config:**
```typescript
createGitHubAdapter({
appId: process.env.GITHUB_APP_ID!,
privateKey: process.env.GITHUB_PRIVATE_KEY!,
installationId: parseInt(process.env.GITHUB_INSTALLATION_ID!, 10),
});
```
**Multi-tenant** (omit `installationId`):
```typescript
createGitHubAdapter({
appId: process.env.GITHUB_APP_ID!,
privateKey: process.env.GITHUB_PRIVATE_KEY!,
});
```
The adapter automatically extracts installation IDs from webhooks and caches API clients per-installation.
## Advanced
### Installation lookup
Resolve the GitHub App installation ID associated with a `Thread` or `Message`:
```typescript
bot.onNewMention(async (thread, message) => {
const installationIdFromThread = await github.getInstallationId(thread);
const installationIdFromMessage = await github.getInstallationId(
message.threadId
);
});
```
- **PAT mode** — returns `undefined`.
- **Single-tenant GitHub App** — returns the configured installation ID.
- **Multi-tenant** — only succeeds after the adapter has received a webhook for that repository and cached the mapping. Use a persistent state adapter so the mapping survives restarts.
### Direct API client
Access the underlying [Octokit](https://github.com/octokit/octokit.js) instance via `.client`:
```typescript
const github = bot.getAdapter("github").client;
const { data: pulls } = await github.rest.pulls.list({
owner: "vercel",
repo: "chat",
state: "open",
});
```
PAT and single-tenant App modes return the same client anywhere. Multi-tenant mode requires webhook-handler context — calling `.client` outside a handler throws.
### Webhook setup
For repository or organization webhooks:
1. **Settings** then **Webhooks** then **Add webhook**.
2. Set payload URL to `https://your-domain.com/api/webhooks/github`.
3. Set **Content type** to `application/json` (the default `application/x-www-form-urlencoded` does not work).
4. Set **Secret** to match `webhookSecret`.
5. Select events: Issue comments, Pull request review comments.
GitHub App webhooks are configured during app creation — make sure to select `application/json`.
### Thread model
| Type | Context | Thread ID format |
|------|---------|-----------------|
| PR-level | PR Conversation tab | `github:{owner}/{repo}:{prNumber}` |
| Review comments | PR Files Changed tab | `github:{owner}/{repo}:{prNumber}:rc:{commentId}` |
| Issue comments | Issue thread | `github:{owner}/{repo}:issue:{issueNumber}` |
### Reactions
| SDK emoji | GitHub reaction |
|-----------|----------------|
| `thumbs_up` | +1 |
| `thumbs_down` | -1 |
| `laugh` | laugh |
| `confused` | confused |
| `heart` | heart |
| `hooray` | hooray |
| `rocket` | rocket |
| `eyes` | eyes |
## Feature support
<FeatureSupport />