Skip to content

Commit f69d5ea

Browse files
committed
add llm support
1 parent 82458df commit f69d5ea

File tree

9 files changed

+394
-22
lines changed

9 files changed

+394
-22
lines changed

bun.lock

Lines changed: 13 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,19 @@
1212
},
1313
"dependencies": {
1414
"@orama/orama": "^3.1.18",
15+
"@radix-ui/react-popover": "^1.1.15",
1516
"ajv": "^8.17.1",
17+
"class-variance-authority": "^0.7.1",
1618
"fumadocs-core": "16.4.7",
1719
"fumadocs-mdx": "14.2.5",
18-
"fumadocs-openapi": "^10.2.4",
20+
"fumadocs-openapi": "^10.2.5",
1921
"fumadocs-ui": "16.4.7",
2022
"lucide-react": "^0.562.0",
2123
"next": "16.1.3",
2224
"react": "^19.2.3",
2325
"react-dom": "^19.2.3",
24-
"shiki": "^3.21.0"
26+
"shiki": "^3.21.0",
27+
"tailwind-merge": "^3.4.0"
2528
},
2629
"devDependencies": {
2730
"@tailwindcss/postcss": "^4.1.18",

src/app/[[...slug]]/page.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ import { notFound } from "next/navigation";
99
import { getMDXComponents } from "@/mdx-components";
1010
import type { Metadata } from "next";
1111
import { createRelativeLink } from "fumadocs-ui/mdx";
12+
import { LLMCopyButton, ViewOptions } from "@/components/page-actions";
13+
14+
function getMarkdownUrl(pageUrl: string): string {
15+
// Use /llm prefix with .txt extension for LLM-friendly URLs
16+
if (pageUrl === "/" || pageUrl === "") {
17+
return "/llm/index.txt";
18+
}
19+
return `/llm${pageUrl}.txt`;
20+
}
1221

1322
export default async function Page(props: PageProps<"/[[...slug]]">) {
1423
const params = await props.params;
@@ -21,6 +30,7 @@ export default async function Page(props: PageProps<"/[[...slug]]">) {
2130
if (!page) notFound();
2231

2332
const MDX = page.data.body;
33+
const markdownUrl = getMarkdownUrl(page.url);
2434

2535
return (
2636
<DocsPage
@@ -29,7 +39,16 @@ export default async function Page(props: PageProps<"/[[...slug]]">) {
2939
tableOfContent={{ style: "clerk" }}
3040
>
3141
<DocsTitle>{page.data.title}</DocsTitle>
32-
<DocsDescription>{page.data.description}</DocsDescription>
42+
<DocsDescription className="mb-0">
43+
{page.data.description}
44+
</DocsDescription>
45+
<div className="flex flex-row gap-2 items-center border-b pt-2 pb-6">
46+
<LLMCopyButton markdownUrl={markdownUrl} />
47+
<ViewOptions
48+
markdownUrl={markdownUrl}
49+
githubUrl={`https://github.com/Uncover-it/docs/blob/master/content/docs/${page.path}`}
50+
/>
51+
</div>
3352
<DocsBody>
3453
<MDX
3554
components={getMDXComponents({

src/app/llm/[...slug]/route.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { getLLMText, source } from "@/lib/source";
2+
3+
export const revalidate = false;
4+
export const dynamicParams = false;
5+
6+
export async function GET(
7+
_request: Request,
8+
props: { params: Promise<{ slug: string[] }> }
9+
) {
10+
const params = await props.params;
11+
const slug = [...params.slug];
12+
13+
// The last segment ends with .txt - strip it to get the actual page slug
14+
if (slug.length > 0) {
15+
const lastPart = slug[slug.length - 1];
16+
if (lastPart.endsWith(".txt")) {
17+
slug[slug.length - 1] = lastPart.slice(0, -4);
18+
}
19+
}
20+
21+
// Filter out empty strings and handle "index" specially
22+
if (slug.length === 1 && slug[0] === "index") {
23+
slug.length = 0;
24+
}
25+
26+
let page = source.getPage(slug);
27+
28+
if (!page) {
29+
return new Response("Not Found", { status: 404 });
30+
}
31+
32+
const content = await getLLMText(page);
33+
34+
return new Response(content, {
35+
headers: {
36+
"Content-Type": "text/plain; charset=utf-8",
37+
},
38+
});
39+
}
40+
41+
export async function generateStaticParams() {
42+
const params = source.generateParams();
43+
44+
return params.map((param) => {
45+
const baseSlug = param.slug ?? [];
46+
47+
// For index page, use ["index.txt"]
48+
if (baseSlug.length === 0) {
49+
return { slug: ["index.txt"] };
50+
}
51+
52+
// Add .txt extension to the last segment
53+
const slug = [...baseSlug];
54+
slug[slug.length - 1] += ".txt";
55+
56+
return { slug };
57+
});
58+
}

0 commit comments

Comments
 (0)