脚手架的 src/pages/[...slug]/index.md.ts 和 src/pages/[...slug]/index.mdx.ts 路由为每个页面提供 Markdown 和源版本。你可以在三个层级上更改它们的输出:
- 包装共享路由以更改所有页面的输出。
- 用自己的代码替换共享路由。
- 添加更具体的路由文件来接管单个集合。
示例使用 .md 路由。.mdx 路由使用 markdownSourceRoute() 的方式相同。llms.txt 路由和 OG 卡片路由遵循相同的模式;请参阅覆盖 llms.txt 索引和自定义 OG 卡片。
包装共享路由
调用共享路由的 GET,然后更改其响应。此示例向每个 Markdown 版本添加许可证行:
import type { APIRoute } from "astro";
import { markdownRoute } from "@cloudflare/nimbus-docs/agent-endpoints";
export const prerender = true;
const route = markdownRoute();
export const getStaticPaths = route.getStaticPaths;
export const GET: APIRoute = async (context) => {
const response = await route.GET(context);
if (!response.ok) return response;
const body = await response.text();
return new Response(`${body}\nLicensed under CC BY 4.0.\n`, {
headers: response.headers,
});
};替换共享路由
使用 @cloudflare/nimbus-docs/agent-endpoints 中的公共辅助函数编写自己的 GET。getMarkdownPayload() 以 body 形式返回页面生成的 Markdown,以 content 形式返回仅页面内容(不含 frontmatter 和索引前言)。保留共享路由的 getStaticPaths:它列出每个集合的页面,跳过更具体路由拥有的页面,并将每个页面的 reference 作为 prop 传递。
此示例仅提供页面内容:
import type { APIRoute } from "astro";
import {
getMarkdownPayload,
markdownRoute,
type MarkdownEndpointReference,
} from "@cloudflare/nimbus-docs/agent-endpoints";
export const prerender = true;
export const { getStaticPaths } = markdownRoute();
export const GET: APIRoute = async ({ props, request }) => {
const { reference } = props as { reference: MarkdownEndpointReference };
const payload = await getMarkdownPayload({
collection: reference.collection,
surface: "markdown",
reference,
context: { request },
});
if (!payload) return new Response("Not found", { status: 404 });
return new Response(payload.content, {
headers: { "Content-Type": payload.mediaType },
});
};要自己列出页面,getMarkdownStaticPaths({ collection, surface }) 返回一个集合的路径。基于它构建的路由仅服务它列出的集合。
接管单个集合
Astro 对更具体的路由赋予更高优先级。在集合的 URL 前缀下添加路由文件,它将服务该集合的 Markdown 版本。共享路由会跳过更具体路由模式匹配的所有 URL。
markdownRoute() 可在任何路由文件中使用,仅服务其路由匹配的 URL。包装它以自定义单个集合:
import type { APIRoute } from "astro";
import { markdownRoute } from "@cloudflare/nimbus-docs/agent-endpoints";
export const prerender = true;
const route = markdownRoute();
export const getStaticPaths = route.getStaticPaths;
export const GET: APIRoute = async (context) => {
const response = await route.GET(context);
if (!response.ok) return response;
const body = await response.text();
return new Response(`${body}\nSubscribe at https://example.com/blog/rss.xml\n`, {
headers: response.headers,
});
};或者使用公共辅助函数编写路由。更新日志配方(nimbus-docs add changelog)添加了 src/pages/changelog/[...slug]/index.md.ts,它使用每个条目的日期和标签构建自己的 frontmatter:
export const prerender = true;
export const getStaticPaths = async () =>
getMarkdownStaticPaths({ collection: "changelog", surface: "markdown" });
export async function GET({ params, props, request }: SlugContext) {
const payload = await getMarkdownPayload({
collection: "changelog",
surface: "markdown",
slug: params.slug,
reference: props.reference,
context: { request },
});
if (!payload) return new Response("Not found", { status: 404 });
// 从条目的数据构建 frontmatter,然后追加 payload.content。
}更具体的路由必须生成其模式匹配的每个页面。如果跳过某些页面,这些页面将没有 Markdown 版本,而 llms.txt 仍然会链接到它们。Nimbus 会在构建警告中列出缺失的路径和拥有的路由。当 Astro 的 prerenderConflictBehavior 设置为 "error" 时,构建会直接失败。
覆盖 llms.txt 索引
脚手架的 llms.txt 路由调用 llmsRoute()、llmsFullRoute() 和 llmsSectionRoute()。以相同方式包装返回的 GET。此示例向 /llms.txt 添加支持链接:
import type { APIRoute } from "astro";
import { llmsRoute } from "@cloudflare/nimbus-docs/agent-endpoints";
export const prerender = true;
const route = llmsRoute();
export const GET: APIRoute = async (context) => {
const response = await route.GET(context);
if (!response.ok) return response;
const body = await response.text();
return new Response(`${body}\n## Support\n\n- [Contact support](https://example.com/support)\n`, {
headers: response.headers,
});
};对于分节索引,保留 llmsSectionRoute() 的 getStaticPaths(它列出每个分节),并包装其 GET。要从头构建正文,请使用 reference(如 { scope: "section", surface: "index", section: "writing" })调用 getLlmsPayload();对于未知索引,它返回 null。
自定义 OG 卡片
脚手架的 src/pages/og/[...slug].ts 将 getOgImagePages() 传递给 astro-og-canvas。该映射每个页面一个条目,键使得每张卡片写入该页面的 ogImageUrl,每个值是页面的 IndexedEntry。在 src/pages/og/_og-card-config.ts 中更改卡片外观,或在 getImageOptions 中逐页更改。此示例为更新日志卡片添加标签:
import { getOgImagePages } from "@cloudflare/nimbus-docs/runtime";
import { OGImageRoute } from "astro-og-canvas";
import { ogCardConfig } from "./_og-card-config";
export const prerender = true;
export const { getStaticPaths, GET } = await OGImageRoute({
pages: await getOgImagePages(),
getImageOptions: (_path, page) => ({
title: page.collection === "changelog" ? `Changelog: ${page.title}` : page.title,
description: page.description ?? "",
...ogCardConfig,
}),
});请将路由保持在 src/pages/og/[...slug].ts,保持映射的键、默认的 getSlug 和 PNG 输出:页面路由链接到 ogImageUrl,因此更改位置、键、slug 或格式会导致页面指向不存在的卡片。frontmatter 中设置了 socialImage 的页面会使用该图片,因为页面路由传递的是 entry.data.socialImage ?? ogImageUrl。
覆盖更改了什么
覆盖仅更改该路由提供的内容。llms-full.txt 和托管 MCP 仍使用 Nimbus 生成的 Markdown。
共享路由和使用 markdownRoute() 或 markdownSourceRoute() 的路由必须保持 export const prerender = true。如果在请求时渲染,构建会失败。
在路由文件本身中调用工厂函数,如上面的示例所示。与 Astro 自己的 prerender 检测一样,Nimbus 通过读取路由文件来查找它,因此从另一个模块重新导出的工厂函数在构建启动时不会被检查。在构建结束时,Nimbus 会警告每个没有预渲染路由生成的 Markdown 版本和 llms.txt 索引,并指出服务它的路由。