Skip to content

Commit 25341d7

Browse files
committed
feat(llms-txt): add API route for llms.txt generation
Serve llms.txt at /api/registry/llms-txt/[...pkg] following existing registry API patterns with cached event handler and SWR.
1 parent b7b4a1d commit 25341d7

File tree

1 file changed

+50
-0
lines changed

1 file changed

+50
-0
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import * as v from 'valibot'
2+
import { PackageRouteParamsSchema } from '#shared/schemas/package'
3+
import { CACHE_MAX_AGE_ONE_HOUR } from '#shared/utils/constants'
4+
import { handleApiError } from '#server/utils/error-handler'
5+
import { handleLlmsTxt } from '#server/utils/llms-txt'
6+
7+
/**
8+
* Serves llms.txt for an npm package — a single LLM-friendly markdown document
9+
* aggregating README and agent instruction files (CLAUDE.md, AGENTS.md, etc.).
10+
*
11+
* URL patterns:
12+
* - /api/registry/llms-txt/nuxt → latest version
13+
* - /api/registry/llms-txt/@nuxt/kit → scoped, latest
14+
* - /api/registry/llms-txt/nuxt/v/3.12.0 → specific version
15+
* - /api/registry/llms-txt/@nuxt/kit/v/1.0.0 → scoped, specific version
16+
*/
17+
export default defineCachedEventHandler(
18+
async event => {
19+
const pkgParamSegments = getRouterParam(event, 'pkg')?.split('/') ?? []
20+
if (pkgParamSegments.length === 0) {
21+
throw createError({ statusCode: 404, message: 'Package name is required.' })
22+
}
23+
24+
const { rawPackageName, rawVersion } = parsePackageParams(pkgParamSegments)
25+
26+
try {
27+
const { packageName, version } = v.parse(PackageRouteParamsSchema, {
28+
packageName: rawPackageName,
29+
version: rawVersion,
30+
})
31+
32+
const content = await handleLlmsTxt(packageName, version)
33+
setHeader(event, 'Content-Type', 'text/markdown; charset=utf-8')
34+
return content
35+
} catch (error: unknown) {
36+
handleApiError(error, {
37+
statusCode: 502,
38+
message: 'Failed to generate llms.txt.',
39+
})
40+
}
41+
},
42+
{
43+
maxAge: CACHE_MAX_AGE_ONE_HOUR,
44+
swr: true,
45+
getKey: event => {
46+
const pkg = getRouterParam(event, 'pkg') ?? ''
47+
return `llms-txt:${pkg.replace(/\/+$/, '').trim()}`
48+
},
49+
},
50+
)

0 commit comments

Comments
 (0)