diff --git a/packages/gitbook/src/components/PageBody/PageBody.tsx b/packages/gitbook/src/components/PageBody/PageBody.tsx index 2e5e6a630..a24d73140 100644 --- a/packages/gitbook/src/components/PageBody/PageBody.tsx +++ b/packages/gitbook/src/components/PageBody/PageBody.tsx @@ -4,6 +4,7 @@ import type { JSONDocument, RevisionPageDocument, SiteInsightsDisplayContext } f import { getSpaceLanguage } from '@/intl/server'; import { t } from '@/intl/translate'; import { hasFullWidthBlock, hasMoreThan, hasTopLevelBlock, isNodeEmpty } from '@/lib/document'; +import { getLLMsTxtURL, getPageMarkdownURL } from '@/lib/llms-directive'; import type { AncestorRevisionPage } from '@/lib/pages'; import { tcls } from '@/lib/tailwind'; import { DocumentView, DocumentViewSkeleton } from '../DocumentView'; @@ -88,6 +89,7 @@ export async function PageBody(props: { )} > + {page.cover && page.layout.cover && page.layout.coverSize === 'hero' ? ( ) : null} @@ -160,3 +162,17 @@ export async function PageBody(props: { ); } + +function LLMsTxtPageDirective(props: { + context: GitBookSiteContext; + page: RevisionPageDocument; +}) { + const { context, page } = props; + + return ( +
+ For the complete documentation index, see llms.txt. + This page is also available as Markdown. +
+ ); +} diff --git a/packages/gitbook/src/lib/llms-directive.test.ts b/packages/gitbook/src/lib/llms-directive.test.ts new file mode 100644 index 000000000..b6829f344 --- /dev/null +++ b/packages/gitbook/src/lib/llms-directive.test.ts @@ -0,0 +1,39 @@ +import { describe, expect, it } from 'bun:test'; +import type { RevisionPageDocument } from '@gitbook/api'; +import type { GitBookSiteContext } from './context'; +import { createLinker } from './links'; +import { + getLLMsTxtURL, + getPageMarkdownURL, + renderLLMsTxtMarkdownDirective, +} from './llms-directive'; + +describe('llms directive', () => { + const context = { + linker: createLinker({ + host: 'docs.company.com', + siteBasePath: '/docs', + spaceBasePath: '/docs/v1', + }), + } as GitBookSiteContext; + + const page = { + path: 'guides/start', + } as RevisionPageDocument; + + it('links llms.txt from the site root', () => { + expect(getLLMsTxtURL(context)).toBe('https://docs.company.com/docs/llms.txt'); + }); + + it('links page markdown from the current space', () => { + expect(getPageMarkdownURL(context, page)).toBe( + 'https://docs.company.com/docs/v1/guides/start.md' + ); + }); + + it('renders a markdown blockquote directive', () => { + expect(renderLLMsTxtMarkdownDirective(context, page)).toBe( + '> For the complete documentation index, see [llms.txt](https://docs.company.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.company.com/docs/v1/guides/start.md).' + ); + }); +}); diff --git a/packages/gitbook/src/lib/llms-directive.ts b/packages/gitbook/src/lib/llms-directive.ts new file mode 100644 index 000000000..77e3489c3 --- /dev/null +++ b/packages/gitbook/src/lib/llms-directive.ts @@ -0,0 +1,29 @@ +import type { RevisionPageDocument, RevisionPageGroup } from '@gitbook/api'; +import type { GitBookSiteContext } from './context'; + +/** + * Return the URL for the site-level llms.txt file. + */ +export function getLLMsTxtURL(context: GitBookSiteContext): string { + return context.linker.toAbsoluteURL(context.linker.toPathInSite('llms.txt')); +} + +/** + * Return the URL for the markdown version of a page. + */ +export function getPageMarkdownURL( + context: GitBookSiteContext, + page: RevisionPageDocument | RevisionPageGroup +): string { + return `${context.linker.toAbsoluteURL(context.linker.toPathInSpace(page.path))}.md`; +} + +/** + * Render the agent-facing directive that points agents to the site index. + */ +export function renderLLMsTxtMarkdownDirective( + context: GitBookSiteContext, + page: RevisionPageDocument | RevisionPageGroup +): string { + return `> For the complete documentation index, see [llms.txt](${getLLMsTxtURL(context)}). Markdown versions of documentation pages are available by appending \`.md\` to page URLs; this page is available as [Markdown](${getPageMarkdownURL(context, page)}).`; +} diff --git a/packages/gitbook/src/routes/markdownPage.ts b/packages/gitbook/src/routes/markdownPage.ts index 5848e204b..02445b26d 100644 --- a/packages/gitbook/src/routes/markdownPage.ts +++ b/packages/gitbook/src/routes/markdownPage.ts @@ -1,6 +1,7 @@ import type { GitBookSiteContext } from '@/lib/context'; import { getExposableError } from '@/lib/data'; import { linkerWithMarkdownPages } from '@/lib/links'; +import { renderLLMsTxtMarkdownDirective } from '@/lib/llms-directive'; import { getMarkdownForPage } from '@/lib/markdownPage'; import { type ResolvedPagePath, @@ -30,7 +31,7 @@ export async function servePageMarkdown(baseContext: GitBookSiteContext, pagePat if (baseContext.displayAgentInstructions === false) { return markdownPage; } - return `${markdownPage}${renderAskFooter(context, pageLookup)}`; + return `${renderLLMsTxtMarkdownDirective(context, pageLookup.page)}\n\n${markdownPage}${renderAskFooter(context, pageLookup)}`; }); }