diff --git a/README.md b/README.md index 35e9001..c4729eb 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ Content lives as Markdown in your repo and is served **at request time** — par - **Instant production content** — GitHub-sourced content pinned to a commit SHA, ISR-cached HTML, revalidated on push by a GitHub webhook (`/api/revalidate`). - **Versioned previews** — any branch (`/tree/:branch`) or commit (`/blob/:sha`) can be previewed through versioned URLs. - Docs UI built with [Nuxt UI](https://ui.nuxt.com): sidebar navigation, search (`⌘K`), TOC, prev/next links, version history panel. -- SEO & AEO out of the box: sitemap, robots, canonical URLs, OG images (Satori), JSON-LD, `llms.txt` / `llms-full.txt`, raw markdown mirrors (`/raw/**`), RSS, MCP server (`/mcp`), Agent Skills discovery (`/.well-known/skills/`). +- SEO out of the box: sitemap, robots, canonical URLs, OG images (Satori), JSON-LD, RSS. +- Markdown for agents through [nuxt-agent-discovery](https://github.com/benjamincanac/nuxt-agent-discovery): content negotiation on every documentation page, raw markdown mirrors (`/raw/**`), `llms.txt` / `llms-full.txt`, `sitemap.md`, `/openapi.json`, `/.well-known/api-catalog`, an MCP server (`/mcp`) with its server card, Agent Skills discovery (`/.well-known/skills/`). ## Quick start @@ -44,13 +45,13 @@ From there, the docs cover everything: ## Agent Skills -Drop skills into a `skills/` directory at the app root and the layer serves them at `/.well-known/skills/`, following the [Agent Skills Discovery RFC](https://github.com/cloudflare/agent-skills-discovery-rfc) (v0.1). Users install them with: +Drop skills into a `skills/` directory at the app root and [nuxt-agent-discovery](https://github.com/benjamincanac/nuxt-agent-discovery) serves them at `/.well-known/skills/`, following the [Agent Skills Discovery RFC](https://github.com/cloudflare/agent-skills-discovery-rfc) (v0.1). Users install them with: ```bash npx skills add https://your-docs-domain.com ``` -Each skill is a directory with a `SKILL.md` whose frontmatter includes a `description`; `name` defaults to the directory name. Skills are scanned at build time from the filesystem (they ship with the app, not with GitHub-sourced content), so a skill change needs a redeploy. Override the directory with `comarkDocs.skills.dir`. +Each skill is a directory with a `SKILL.md` whose frontmatter includes a `description`; `name` defaults to the directory name. Skills are scanned at build time from the filesystem (they ship with the app, not with GitHub-sourced content), so a skill change needs a redeploy. Override the directory with `agentDiscovery.skills.dir`. ## Keyboard shortcuts diff --git a/app/components/docs/DocsPageAsideLinks.vue b/app/components/docs/DocsPageAsideLinks.vue index 387423f..7424c47 100644 --- a/app/components/docs/DocsPageAsideLinks.vue +++ b/app/components/docs/DocsPageAsideLinks.vue @@ -13,7 +13,8 @@ const { copy: copyLink } = useClipboard() const copying = ref(false) const site = useSiteConfig() -const mdPath = computed(() => `/raw${route.path}.md`) +const { rawPrefix } = useRuntimeConfig().public.agentDiscovery +const mdPath = computed(() => `${rawPrefix}${route.path}.md`) const mdUrl = computed(() => `${site.url}${mdPath.value}`) const { github, docs } = useAppConfig() diff --git a/app/components/landing/LandingFaq.vue b/app/components/landing/LandingFaq.vue index 752fe26..9f87144 100644 --- a/app/components/landing/LandingFaq.vue +++ b/app/components/landing/LandingFaq.vue @@ -9,23 +9,12 @@ const props = defineProps<{ items: FaqItem[] }>() -// FAQPage structured data mirrors the visible accordion. -useHead({ - script: [ - { - type: 'application/ld+json', - innerHTML: jsonLd({ - '@context': 'https://schema.org', - '@type': 'FAQPage', - mainEntity: props.items.map((item) => ({ - '@type': 'Question', - name: item.label, - acceptedAnswer: { '@type': 'Answer', text: item.content }, - })), - }), - }, - ], -}) +// FAQPage structured data mirrors the visible accordion. The page node is retyped rather than a second +// one emitted, so the questions hang off the `WebPage` nuxt-schema-org already has, through `mainEntity`. +useSchemaOrg([ + defineWebPage({ '@type': 'FAQPage' }), + ...props.items.map((item) => defineQuestion({ name: item.label, acceptedAnswer: item.content })), +])