Skip to content

Commit 7b7e469

Browse files
committed
Added a build step to copy llms.txt to the dist directory for static deployment and cloduflare page function to intercept the requests
1 parent f815c70 commit 7b7e469

3 files changed

Lines changed: 85 additions & 6 deletions

File tree

defillama-openapi-free.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3096,4 +3096,4 @@
30963096
}
30973097
}
30983098
}
3099-
}
3099+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* Cloudflare Pages Function to detect AI/LLM requests and serve llms.txt
3+
*
4+
* This function runs on Cloudflare's edge and intercepts requests before
5+
* serving static assets. Place this in /functions/_middleware.ts
6+
*
7+
* Docs: https://developers.cloudflare.com/pages/functions/middleware/
8+
*/
9+
10+
const AI_USER_AGENTS = [
11+
'anthropic-ai',
12+
'claude',
13+
'openai',
14+
'gptbot',
15+
'chatgpt',
16+
'bingbot',
17+
'googlebot',
18+
'google-extended',
19+
'perplexitybot',
20+
'amazonbot',
21+
'meta-externalagent',
22+
'cohere-ai',
23+
'diffbot',
24+
'curl',
25+
'wget',
26+
]
27+
28+
function isAIUserAgent(userAgent: string | null): boolean {
29+
if (!userAgent) return false
30+
const ua = userAgent.toLowerCase()
31+
return AI_USER_AGENTS.some((agent) => ua.includes(agent))
32+
}
33+
34+
export async function onRequest(context: {
35+
request: Request
36+
next: () => Promise<Response>
37+
env: any
38+
}): Promise<Response> {
39+
const url = new URL(context.request.url)
40+
const userAgent = context.request.headers.get('user-agent')
41+
42+
// Serve llms.txt content on homepage for AI agents
43+
if (url.pathname === '/' && isAIUserAgent(userAgent)) {
44+
try {
45+
// Fetch the llms.txt file from your static assets
46+
const llmsTxtUrl = new URL('/llms.txt', context.request.url)
47+
const llmsResponse = await fetch(llmsTxtUrl.toString())
48+
49+
if (llmsResponse.ok) {
50+
const llmsContent = await llmsResponse.text()
51+
return new Response(llmsContent, {
52+
status: 200,
53+
headers: {
54+
'Content-Type': 'text/plain; charset=utf-8',
55+
'X-Served-As': 'llms.txt',
56+
'Cache-Control': 'public, max-age=3600',
57+
},
58+
})
59+
}
60+
} catch (error) {
61+
console.error('Error serving llms.txt:', error)
62+
}
63+
}
64+
65+
// Continue to the next middleware or serve static assets
66+
return context.next()
67+
}

examples/web/vite.config.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import vue from '@vitejs/plugin-vue'
2-
import { defineConfig, Plugin } from 'vite'
3-
import path from 'path'
4-
import fs from 'fs'
2+
import { defineConfig, type Plugin } from 'vite'
3+
import { resolve } from 'path'
4+
import { readFileSync, existsSync, mkdirSync, copyFileSync } from 'fs'
55

66
const AI_USER_AGENTS = [
77
'anthropic-ai',
@@ -28,12 +28,12 @@ function isAIRequest(userAgent: string | undefined): boolean {
2828

2929
function llmsTxtPlugin(): Plugin {
3030
let llmsContent: string
31+
const llmsPath = resolve(__dirname, '../../llms.txt')
3132

3233
return {
3334
name: 'llms-txt-plugin',
3435
configureServer(server) {
35-
const llmsPath = path.resolve(__dirname, '../../llms.txt')
36-
llmsContent = fs.readFileSync(llmsPath, 'utf-8')
36+
llmsContent = readFileSync(llmsPath, 'utf-8')
3737

3838
server.middlewares.use((req, res, next) => {
3939
const userAgent = req.headers['user-agent']
@@ -54,6 +54,15 @@ function llmsTxtPlugin(): Plugin {
5454
next()
5555
})
5656
},
57+
buildEnd() {
58+
// Copy llms.txt to dist/public for static deployment
59+
const outputDir = resolve(__dirname, 'dist')
60+
if (!existsSync(outputDir)) {
61+
mkdirSync(outputDir, { recursive: true })
62+
}
63+
copyFileSync(llmsPath, resolve(outputDir, 'llms.txt'))
64+
console.log('✓ Copied llms.txt to dist/')
65+
},
5766
}
5867
}
5968

@@ -64,4 +73,7 @@ export default defineConfig({
6473
port: 5050,
6574
open: true,
6675
},
76+
build: {
77+
outDir: 'dist',
78+
},
6779
})

0 commit comments

Comments
 (0)