import type { Config, Context } from "@netlify/edge-functions";
import Negotiator from "negotiator";
export default async (request: Request, context: Context) => {
const negotiator = new Negotiator({
headers: { accept: request.headers.get("accept") ?? undefined },
});
if (!negotiator.mediaTypes().includes("text/markdown")) {
return withVary(await context.next());
}
const url = new URL(request.url);
let pathname = url.pathname;
// Strip trailing slash
if (pathname.endsWith("/") && pathname !== "/") {
pathname = pathname.slice(0, -1);
}
// Serve llms.txt for the home page; otherwise use the .md file generated by the llms-txt plugin
const mdPath =
pathname === "/" || pathname === "/home" ? "/llms.txt" : `${pathname}.md`;
const mdUrl = new URL(mdPath, request.url);
const response = await context.rewrite(mdUrl);
// If no .md file exists for this path, fall through to HTML.
// Also check content-type: a SPA/pretty-404 fallback may return 200 with HTML.
if (
!response.ok ||
response.headers.get("content-type")?.startsWith("text/html")
) {
return withVary(await context.next());
}
return new Response(response.body, {
status: response.status,
headers: {
"content-type": "text/markdown; charset=utf-8",
"cache-control": "public, max-age=3600, stale-while-revalidate=86400",
vary: "Accept",
},
});
};
export const config: Config = {
path: "/*",
excludedPath: [
"/assets/*",
"/img/*",
"/fonts/*",
"/screenshots/*",
"/video/*",
"/**/*.md",
],
};
async function withVary(response: Response): Promise<Response> {
const headers = new Headers(response.headers);
headers.append("vary", "Accept");
return new Response(response.body, { status: response.status, headers });
}