Skip to content

Commit e4b8780

Browse files
authored
Render raw markdown pages for llms to read, ref in llms.txt (#501)
* render raw markdown pages for llms to read, ref in llms.txt * make async
1 parent fb52d81 commit e4b8780

File tree

4 files changed

+244
-169
lines changed

4 files changed

+244
-169
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { access, readFile } from "node:fs/promises";
2+
import { join } from "node:path";
3+
import { type NextRequest, NextResponse } from "next/server";
4+
5+
export const dynamic = "force-dynamic";
6+
7+
// Regex pattern for removing .md extension
8+
const MD_EXTENSION_REGEX = /\.md$/;
9+
10+
export async function GET(
11+
request: NextRequest,
12+
_context: { params: Promise<{ slug?: string[] }> }
13+
) {
14+
try {
15+
// Get the original pathname from the request
16+
const url = new URL(request.url);
17+
// Remove /api/markdown prefix to get the original path
18+
const originalPath = url.pathname.replace("/api/markdown", "");
19+
20+
// Remove .md extension
21+
const pathWithoutMd = originalPath.replace(MD_EXTENSION_REGEX, "");
22+
23+
// Map URL to file path
24+
// e.g., /en/home/quickstart -> app/en/home/quickstart/page.mdx
25+
const filePath = join(process.cwd(), "app", `${pathWithoutMd}/page.mdx`);
26+
27+
// Check if file exists
28+
try {
29+
await access(filePath);
30+
} catch {
31+
return new NextResponse("Markdown file not found", { status: 404 });
32+
}
33+
34+
const content = await readFile(filePath, "utf-8");
35+
36+
// Return the raw markdown with proper headers
37+
return new NextResponse(content, {
38+
status: 200,
39+
headers: {
40+
"Content-Type": "text/plain; charset=utf-8",
41+
"Content-Disposition": "inline",
42+
},
43+
});
44+
} catch (error) {
45+
return new NextResponse(`Internal server error: ${error}`, {
46+
status: 500,
47+
});
48+
}
49+
}

middleware.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { type NextRequest, NextResponse } from "next/server";
22

33
const SUPPORTED_LOCALES = ["en", "es", "pt-BR"];
44

5+
// Regex pattern for removing .md extension
6+
const MD_EXTENSION_REGEX = /\.md$/;
7+
58
/**
69
* Parse Accept-Language header and normalize locale codes
710
*/
@@ -60,6 +63,21 @@ function pathnameIsMissingLocale(pathname: string): boolean {
6063
export function middleware(request: NextRequest) {
6164
const pathname = request.nextUrl.pathname;
6265

66+
// Handle .md requests without locale - redirect to add locale first
67+
if (pathname.endsWith(".md") && pathnameIsMissingLocale(pathname)) {
68+
const locale = getPreferredLocale(request);
69+
const pathWithoutMd = pathname.replace(MD_EXTENSION_REGEX, "");
70+
const redirectPath = `/${locale}${pathWithoutMd}.md`;
71+
return NextResponse.redirect(new URL(redirectPath, request.url));
72+
}
73+
74+
// Rewrite .md requests (with locale) to the markdown API route
75+
if (pathname.endsWith(".md") && !pathname.startsWith("/api/")) {
76+
const url = request.nextUrl.clone();
77+
url.pathname = `/api/markdown${pathname}`;
78+
return NextResponse.rewrite(url);
79+
}
80+
6381
// Redirect if there is no locale
6482
if (pathnameIsMissingLocale(pathname)) {
6583
const locale = getPreferredLocale(request);

0 commit comments

Comments
 (0)