diff --git a/apps/docs/app/[lang]/(home)/page.tsx b/apps/docs/app/[lang]/(home)/page.tsx
index 82afb998..1c6735b1 100644
--- a/apps/docs/app/[lang]/(home)/page.tsx
+++ b/apps/docs/app/[lang]/(home)/page.tsx
@@ -132,8 +132,30 @@ const textGridSection = [
},
];
+const jsonLd = {
+ "@context": "https://schema.org",
+ "@type": "SoftwareSourceCode",
+ name: "Chat SDK",
+ description: textDescription,
+ url: "https://chat-sdk.dev",
+ codeRepository: "https://github.com/vercel/chat",
+ programmingLanguage: "TypeScript",
+ runtimePlatform: "Node.js",
+ license: "https://opensource.org/licenses/Apache-2.0",
+ author: {
+ "@type": "Organization",
+ name: "Vercel",
+ url: "https://vercel.com",
+ },
+};
+
const HomePage = () => (
+
{
export const config = {
// Matcher ignoring `/_next/`, `/api/`, static assets, favicon, sitemap, robots, etc.
matcher: [
- "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
+ "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|AGENTS.md|\\.well-known).*)",
],
};
diff --git a/apps/docs/public/.well-known/agent-skills/chat-sdk/SKILL.md b/apps/docs/public/.well-known/agent-skills/chat-sdk/SKILL.md
new file mode 100644
index 00000000..b1bfc88e
--- /dev/null
+++ b/apps/docs/public/.well-known/agent-skills/chat-sdk/SKILL.md
@@ -0,0 +1,203 @@
+---
+name: chat-sdk
+description: Build multi-platform chat bots with Chat SDK (`chat` npm package). Use when developers want to build a Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, or WhatsApp bot, handle mentions, direct messages, subscribed threads, reactions, slash commands, cards, modals, files, or AI streaming, set up webhook routes or multi-adapter bots, send rich cards or streamed AI responses to chat platforms, or build a custom adapter or state adapter.
+---
+
+# Chat SDK
+
+Unified TypeScript SDK for building chat bots across Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, and WhatsApp. Write bot logic once, deploy everywhere.
+
+## Start with published sources
+
+When Chat SDK is installed in a user project, inspect the published files that ship in `node_modules`:
+
+```
+node_modules/chat/docs/ # bundled docs
+node_modules/chat/dist/index.d.ts # core API types
+node_modules/chat/dist/jsx-runtime.d.ts # JSX runtime types
+node_modules/chat/docs/contributing/ # adapter-authoring docs
+node_modules/chat/docs/guides/ # framework/platform guides
+```
+
+If one of the paths below does not exist, that package is not installed in the project yet.
+
+Read these before writing code:
+- `node_modules/chat/docs/getting-started.mdx` — install and setup
+- `node_modules/chat/docs/usage.mdx` — `Chat` config and lifecycle
+- `node_modules/chat/docs/handling-events.mdx` — event routing and handlers
+- `node_modules/chat/docs/threads-messages-channels.mdx` — thread/channel/message model
+- `node_modules/chat/docs/posting-messages.mdx` — post, edit, delete, schedule
+- `node_modules/chat/docs/streaming.mdx` — AI SDK integration and streaming semantics
+- `node_modules/chat/docs/cards.mdx` — JSX cards
+- `node_modules/chat/docs/actions.mdx` — button/select interactions
+- `node_modules/chat/docs/modals.mdx` — modal submit/close flows
+- `node_modules/chat/docs/slash-commands.mdx` — slash command routing
+- `node_modules/chat/docs/direct-messages.mdx` — DM behavior and `openDM()`
+- `node_modules/chat/docs/files.mdx` — attachments/uploads
+- `node_modules/chat/docs/state.mdx` — persistence, locking, dedupe
+- `node_modules/chat/docs/adapters.mdx` — cross-platform feature matrix
+- `node_modules/chat/docs/api/chat.mdx` — exact `Chat` API
+- `node_modules/chat/docs/api/thread.mdx` — exact `Thread` API
+- `node_modules/chat/docs/api/message.mdx` — exact `Message` API
+- `node_modules/chat/docs/api/modals.mdx` — modal element and event details
+
+For the specific adapter or state package you are using, inspect that installed package's `dist/index.d.ts` export surface in `node_modules`.
+
+## Quick start
+
+```typescript
+import { Chat } from "chat";
+import { createSlackAdapter } from "@chat-adapter/slack";
+import { createRedisState } from "@chat-adapter/state-redis";
+
+const bot = new Chat({
+ userName: "mybot",
+ adapters: {
+ slack: createSlackAdapter(),
+ },
+ state: createRedisState(),
+ dedupeTtlMs: 600_000,
+});
+
+bot.onNewMention(async (thread) => {
+ await thread.subscribe();
+ await thread.post("Hello! I'm listening to this thread.");
+});
+
+bot.onSubscribedMessage(async (thread, message) => {
+ await thread.post(`You said: ${message.text}`);
+});
+```
+
+## Core concepts
+
+- **Chat** — main entry point; coordinates adapters, routing, locks, and state
+- **Adapters** — platform-specific integrations for Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, and WhatsApp
+- **State adapters** — persistence for subscriptions, locks, dedupe, and thread state
+- **Thread** — conversation context with `post()`, `stream()`, `subscribe()`, `setState()`, `startTyping()`
+- **Message** — normalized content with `text`, `formatted`, attachments, author info, and platform `raw`
+- **Channel** — container for threads and top-level posts
+
+## Event handlers
+
+| Handler | Trigger |
+|---------|---------|
+| `onNewMention` | Bot @-mentioned in an unsubscribed thread |
+| `onDirectMessage` | New DM in an unsubscribed DM thread |
+| `onSubscribedMessage` | Any message in a subscribed thread |
+| `onNewMessage(regex)` | Regex match in an unsubscribed thread |
+| `onReaction(emojis?)` | Emoji added or removed |
+| `onAction(actionIds?)` | Button clicks and select/radio interactions |
+| `onModalSubmit(callbackId?)` | Modal form submitted |
+| `onModalClose(callbackId?)` | Modal dismissed/cancelled |
+| `onSlashCommand(commands?)` | Slash command invocation |
+| `onAssistantThreadStarted` | Slack assistant thread opened |
+| `onAssistantContextChanged` | Slack assistant context changed |
+| `onAppHomeOpened` | Slack App Home opened |
+| `onMemberJoinedChannel` | Slack member joined channel event |
+
+Read `node_modules/chat/docs/handling-events.mdx`, `node_modules/chat/docs/actions.mdx`, `node_modules/chat/docs/modals.mdx`, and `node_modules/chat/docs/slash-commands.mdx` before wiring handlers. `onDirectMessage` behavior is documented in `node_modules/chat/docs/direct-messages.mdx`.
+
+## Streaming
+
+Pass any `AsyncIterable` to `thread.post()` or `thread.stream()`. For AI SDK, prefer `result.fullStream` over `result.textStream` when available so step boundaries are preserved.
+
+```typescript
+import { ToolLoopAgent } from "ai";
+
+const agent = new ToolLoopAgent({ model: "anthropic/claude-4.5-sonnet" });
+
+bot.onNewMention(async (thread, message) => {
+ const result = await agent.stream({ prompt: message.text });
+ await thread.post(result.fullStream);
+});
+```
+
+Key details:
+- `streamingUpdateIntervalMs` controls post+edit fallback cadence
+- `fallbackStreamingPlaceholderText` defaults to `"..."`; set `null` to disable
+- Structured `StreamChunk` support is Slack-only; other adapters ignore non-text chunks
+
+## Cards and modals (JSX)
+
+Set `jsxImportSource: "chat"` in `tsconfig.json`.
+
+Card components:
+- `Card`, `CardText`, `Section`, `Fields`, `Field`, `Button`, `CardLink`, `LinkButton`, `Actions`, `Select`, `SelectOption`, `RadioSelect`, `Table`, `Image`, `Divider`
+
+Modal components:
+- `Modal`, `TextInput`, `Select`, `SelectOption`, `RadioSelect`
+
+```tsx
+await thread.post(
+
+ Your order has been received.
+
+
+
+
+
+);
+```
+
+## Adapter inventory
+
+### Official platform adapters
+
+| Platform | Package | Factory |
+|---------|---------|---------|
+| Slack | `@chat-adapter/slack` | `createSlackAdapter` |
+| Microsoft Teams | `@chat-adapter/teams` | `createTeamsAdapter` |
+| Google Chat | `@chat-adapter/gchat` | `createGoogleChatAdapter` |
+| Discord | `@chat-adapter/discord` | `createDiscordAdapter` |
+| GitHub | `@chat-adapter/github` | `createGitHubAdapter` |
+| Linear | `@chat-adapter/linear` | `createLinearAdapter` |
+| Telegram | `@chat-adapter/telegram` | `createTelegramAdapter` |
+| WhatsApp Business Cloud | `@chat-adapter/whatsapp` | `createWhatsAppAdapter` |
+
+### Official state adapters
+
+| State backend | Package | Factory |
+|--------------|---------|---------|
+| Redis | `@chat-adapter/state-redis` | `createRedisState` |
+| ioredis | `@chat-adapter/state-ioredis` | `createIoRedisState` |
+| PostgreSQL | `@chat-adapter/state-pg` | `createPostgresState` |
+| Memory | `@chat-adapter/state-memory` | `createMemoryState` |
+
+### Community adapters
+
+- `chat-state-cloudflare-do`
+- `@beeper/chat-adapter-matrix`
+- `chat-adapter-imessage`
+- `@bitbasti/chat-adapter-webex`
+- `@resend/chat-sdk-adapter`
+- `@zernio/chat-sdk-adapter`
+- `chat-adapter-baileys`
+- `@liveblocks/chat-sdk-adapter`
+- `chat-adapter-sendblue`
+- `chat-adapter-zalo`
+
+### Coming-soon platform entries
+
+- Instagram
+- Signal
+- X
+- Messenger
+
+## Building a custom adapter
+
+Read these published docs first:
+- `node_modules/chat/docs/contributing/building.mdx`
+- `node_modules/chat/docs/contributing/testing.mdx`
+- `node_modules/chat/docs/contributing/publishing.mdx`
+
+Also inspect:
+- `node_modules/chat/dist/index.d.ts` — `Adapter` and related interfaces
+- `node_modules/@chat-adapter/shared/dist/index.d.ts` — shared errors and utilities
+- Installed official adapter `dist/index.d.ts` files — reference implementations for config and APIs
+
+A custom adapter needs request verification, webhook parsing, message/thread/channel operations, ID encoding/decoding, and a format converter. Use `BaseFormatConverter` from `chat` and shared utilities from `@chat-adapter/shared`.
+
+## Webhook setup
+
+Each registered adapter exposes `bot.webhooks.`. Wire those directly to your HTTP framework routes. See `node_modules/chat/docs/guides/slack-nextjs.mdx` and `node_modules/chat/docs/guides/discord-nuxt.mdx` for framework-specific route patterns.
diff --git a/apps/docs/public/.well-known/agent-skills/index.json b/apps/docs/public/.well-known/agent-skills/index.json
new file mode 100644
index 00000000..5f45471d
--- /dev/null
+++ b/apps/docs/public/.well-known/agent-skills/index.json
@@ -0,0 +1,11 @@
+{
+ "skills": [
+ {
+ "name": "chat-sdk",
+ "type": "skill-md",
+ "description": "Build multi-platform chat bots with Chat SDK (`chat` npm package). Use when developers want to build a Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, or WhatsApp bot with a single TypeScript codebase.",
+ "url": "/.well-known/agent-skills/chat-sdk/SKILL.md",
+ "digest": "sha256:2a83553c6351ee766e3d58eeefa99240ac37af091b63df8844b06e893c87cdb9"
+ }
+ ]
+}
diff --git a/apps/docs/public/AGENTS.md b/apps/docs/public/AGENTS.md
new file mode 100644
index 00000000..b1bfc88e
--- /dev/null
+++ b/apps/docs/public/AGENTS.md
@@ -0,0 +1,203 @@
+---
+name: chat-sdk
+description: Build multi-platform chat bots with Chat SDK (`chat` npm package). Use when developers want to build a Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, or WhatsApp bot, handle mentions, direct messages, subscribed threads, reactions, slash commands, cards, modals, files, or AI streaming, set up webhook routes or multi-adapter bots, send rich cards or streamed AI responses to chat platforms, or build a custom adapter or state adapter.
+---
+
+# Chat SDK
+
+Unified TypeScript SDK for building chat bots across Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, and WhatsApp. Write bot logic once, deploy everywhere.
+
+## Start with published sources
+
+When Chat SDK is installed in a user project, inspect the published files that ship in `node_modules`:
+
+```
+node_modules/chat/docs/ # bundled docs
+node_modules/chat/dist/index.d.ts # core API types
+node_modules/chat/dist/jsx-runtime.d.ts # JSX runtime types
+node_modules/chat/docs/contributing/ # adapter-authoring docs
+node_modules/chat/docs/guides/ # framework/platform guides
+```
+
+If one of the paths below does not exist, that package is not installed in the project yet.
+
+Read these before writing code:
+- `node_modules/chat/docs/getting-started.mdx` — install and setup
+- `node_modules/chat/docs/usage.mdx` — `Chat` config and lifecycle
+- `node_modules/chat/docs/handling-events.mdx` — event routing and handlers
+- `node_modules/chat/docs/threads-messages-channels.mdx` — thread/channel/message model
+- `node_modules/chat/docs/posting-messages.mdx` — post, edit, delete, schedule
+- `node_modules/chat/docs/streaming.mdx` — AI SDK integration and streaming semantics
+- `node_modules/chat/docs/cards.mdx` — JSX cards
+- `node_modules/chat/docs/actions.mdx` — button/select interactions
+- `node_modules/chat/docs/modals.mdx` — modal submit/close flows
+- `node_modules/chat/docs/slash-commands.mdx` — slash command routing
+- `node_modules/chat/docs/direct-messages.mdx` — DM behavior and `openDM()`
+- `node_modules/chat/docs/files.mdx` — attachments/uploads
+- `node_modules/chat/docs/state.mdx` — persistence, locking, dedupe
+- `node_modules/chat/docs/adapters.mdx` — cross-platform feature matrix
+- `node_modules/chat/docs/api/chat.mdx` — exact `Chat` API
+- `node_modules/chat/docs/api/thread.mdx` — exact `Thread` API
+- `node_modules/chat/docs/api/message.mdx` — exact `Message` API
+- `node_modules/chat/docs/api/modals.mdx` — modal element and event details
+
+For the specific adapter or state package you are using, inspect that installed package's `dist/index.d.ts` export surface in `node_modules`.
+
+## Quick start
+
+```typescript
+import { Chat } from "chat";
+import { createSlackAdapter } from "@chat-adapter/slack";
+import { createRedisState } from "@chat-adapter/state-redis";
+
+const bot = new Chat({
+ userName: "mybot",
+ adapters: {
+ slack: createSlackAdapter(),
+ },
+ state: createRedisState(),
+ dedupeTtlMs: 600_000,
+});
+
+bot.onNewMention(async (thread) => {
+ await thread.subscribe();
+ await thread.post("Hello! I'm listening to this thread.");
+});
+
+bot.onSubscribedMessage(async (thread, message) => {
+ await thread.post(`You said: ${message.text}`);
+});
+```
+
+## Core concepts
+
+- **Chat** — main entry point; coordinates adapters, routing, locks, and state
+- **Adapters** — platform-specific integrations for Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, and WhatsApp
+- **State adapters** — persistence for subscriptions, locks, dedupe, and thread state
+- **Thread** — conversation context with `post()`, `stream()`, `subscribe()`, `setState()`, `startTyping()`
+- **Message** — normalized content with `text`, `formatted`, attachments, author info, and platform `raw`
+- **Channel** — container for threads and top-level posts
+
+## Event handlers
+
+| Handler | Trigger |
+|---------|---------|
+| `onNewMention` | Bot @-mentioned in an unsubscribed thread |
+| `onDirectMessage` | New DM in an unsubscribed DM thread |
+| `onSubscribedMessage` | Any message in a subscribed thread |
+| `onNewMessage(regex)` | Regex match in an unsubscribed thread |
+| `onReaction(emojis?)` | Emoji added or removed |
+| `onAction(actionIds?)` | Button clicks and select/radio interactions |
+| `onModalSubmit(callbackId?)` | Modal form submitted |
+| `onModalClose(callbackId?)` | Modal dismissed/cancelled |
+| `onSlashCommand(commands?)` | Slash command invocation |
+| `onAssistantThreadStarted` | Slack assistant thread opened |
+| `onAssistantContextChanged` | Slack assistant context changed |
+| `onAppHomeOpened` | Slack App Home opened |
+| `onMemberJoinedChannel` | Slack member joined channel event |
+
+Read `node_modules/chat/docs/handling-events.mdx`, `node_modules/chat/docs/actions.mdx`, `node_modules/chat/docs/modals.mdx`, and `node_modules/chat/docs/slash-commands.mdx` before wiring handlers. `onDirectMessage` behavior is documented in `node_modules/chat/docs/direct-messages.mdx`.
+
+## Streaming
+
+Pass any `AsyncIterable` to `thread.post()` or `thread.stream()`. For AI SDK, prefer `result.fullStream` over `result.textStream` when available so step boundaries are preserved.
+
+```typescript
+import { ToolLoopAgent } from "ai";
+
+const agent = new ToolLoopAgent({ model: "anthropic/claude-4.5-sonnet" });
+
+bot.onNewMention(async (thread, message) => {
+ const result = await agent.stream({ prompt: message.text });
+ await thread.post(result.fullStream);
+});
+```
+
+Key details:
+- `streamingUpdateIntervalMs` controls post+edit fallback cadence
+- `fallbackStreamingPlaceholderText` defaults to `"..."`; set `null` to disable
+- Structured `StreamChunk` support is Slack-only; other adapters ignore non-text chunks
+
+## Cards and modals (JSX)
+
+Set `jsxImportSource: "chat"` in `tsconfig.json`.
+
+Card components:
+- `Card`, `CardText`, `Section`, `Fields`, `Field`, `Button`, `CardLink`, `LinkButton`, `Actions`, `Select`, `SelectOption`, `RadioSelect`, `Table`, `Image`, `Divider`
+
+Modal components:
+- `Modal`, `TextInput`, `Select`, `SelectOption`, `RadioSelect`
+
+```tsx
+await thread.post(
+
+ Your order has been received.
+
+
+
+
+
+);
+```
+
+## Adapter inventory
+
+### Official platform adapters
+
+| Platform | Package | Factory |
+|---------|---------|---------|
+| Slack | `@chat-adapter/slack` | `createSlackAdapter` |
+| Microsoft Teams | `@chat-adapter/teams` | `createTeamsAdapter` |
+| Google Chat | `@chat-adapter/gchat` | `createGoogleChatAdapter` |
+| Discord | `@chat-adapter/discord` | `createDiscordAdapter` |
+| GitHub | `@chat-adapter/github` | `createGitHubAdapter` |
+| Linear | `@chat-adapter/linear` | `createLinearAdapter` |
+| Telegram | `@chat-adapter/telegram` | `createTelegramAdapter` |
+| WhatsApp Business Cloud | `@chat-adapter/whatsapp` | `createWhatsAppAdapter` |
+
+### Official state adapters
+
+| State backend | Package | Factory |
+|--------------|---------|---------|
+| Redis | `@chat-adapter/state-redis` | `createRedisState` |
+| ioredis | `@chat-adapter/state-ioredis` | `createIoRedisState` |
+| PostgreSQL | `@chat-adapter/state-pg` | `createPostgresState` |
+| Memory | `@chat-adapter/state-memory` | `createMemoryState` |
+
+### Community adapters
+
+- `chat-state-cloudflare-do`
+- `@beeper/chat-adapter-matrix`
+- `chat-adapter-imessage`
+- `@bitbasti/chat-adapter-webex`
+- `@resend/chat-sdk-adapter`
+- `@zernio/chat-sdk-adapter`
+- `chat-adapter-baileys`
+- `@liveblocks/chat-sdk-adapter`
+- `chat-adapter-sendblue`
+- `chat-adapter-zalo`
+
+### Coming-soon platform entries
+
+- Instagram
+- Signal
+- X
+- Messenger
+
+## Building a custom adapter
+
+Read these published docs first:
+- `node_modules/chat/docs/contributing/building.mdx`
+- `node_modules/chat/docs/contributing/testing.mdx`
+- `node_modules/chat/docs/contributing/publishing.mdx`
+
+Also inspect:
+- `node_modules/chat/dist/index.d.ts` — `Adapter` and related interfaces
+- `node_modules/@chat-adapter/shared/dist/index.d.ts` — shared errors and utilities
+- Installed official adapter `dist/index.d.ts` files — reference implementations for config and APIs
+
+A custom adapter needs request verification, webhook parsing, message/thread/channel operations, ID encoding/decoding, and a format converter. Use `BaseFormatConverter` from `chat` and shared utilities from `@chat-adapter/shared`.
+
+## Webhook setup
+
+Each registered adapter exposes `bot.webhooks.`. Wire those directly to your HTTP framework routes. See `node_modules/chat/docs/guides/slack-nextjs.mdx` and `node_modules/chat/docs/guides/discord-nuxt.mdx` for framework-specific route patterns.
diff --git a/skills/chat/SKILL.md b/skills/chat/SKILL.md
index 349d9b9c..b1bfc88e 100644
--- a/skills/chat/SKILL.md
+++ b/skills/chat/SKILL.md
@@ -1,16 +1,6 @@
---
name: chat-sdk
-description: >
- Build multi-platform chat bots with Chat SDK (`chat` npm package). Use when developers want to
- (1) Build a Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, or WhatsApp bot,
- (2) Use Chat SDK to handle mentions, direct messages, subscribed threads, reactions, slash
- commands, cards, modals, files, or AI streaming,
- (3) Set up webhook routes or multi-adapter bots,
- (4) Send rich cards or streamed AI responses to chat platforms,
- (5) Build or maintain a custom adapter or state adapter.
- Triggers on "chat sdk", "chat bot", "slack bot", "teams bot", "google chat bot", "discord bot",
- "telegram bot", "whatsapp bot", "@chat-adapter", "@chat-adapter/state-", "custom adapter",
- "state adapter", "build adapter", and building bots that work across multiple chat platforms.
+description: Build multi-platform chat bots with Chat SDK (`chat` npm package). Use when developers want to build a Slack, Teams, Google Chat, Discord, Telegram, GitHub, Linear, or WhatsApp bot, handle mentions, direct messages, subscribed threads, reactions, slash commands, cards, modals, files, or AI streaming, set up webhook routes or multi-adapter bots, send rich cards or streamed AI responses to chat platforms, or build a custom adapter or state adapter.
---
# Chat SDK