From 2c3335864b7cb6d8c0989e77294528e3486c47bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Chopin?= Date: Sat, 22 Aug 2026 20:11:44 +0200 Subject: [PATCH 1/5] feat: serve markdown to agents via content negotiation Vercel routing-layer rewrites (Docus-style) send Accept: text/markdown and curl requests to the /raw/** mirrors, ahead of the ISR cache. Adds raw mirrors for /tree and /blob previews, markdown 404 bodies with recovery links, an llms.txt when-to-use section, and an Organization JSON-LD node. --- app/components/docs/DocsPageAsideLinks.vue | 1 - app/error.vue | 37 ++++++++- app/pages/index.vue | 35 +++++---- modules/markdown-rewrite.ts | 35 +++++++++ nuxt.schema.ts | 12 ++- .../1.getting-started/1.introduction.md | 2 +- .../1.getting-started/3.configuration.md | 43 +++++++++- .../content/3.concepts/1.architecture.md | 13 ++++ .../3.concepts/2.versioned-previews.md | 2 +- server/plugins/llms.ts | 10 +++ server/routes/raw/[...slug].md.get.ts | 11 +-- .../routes/raw/blob/[sha]/[...slug].md.get.ts | 28 +++++++ .../raw/tree/[branch]/[...slug].md.get.ts | 29 +++++++ server/utils/not-found.ts | 34 ++++++++ test/markdown-rewrite.test.ts | 78 +++++++++++++++++++ utils/markdown-rewrite.ts | 46 +++++++++++ 16 files changed, 386 insertions(+), 30 deletions(-) create mode 100644 modules/markdown-rewrite.ts create mode 100644 server/routes/raw/blob/[sha]/[...slug].md.get.ts create mode 100644 server/routes/raw/tree/[branch]/[...slug].md.get.ts create mode 100644 server/utils/not-found.ts create mode 100644 test/markdown-rewrite.test.ts create mode 100644 utils/markdown-rewrite.ts diff --git a/app/components/docs/DocsPageAsideLinks.vue b/app/components/docs/DocsPageAsideLinks.vue index 52a07b5..119b7ef 100644 --- a/app/components/docs/DocsPageAsideLinks.vue +++ b/app/components/docs/DocsPageAsideLinks.vue @@ -110,7 +110,6 @@ const items = [ :ui="{ list: 'gap-2.5' }" /> prodContent.se }) provide('navigation', navigation) + +// First real docs page, so a dead link still offers a way into the content. +const docsLink = computed(() => findFirstPagePath(navigation.value ?? []) ?? '/') + +interface NavigationNode { + path?: string + page?: boolean + children?: NavigationNode[] +} + +function findFirstPagePath(items: NavigationNode[]): string | undefined { + for (const item of items) { + if (item.page !== false && item.path && item.path !== '/') return item.path + if (item.children?.length) { + const child = findFirstPagePath(item.children) + if (child) return child + } + } +}