@vercel/agent-readability 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vercel, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,227 @@
1
+ # @vercel/agent-readability
2
+
3
+ Detect AI agents. Serve them markdown. Audit your site against the
4
+ [Agent Readability Spec](https://vercel.com/kb/guide/agent-readability-spec).
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ npm install @vercel/agent-readability
10
+ ```
11
+
12
+ Or run the audit CLI directly without installing:
13
+
14
+ ```bash
15
+ npx @vercel/agent-readability audit https://vercel.com/docs
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ Add AI agent detection to your Next.js middleware in three lines:
21
+
22
+ ```ts
23
+ // middleware.ts
24
+ import { withAgentReadability } from '@vercel/agent-readability/next'
25
+
26
+ export default withAgentReadability({
27
+ rewrite: (pathname) => `/api/docs-md${pathname}`,
28
+ })
29
+
30
+ export const config = {
31
+ matcher: ['/docs/:path*'],
32
+ }
33
+ ```
34
+
35
+ AI agents hitting `/docs/*` now receive markdown instead of HTML.
36
+
37
+ ## What It Does
38
+
39
+ Three-layer detection identifies AI agents from HTTP request headers:
40
+
41
+ 1. **Known UA patterns.** 40+ agents including ClaudeBot, GPTBot, Cursor, and Perplexity.
42
+ 2. **Signature-Agent header.** Catches ChatGPT agent (RFC 9421).
43
+ 3. **sec-fetch-mode heuristic.** Catches unknown bots that lack browser fingerprints.
44
+
45
+ The detection optimizes for recall over precision. Serving markdown to a non-AI bot
46
+ is low cost. Missing an AI agent means a worse experience.
47
+
48
+ ## Core API
49
+
50
+ ### `isAIAgent(request)`
51
+
52
+ Detect AI agents from request headers.
53
+
54
+ ```ts
55
+ import { isAIAgent } from '@vercel/agent-readability'
56
+
57
+ const result = isAIAgent(request)
58
+ // { detected: true, method: 'ua-match' }
59
+ ```
60
+
61
+ Accepts any object with a `headers.get()` method: `Request`, `NextRequest`,
62
+ or a custom wrapper.
63
+
64
+ Returns a discriminated union:
65
+ - `{ detected: true, method: 'ua-match' | 'signature-agent' | 'heuristic' }`
66
+ - `{ detected: false, method: null }`
67
+
68
+ When `detected` is `true`, `method` is always non-null. TypeScript narrows automatically.
69
+
70
+ ### `acceptsMarkdown(request)`
71
+
72
+ Check if the request prefers markdown via the `Accept` header.
73
+
74
+ ```ts
75
+ import { acceptsMarkdown } from '@vercel/agent-readability'
76
+
77
+ if (acceptsMarkdown(request)) {
78
+ return new Response(markdown, {
79
+ headers: { 'Content-Type': 'text/markdown', 'Vary': 'Accept' },
80
+ })
81
+ }
82
+ ```
83
+
84
+ ### `shouldServeMarkdown(request)`
85
+
86
+ Combines agent detection and content negotiation into one call.
87
+
88
+ ```ts
89
+ import { shouldServeMarkdown } from '@vercel/agent-readability'
90
+
91
+ const { serve, reason } = shouldServeMarkdown(request)
92
+ // serve: true, reason: 'agent' | 'accept-header'
93
+ ```
94
+
95
+ ### `generateNotFoundMarkdown(path, options?)`
96
+
97
+ Generates a markdown body for missing pages. Return this with a 200 status
98
+ (not 404) because agents discard 404 response bodies.
99
+
100
+ ```ts
101
+ import { generateNotFoundMarkdown } from '@vercel/agent-readability'
102
+
103
+ const md = generateNotFoundMarkdown('/docs/missing', {
104
+ baseUrl: 'https://example.com',
105
+ })
106
+ // Return as 200 so agents read the body
107
+ return new Response(md, {
108
+ headers: { 'Content-Type': 'text/markdown' },
109
+ })
110
+ ```
111
+
112
+ ### Pattern Exports
113
+
114
+ `AI_AGENT_UA_PATTERNS`, `TRADITIONAL_BOT_PATTERNS`, `SIGNATURE_AGENT_DOMAINS`,
115
+ and `BOT_LIKE_REGEX` are exported for consumers who need to extend or inspect them.
116
+
117
+ ## Next.js Adapter
118
+
119
+ ### `withAgentReadability(options, handler?)`
120
+
121
+ Middleware wrapper that detects AI agents and rewrites matching requests
122
+ to markdown routes. Compatible with Next.js 14 and 15 (Pages and App Router).
123
+
124
+ ```ts
125
+ import { withAgentReadability } from '@vercel/agent-readability/next'
126
+
127
+ export default withAgentReadability({
128
+ docsPrefix: '/docs',
129
+ rewrite: (pathname) => `/en/llms.mdx/${pathname.replace('/docs/', '')}`,
130
+ onDetection: async ({ path, method }) => {
131
+ await trackMdRequest({ path, detectionMethod: method })
132
+ },
133
+ })
134
+ ```
135
+
136
+ The `onDetection` callback runs via `event.waitUntil()` and does not block
137
+ the response.
138
+
139
+ #### Composing with other middleware
140
+
141
+ Pass your existing middleware as the second argument:
142
+
143
+ ```ts
144
+ export default withAgentReadability(
145
+ {
146
+ rewrite: (p) => `/md${p}`,
147
+ },
148
+ (req, event) => i18nMiddleware(req, event),
149
+ )
150
+ ```
151
+
152
+ #### Options
153
+
154
+ | Option | Type | Default | Description |
155
+ |--------|------|---------|-------------|
156
+ | `docsPrefix` | `string` | `'/docs'` | URL prefix to intercept |
157
+ | `rewrite` | `(pathname: string) => string` | required | Maps request path to markdown route |
158
+ | `onDetection` | `(info) => void \| Promise<void>` | - | Analytics callback (runs in `waitUntil`) |
159
+
160
+ #### `agentReadabilityMatcher`
161
+
162
+ A pre-built matcher that excludes Next.js internals and static files.
163
+ Use this for site-wide agent detection instead of scoping to a prefix:
164
+
165
+ ```ts
166
+ import { withAgentReadability, agentReadabilityMatcher } from '@vercel/agent-readability/next'
167
+
168
+ export default withAgentReadability({
169
+ docsPrefix: '/',
170
+ rewrite: (pathname) => `/md${pathname}`,
171
+ })
172
+
173
+ export const config = {
174
+ matcher: agentReadabilityMatcher,
175
+ }
176
+ ```
177
+
178
+ ## Audit CLI
179
+
180
+ Check your site against the Agent Readability Spec.
181
+
182
+ ```bash
183
+ npx @vercel/agent-readability audit https://sdk.vercel.ai
184
+ ```
185
+
186
+ Runs 16 weighted checks across three categories. Returns a score from 0 to 100.
187
+ Failed checks include fix suggestions that can be copy-pasted into your coding agent.
188
+
189
+ ### CI Integration
190
+
191
+ ```yaml
192
+ - name: Audit agent readability
193
+ run: npx @vercel/agent-readability audit ${{ env.SITE_URL }} --min-score 70 --json
194
+ ```
195
+
196
+ Exits with code 1 if the score is below the threshold.
197
+
198
+ ### CLI Options
199
+
200
+ | Flag | Description |
201
+ |------|-------------|
202
+ | `--json` | Output as JSON |
203
+ | `--min-score <n>` | Exit with error if score < n |
204
+
205
+ ## Caching
206
+
207
+ When the same URL serves HTML to browsers and markdown to AI agents,
208
+ CDN caching must include the `Accept` header in the cache key.
209
+
210
+ Set `Vary: Accept` on all markdown responses. Without it, CDNs may serve
211
+ cached HTML to agents or cached markdown to browsers.
212
+
213
+ The `withAgentReadability` middleware handles detection and rewriting.
214
+ Your markdown route handler is responsible for setting response headers
215
+ including `Vary: Accept` and `Content-Type: text/markdown`.
216
+
217
+ ## Edge Runtime
218
+
219
+ The core library and Next.js adapter use only Web APIs. They work in
220
+ Vercel Edge Runtime, Cloudflare Workers, and any standard `Request`/`Response`
221
+ environment.
222
+
223
+ The CLI runs on Node.js 20+.
224
+
225
+ ## License
226
+
227
+ MIT