Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
439f2de
chore(deps): update fumadocs-core to 15.8.5 and fumadocs-mdx to 12.0.…
aryasaatvik Oct 13, 2025
61a800d
feat(docs): implement LLM markdown rewrites and add new routes for LL…
aryasaatvik Oct 13, 2025
b0441c7
ref(docs): replace middleware with static rewrites for LLM content
aryasaatvik Oct 13, 2025
24d0d0c
chore(deps): update fumadocs-ui to 15.8.5 in package.json and pnpm-lo…
aryasaatvik Oct 13, 2025
cb4dd17
chore: move llms.txt and llms-full.txt to the root
aryasaatvik Oct 13, 2025
a133fe4
feat(docs): add new redirect for manually requesting markdown files i…
aryasaatvik Oct 13, 2025
9ee7547
feat(docs): add copy button and view options for markdown files
aryasaatvik Oct 13, 2025
4bc7213
chore(docs): update test script to include next typegen before tsc
aryasaatvik Oct 13, 2025
82b59ad
fix(docs): use consistent cn utility import
aryasaatvik Oct 14, 2025
683b3dd
feat(docs): use nuqs serializer for ChatGPT URL construction
aryasaatvik Oct 14, 2025
22ef450
feat(docs): add Suspense boundary with buttonVariants skeleton
aryasaatvik Oct 14, 2025
5cd30b9
feat(docs): move PageActionsSkeleton to page-actions component
aryasaatvik Oct 14, 2025
0027b7c
Merge branch 'next' into feat/llm-docs
aryasaatvik Oct 26, 2025
af1b68c
feat(docs): restructure LLM documentation output
aryasaatvik Oct 26, 2025
82120b0
feat(docs): add page exclusions for LLM text generation
aryasaatvik Oct 26, 2025
bf1fac4
fix(docs): filter out excluded pages in LLM text generation
aryasaatvik Oct 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/docs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ const config = {
]
},
reactStrictMode: true,
async rewrites() {
return [
{
source: "/docs/:path*.md(x)?",
destination: "/docs/llms.mdx/:path*",
},
];
},
redirects: async () => {
return [
{
Expand Down
4 changes: 2 additions & 2 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@
"clsx": "^2.1.1",
"dayjs": "^1.11.13",
"effect": "^3.17.8",
"fumadocs-core": "^15.6.12",
"fumadocs-mdx": "^11.7.5",
"fumadocs-core": "^15.8.5",
"fumadocs-mdx": "^12.0.3",
"fumadocs-ui": "^15.6.12",
"lucide-react": "^0.540.0",
"next": "15.5.0",
Expand Down
7 changes: 6 additions & 1 deletion packages/docs/source.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ export default defineConfig({
})

export const { docs, meta } = defineDocs({
dir: 'content/docs'
dir: 'content/docs',
docs: {
postprocess: {
includeProcessedMarkdown: true,
},
}
})

export const blog = defineCollections({
Expand Down
12 changes: 12 additions & 0 deletions packages/docs/src/app/docs/llms-full.txt/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { source } from '@/src/app/source';
import { getLLMText } from '@/src/lib/get-llm-text';

// cached forever
export const revalidate = false;

export async function GET() {
const scan = source.getPages().map(getLLMText);
const scanned = await Promise.all(scan);

return new Response(scanned.join('\n\n'));
}
24 changes: 24 additions & 0 deletions packages/docs/src/app/docs/llms.mdx/[[...slug]]/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { getLLMText } from '@/src/lib/get-llm-text';
import { source } from '@/src/app/source';
import { notFound } from 'next/navigation';

export const revalidate = false;

export async function GET(
_req: Request,
{ params }: RouteContext<'/docs/llms.mdx/[[...slug]]'>,
) {
const { slug } = await params;
const page = source.getPage(slug);
if (!page) notFound();

return new Response(await getLLMText(page), {
headers: {
'Content-Type': 'text/markdown',
},
});
}

export function generateStaticParams() {
return source.generateParams();
}
12 changes: 12 additions & 0 deletions packages/docs/src/app/docs/llms.txt/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { source } from '@/src/app/source';
import { getLLMText } from '@/src/lib/get-llm-text';

// cached forever
export const revalidate = false;

export async function GET() {
const scan = source.getPages().map(getLLMText);
const scanned = await Promise.all(scan);

return new Response(scanned.join('\n\n'));
}
10 changes: 10 additions & 0 deletions packages/docs/src/lib/get-llm-text.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { source } from "@/src/app/source";
import type { InferPageType } from "fumadocs-core/source";;

export async function getLLMText(page: InferPageType<typeof source>) {
const processed = await page.data.getText('processed');

return `# ${page.data.title} (${page.url})

${processed}`;
}
20 changes: 20 additions & 0 deletions packages/docs/src/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { NextRequest, NextResponse } from "next/server";
import { isMarkdownPreferred, rewritePath } from "fumadocs-core/negotiation";

const { rewrite: rewriteLLM } = rewritePath("/docs/*path", "/docs/llms.mdx/*path");

export function middleware(request: NextRequest) {
if (isMarkdownPreferred(request)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: What does this function do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it checks the Accept header for the presence of text/plain or text/markdown preference and the order and q value if both text/html and (text/plain or text/markdown) are present.

using a static rewrite also works for claude code and opencode since they dont rely on q value and order

const result = rewriteLLM(request.nextUrl.pathname);

if (result) {
return NextResponse.rewrite(new URL(result, request.nextUrl));
}
}

return NextResponse.next();
}

export const config = {
matcher: "/docs/:path*",
};
Loading
Loading