From 2e7f07c34ef7bd82c455ded5249e7a254ac897a4 Mon Sep 17 00:00:00 2001 From: sonpiaz Date: Sat, 12 Sep 2026 12:42:53 -0700 Subject: [PATCH 1/6] feat: share the existing agent markdown renderer Constraint: Preserve every rendered body and existing routing. Confidence: high --- src/app/llms.md/[[...slug]]/route.ts | 45 ++-------------------------- src/lib/agent-md.ts | 45 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 src/lib/agent-md.ts diff --git a/src/app/llms.md/[[...slug]]/route.ts b/src/app/llms.md/[[...slug]]/route.ts index f0e2bbe..216f062 100644 --- a/src/app/llms.md/[[...slug]]/route.ts +++ b/src/app/llms.md/[[...slug]]/route.ts @@ -1,6 +1,7 @@ import { notFound } from 'next/navigation'; +import { render } from '@/lib/agent-md'; import { source } from '@/lib/source'; -import { blog, changelog } from '@/../.source/server'; +import { blog } from '@/../.source/server'; import { postSlug } from '@/components/blog/post-meta'; // Per-page markdown for machines: `.md` is rewritten here (see @@ -8,48 +9,6 @@ import { postSlug } from '@/components/blog/post-meta'; // build time, so the filesystem reads in getText('raw') happen at build. export const dynamic = 'force-static'; -const FRONTMATTER = /^---\r?\n[\s\S]*?\r?\n---\r?\n/; - -function toMarkdown(title: string, description: string | undefined, raw: string) { - const body = raw.replace(FRONTMATTER, '').trim(); - const head = description ? `# ${title}\n\n> ${description}` : `# ${title}`; - return `${head}\n\n${body}\n`; -} - -async function render(slug: string[]): Promise { - // /blog/.md - if (slug[0] === 'blog' && slug.length === 2) { - const post = blog.find((p) => postSlug(p.info.path) === slug[1]); - if (!post) return null; - return toMarkdown(post.title, post.description, await post.getText('raw')); - } - - // /changelog.md — the changelog is a single page; aggregate all entries. - if (slug.length === 1 && slug[0] === 'changelog') { - const entries = [...changelog].sort( - (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime(), - ); - const sections = await Promise.all( - entries.map(async (entry) => { - const body = (await entry.getText('raw')).replace(FRONTMATTER, '').trim(); - return `## ${entry.title} (${entry.date})\n\n> ${entry.benefit}\n\n${body}`; - }), - ); - return `# Affitor Changelog\n\n${sections.join('\n\n---\n\n')}\n`; - } - - // Docs pages, including the root landing (`/index.md`). - const page = source.getPage( - slug.length === 1 && slug[0] === 'index' ? [] : slug, - ); - if (!page) return null; - return toMarkdown( - page.data.title ?? slug.join('/'), - page.data.description, - await page.data.getText('raw'), - ); -} - export async function GET( _req: Request, { params }: { params: Promise<{ slug?: string[] }> }, diff --git a/src/lib/agent-md.ts b/src/lib/agent-md.ts new file mode 100644 index 0000000..91a1b0f --- /dev/null +++ b/src/lib/agent-md.ts @@ -0,0 +1,45 @@ +import { source } from '@/lib/source'; +import { blog, changelog } from '@/../.source/server'; +import { postSlug } from '@/components/blog/post-meta'; + +const FRONTMATTER = /^---\r?\n[\s\S]*?\r?\n---\r?\n/; + +export function toMarkdown(title: string, description: string | undefined, raw: string) { + const body = raw.replace(FRONTMATTER, '').trim(); + const head = description ? `# ${title}\n\n> ${description}` : `# ${title}`; + return `${head}\n\n${body}\n`; +} + +export async function render(slug: string[]): Promise { + // /blog/.md + if (slug[0] === 'blog' && slug.length === 2) { + const post = blog.find((p) => postSlug(p.info.path) === slug[1]); + if (!post) return null; + return toMarkdown(post.title, post.description, await post.getText('raw')); + } + + // /changelog.md — the changelog is a single page; aggregate all entries. + if (slug.length === 1 && slug[0] === 'changelog') { + const entries = [...changelog].sort( + (a, b) => new Date(b.date).getTime() - new Date(a.date).getTime(), + ); + const sections = await Promise.all( + entries.map(async (entry) => { + const body = (await entry.getText('raw')).replace(FRONTMATTER, '').trim(); + return `## ${entry.title} (${entry.date})\n\n> ${entry.benefit}\n\n${body}`; + }), + ); + return `# Affitor Changelog\n\n${sections.join('\n\n---\n\n')}\n`; + } + + // Docs pages, including the root landing (`/index.md`). + const page = source.getPage( + slug.length === 1 && slug[0] === 'index' ? [] : slug, + ); + if (!page) return null; + return toMarkdown( + page.data.title ?? slug.join('/'), + page.data.description, + await page.data.getText('raw'), + ); +} From 9f4a38f3d2279ed0760d4f771279c58875bfa218 Mon Sep 17 00:00:00 2001 From: sonpiaz Date: Sat, 12 Sep 2026 12:44:51 -0700 Subject: [PATCH 2/6] feat: publish shared agent metadata and full documentation Constraint: Preserve source bodies, URLs, routing and integration names. Confidence: high --- src/app/[...slug]/page.tsx | 5 +- src/app/docs/[[...slug]]/page.tsx | 5 +- src/app/llms-full.txt/route.ts | 15 ++++++ src/app/page.tsx | 5 +- src/app/sitemap.ts | 15 ++++++ src/lib/agent-md.ts | 83 ++++++++++++++++++++++++++++++- 6 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 src/app/llms-full.txt/route.ts create mode 100644 src/app/sitemap.ts diff --git a/src/app/[...slug]/page.tsx b/src/app/[...slug]/page.tsx index 701ef9f..2798541 100644 --- a/src/app/[...slug]/page.tsx +++ b/src/app/[...slug]/page.tsx @@ -1,4 +1,5 @@ import { source } from '@/lib/source'; +import { getDocArticle } from '@/lib/agent-md'; import { DocsPage, DocsBody, DocsDescription, DocsTitle } from 'fumadocs-ui/page'; import { EditOnGitHub } from 'fumadocs-ui/layouts/docs/page'; import { notFound } from 'next/navigation'; @@ -12,13 +13,15 @@ export default async function Page(props: { params: Promise<{ slug: string[] }> const page = source.getPage(params.slug); if (!page) notFound(); + const article = getDocArticle(page); const MDX = page.data.body; const slugPath = params.slug.join('/'); const filePath = `content/docs/${slugPath}.mdx`; const editUrl = `${GITHUB_REPO}/edit/main/${filePath}`; return ( - + +