diff --git a/README.md b/README.md index a0579a5..73b9301 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ Nuxt LLMs automatically generates [`llms.txt` markdown documentation](https://ll - Generates & prerenders `/llms.txt` automatically - Generate & prerenders `/llms-full.txt` when enabled - Customizable sections directly from your `nuxt.config.ts` +- `useLlmsAlternate` composable to advertise per-page markdown alternates (RFC 8288) - Integrates with Nuxt modules and your application via the runtime hooks system ## Quick Setup @@ -120,6 +121,32 @@ export default defineNuxtConfig({ }) ``` +## Per-page markdown discovery + +`/llms.txt` advertises your site at the global level, but agents crawling individual pages have no standard way to know that a markdown counterpart exists. The `useLlmsAlternate` composable solves this by emitting two discovery hints per [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288): + +- `` in the document `` +- `Link: <...>; rel="alternate"; type="text/markdown"` HTTP response header + +Agents can read the `Link` header from a `HEAD` request — without parsing HTML — and switch to the markdown URL for ingestion. + +```vue + + +``` + +The composable accepts a string, a `ref`, or a getter. Falsy values are ignored, so it is safe to call before async data resolves: + +```ts +const { data: post } = await useAsyncData(/* ... */) +useLlmsAlternate(() => post.value?.markdownUrl) +``` + +This pairs naturally with `@nuxt/content`'s `/raw/.md` endpoint, but works with any markdown URL — including endpoints you serve yourself. + ## Extending the documentation using hooks The module provides a hooks system that allows you to dynamically extend both documentation formats. There are two main hooks: diff --git a/playground/pages/[...slug].vue b/playground/pages/[...slug].vue index 8923059..3175ce3 100644 --- a/playground/pages/[...slug].vue +++ b/playground/pages/[...slug].vue @@ -7,6 +7,11 @@ const { data } = await useAsyncData( return await queryCollection('content').path(route.path).first() }, ) + +useLlmsAlternate(() => { + const path = data.value?.path + return path && path !== '/' ? `/raw${path}.md` : null +})