diff --git a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms-full.txt/route.ts b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms-full.txt/route.ts index a22cd18872..18c853b7c9 100644 --- a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms-full.txt/route.ts +++ b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms-full.txt/route.ts @@ -100,6 +100,13 @@ export async function GET(req: NextRequest, props: { params: Promise }); } catch (error) { console.error(`[llmsFull:${domain}] Stream error:`, error); + track("static_content_failed", { + domain, + host, + path, + staticContentType: "llms-full.txt", + error: error instanceof Error ? error.message : String(error) + }); controller.error(error); } } diff --git a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms.txt/route.ts b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms.txt/route.ts index 9fdfcab1d7..13eeaf8f0d 100644 --- a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms.txt/route.ts +++ b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/llms.txt/route.ts @@ -96,6 +96,13 @@ export async function GET(req: NextRequest, props: { params: Promise }); } catch (error) { console.error(`[llmsTxt:${domain}] Stream error:`, error); + track("static_content_failed", { + domain, + host, + path, + staticContentType: "llms.txt", + error: error instanceof Error ? error.message : String(error) + }); controller.error(error); } } diff --git a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/markdown/route.ts b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/markdown/route.ts index 35eb56b3cb..c2fb0029a6 100644 --- a/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/markdown/route.ts +++ b/packages/fern-docs/bundle/src/app/[host]/[domain]/[lang]/fern-docs/markdown/route.ts @@ -26,15 +26,15 @@ export async function GET(req: NextRequest, props: { params: Promise const fernToken = (await cookies()).get(COOKIE_FERN_TOKEN)?.value; - const path = req.nextUrl.pathname; - const slug = path.replace(MARKDOWN_PATTERN, ""); + const slugParam = req.nextUrl.searchParams.get("slug"); + const slug = slugParam ?? req.nextUrl.pathname.replace(MARKDOWN_PATTERN, ""); const cleanSlug = removeLeadingSlash(slug); const loader = await createCachedDocsLoader(host, domain, fernToken); const node = getPageNodeForPath(await loader.getRoot(), cleanSlug); if (node == null) { - console.error(`[${domain}] Node not found: ${path}`); + console.error(`[${domain}] Node not found: ${cleanSlug}`); notFound(); } @@ -43,9 +43,32 @@ export async function GET(req: NextRequest, props: { params: Promise return new NextResponse("User is not logged in", { status: 403 }); } - const markdown = await getMarkdownForPath(node, loader); + let markdown; + try { + markdown = await getMarkdownForPath(node, loader); + } catch (error) { + console.error(`[${domain}] Error getting markdown for path: ${cleanSlug}`, error); + track("static_content_failed", { + domain, + path: cleanSlug, + slug: cleanSlug, + host, + staticContentType: "markdown", + error: error instanceof Error ? error.message : String(error) + }); + throw error; + } + if (markdown == null) { - console.error(`[${domain}] Markdown not found: ${path}`); + console.error(`[${domain}] Markdown not found: ${cleanSlug}`); + track("static_content_failed", { + domain, + path: cleanSlug, + slug: cleanSlug, + host, + staticContentType: "markdown", + error: "Markdown not found" + }); notFound(); } @@ -57,7 +80,7 @@ export async function GET(req: NextRequest, props: { params: Promise track("static_content_served", { domain, - path, + path: cleanSlug, slug: cleanSlug, host, staticContentType: "markdown", diff --git a/packages/fern-docs/bundle/src/middleware.ts b/packages/fern-docs/bundle/src/middleware.ts index f67d3eac00..5d13e113b0 100644 --- a/packages/fern-docs/bundle/src/middleware.ts +++ b/packages/fern-docs/bundle/src/middleware.ts @@ -158,10 +158,11 @@ export const middleware: NextMiddleware = async (request) => { } /** - * Rewrite API routes to /api/fern-docs + * Rewrite API routes to /api/fern-docs (legacy compatibility - redirect to /fern-docs) */ if (pathname.includes("/api/fern-docs/")) { - return rewrite(withDomain(withoutBasepath("/api/fern-docs/"))); + const rel = withoutBasepath("/api/fern-docs/").replace(/^\/api\/fern-docs/, "/fern-docs"); + return rewrite(withDomain(rel)); } /** @@ -169,7 +170,7 @@ export const middleware: NextMiddleware = async (request) => { */ if (pathname.endsWith("/llms.txt")) { const slug = removeLeadingSlash(withoutEnding(/\/llms\.txt$/)); - return rewrite(withDomain("/api/fern-docs/llms.txt"), { slug }); + return rewrite(withDomain("/fern-docs/llms.txt"), { slug }); } /** @@ -184,7 +185,7 @@ export const middleware: NextMiddleware = async (request) => { */ if (pathname.endsWith("/llms-full.txt")) { const slug = removeLeadingSlash(withoutEnding(/\/llms-full\.txt$/)); - return rewrite(withDomain("/api/fern-docs/llms-full.txt"), { slug }); + return rewrite(withDomain("/fern-docs/llms-full.txt"), { slug }); } /** @@ -192,7 +193,7 @@ export const middleware: NextMiddleware = async (request) => { */ if (pathname.match(MARKDOWN_PATTERN)) { const slug = removeLeadingSlash(withoutEnding(MARKDOWN_PATTERN)); - return rewrite(withDomain("/api/fern-docs/markdown"), { slug }); + return rewrite(withDomain("/fern-docs/markdown"), { slug }); } /** @@ -228,7 +229,7 @@ export const middleware: NextMiddleware = async (request) => { const acceptHeader = request.headers.get("accept"); if (acceptHeader && (acceptHeader.includes("text/plain") || acceptHeader.includes("text/markdown"))) { const slug = removeLeadingSlash(pathname); - return rewrite(withDomain("/api/fern-docs/llms.txt"), { slug }); + return rewrite(withDomain("/fern-docs/llms.txt"), { slug }); } /**