Skip to content

Commit 538bf40

Browse files
authored
llms.txt built in-project (#497)
* Generate LLMs.txt ourself. * regenerate * bring back github actions
1 parent 8adf17a commit 538bf40

File tree

11 files changed

+743
-26557
lines changed

11 files changed

+743
-26557
lines changed

.github/workflows/llmstxt.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Generate LLMs.txt
22

33
on:
44
schedule:
5-
- cron: '0 0 * * 0' # Run at 00:00 every Sunday
5+
- cron: "0 0 * * 0" # Run at 00:00 every Sunday
66
workflow_dispatch:
77

88
permissions:
@@ -22,7 +22,7 @@ jobs:
2222
- name: Use Node.js
2323
uses: actions/setup-node@v4
2424
with:
25-
node-version: '22.x'
25+
node-version: "22.x"
2626

2727
- name: Checkout code
2828
uses: actions/checkout@v4
@@ -38,7 +38,7 @@ jobs:
3838
- name: generate LLMs.txt
3939
run: pnpm llmstxt
4040
env:
41-
FIRECRAWL_API_KEY: ${{ secrets.FIRECRAWL_API_KEY }}
41+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
4242

4343
# commit the changes and make a PR (branch protection)
4444
- name: Create Pull Request
@@ -49,7 +49,7 @@ jobs:
4949
commit-message: Regenerate LLMs.txt and related files
5050
branch: auto-update-llms-txt
5151
delete-branch: true
52-
title: '🤖 Regenerate LLMs.txt'
52+
title: "🤖 Regenerate LLMs.txt"
5353
reviewers: >
5454
evantahler
5555
torresmateo

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ First, run `pnpm install` to install the dependencies.
1010

1111
Then, run `pnpm dev` to start the development server and visit localhost:3000.
1212

13+
### Environment Variables
14+
15+
Copy `.env.example` to `.env.local` and fill in the required values:
16+
17+
```bash
18+
cp .env.example .env.local
19+
```
20+
21+
- `OPENAI_API_KEY` - Required for generating the llms.txt file with AI-powered summaries
22+
23+
## llms.txt Generation
24+
25+
The project includes a Next.js plugin that automatically generates an `llms.txt` file following the [llms.txt specification](https://llmstxt.org/). This file helps LLMs understand and navigate the documentation.
26+
27+
**Automatic generation**: Runs during production builds (`pnpm build`)
28+
29+
**Manual generation**: Run `pnpm llmstxt` to regenerate the file
30+
31+
See [`scripts/README-llmstxt.md`](./scripts/README-llmstxt.md) for detailed documentation.
32+
1333
## Styling
1434

1535
We use Nextra's built-in Callout component for callouts in MDX:

app/en/home/agentic-development/page.mdx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,13 @@ description: "Learn how to speed up your development with agents in your IDEs"
55

66
# Agentic Development
77

8-
Give your AI IDE access to Arcade.dev's documentation using our llms.txt files (short [llms.txt](/llms.txt), [llms-full.txt](/llms-full.txt)), or use [context7](https://context7.com/arcadeai/docs). This allows Claude Code, Cursor, and other AI IDEs to access the documentation and help you write code.
8+
Give your AI IDE access to Arcade.dev's documentation using our [llms.txt](/llms.txt) file, or use [context7](https://context7.com/arcadeai/docs). This allows Claude Code, Cursor, and other AI IDEs to access the documentation and help you write code.
99

1010
## LLMs.txt
1111

1212
LLMs.txt is a file format that allows you to give your AI IDE access to Arcade.dev's documentation in a format that can be easily parsed by the LLM. All you need to do is paste in the conent of the file into your IDE's settings, or reference the docs, e.g. via [Cursor's `@docs` annotation](https://cursor.com/docs/context/symbols#docs).
1313

14-
Our LLMs.txt files are available in two versions:
15-
16-
- [`/llms.txt`](/llms.txt) - a short version of the documentation index
17-
- [`/llms-full.txt`](/llms-full.txt) - a full version of the documentation
14+
Our LLMs.txt files are available at [`/llms.txt`](/llms.txt).
1815

1916
![LLMs.txt example](/images/agentic-development/cursor-llms-txt.png)
2017

lib/next-plugin-llmstxt.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import type { NextConfig } from "next";
2+
3+
type LlmsTxtPluginOptions = {
4+
enabled?: boolean;
5+
generateOnBuild?: boolean;
6+
};
7+
8+
/**
9+
* Next.js plugin that generates llms.txt at build time
10+
*
11+
* This plugin integrates with the Next.js build process to automatically
12+
* generate an llms.txt file that follows the llms.txt specification.
13+
*
14+
* @param options - Plugin configuration options
15+
* @returns Next.js config wrapper function
16+
*/
17+
export function withLlmsTxt(options: LlmsTxtPluginOptions = {}) {
18+
const { enabled = true, generateOnBuild = true } = options;
19+
20+
return (nextConfig: NextConfig = {}): NextConfig => {
21+
if (!enabled) {
22+
return nextConfig;
23+
}
24+
25+
return {
26+
...nextConfig,
27+
webpack: (config, context) => {
28+
// Only run during production build or when explicitly enabled
29+
if (generateOnBuild && !context.isServer) {
30+
// Add a custom plugin that runs after compilation
31+
config.plugins = config.plugins || [];
32+
config.plugins.push({
33+
apply: (compiler: {
34+
hooks: {
35+
afterEmit: {
36+
tapPromise: (
37+
name: string,
38+
callback: () => Promise<void>
39+
) => void;
40+
};
41+
};
42+
options: { name: string };
43+
}) => {
44+
compiler.hooks.afterEmit.tapPromise("LlmsTxtPlugin", async () => {
45+
// Only generate once (not on every rebuild)
46+
if (compiler.options.name === "client") {
47+
try {
48+
// Dynamic import to avoid bundling issues
49+
const { generateLlmsTxt } = await import(
50+
"../scripts/generate-llmstxt.js"
51+
);
52+
53+
await generateLlmsTxt();
54+
} catch (_error) {
55+
// Don't fail the build if llms.txt generation fails
56+
}
57+
}
58+
});
59+
},
60+
});
61+
}
62+
63+
// Call the original webpack function if it exists
64+
if (typeof nextConfig.webpack === "function") {
65+
return nextConfig.webpack(config, context);
66+
}
67+
68+
return config;
69+
},
70+
};
71+
};
72+
}

next.config.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { NextConfig } from "next";
22
import nextra from "nextra";
3+
import { withLlmsTxt } from "./lib/next-plugin-llmstxt";
34
import { remarkGlossary } from "./lib/remark-glossary";
45

56
// Set up Nextra with its configuration
@@ -13,30 +14,34 @@ const withNextra = nextra({
1314
},
1415
});
1516

16-
const nextConfig: NextConfig = withNextra({
17-
headers: async () => [
18-
{
19-
source: "/(.*)",
20-
headers: [
21-
{
22-
key: "X-Frame-Options",
23-
value: "SAMEORIGIN",
24-
},
25-
{
26-
key: "X-Content-Type-Options",
27-
value: "nosniff",
28-
},
29-
{
30-
key: "Permissions-Policy",
31-
value: "camera=(), geolocation=(), microphone=()",
32-
},
33-
{
34-
key: "Referrer-Policy",
35-
value: "strict-origin-when-cross-origin",
36-
},
37-
],
38-
},
39-
],
40-
});
17+
const nextConfig: NextConfig = withLlmsTxt({
18+
enabled: false, // disabled for now, we will recreate this every week
19+
})(
20+
withNextra({
21+
headers: async () => [
22+
{
23+
source: "/(.*)",
24+
headers: [
25+
{
26+
key: "X-Frame-Options",
27+
value: "SAMEORIGIN",
28+
},
29+
{
30+
key: "X-Content-Type-Options",
31+
value: "nosniff",
32+
},
33+
{
34+
key: "Permissions-Policy",
35+
value: "camera=(), geolocation=(), microphone=()",
36+
},
37+
{
38+
key: "Referrer-Policy",
39+
value: "strict-origin-when-cross-origin",
40+
},
41+
],
42+
},
43+
],
44+
})
45+
);
4146

4247
export default nextConfig;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"postbuild": "pagefind --site .next/server/app --output-path public/_pagefind && next-sitemap",
1414
"translate": "pnpm dlx tsx scripts/i18n-sync/index.ts && pnpm format",
1515
"sync:metas": "pnpm dlx tsx scripts/sync-metas.ts app/en",
16-
"llmstxt": "./scripts/generate-llmstxt.sh",
16+
"llmstxt": "pnpm dlx tsx scripts/generate-llmstxt.ts",
1717
"test": "vitest --run",
1818
"test:watch": "vitest --watch"
1919
},

0 commit comments

Comments
 (0)