diff --git a/AGENTS.md b/AGENTS.md index e472230..297128f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,7 @@ accurate product docs while building on the platform. | Published release history | `content/changelog/` | | Live site (canonical rendered output) | [docs.nextcommerce.com](https://docs.nextcommerce.com) | | Admin API, Campaigns SDK, webhooks, themes, GraphQL | [developers.nextcommerce.com](https://developers.nextcommerce.com) — separate repo | -| Which merchant and developer pages cover one capability | [capabilities.json](https://developers.nextcommerce.com/capabilities.json) ([readable](https://developers.nextcommerce.com/docs/capabilities)) — pages here declare their ids in `capability_ids` frontmatter; domain bundles at `https://developers.nextcommerce.com/llms/.txt` | +| Which merchant and developer pages cover one capability | [capabilities.json](https://developers.nextcommerce.com/capabilities.json) — page relationships come from the URLs in the map; domain bundles are at `https://developers.nextcommerce.com/llms/.txt` | Start with `content/docs/index.mdx` and `content/docs/about-next.mdx` for platform overview, then follow the section structure under `content/docs/`. diff --git a/app/docs/[[...slug]]/page.tsx b/app/docs/[[...slug]]/page.tsx index 6b39338..48c48ff 100644 --- a/app/docs/[[...slug]]/page.tsx +++ b/app/docs/[[...slug]]/page.tsx @@ -26,7 +26,7 @@ export default async function Page(props: { {page.data.description} - + ); diff --git a/app/llms.txt/route.ts b/app/llms.txt/route.ts index 0766ab3..0f4b525 100644 --- a/app/llms.txt/route.ts +++ b/app/llms.txt/route.ts @@ -31,7 +31,7 @@ export function GET() { '', '## Capability map and domain bundles', '', - `[capabilities.json](${capabilityMap.sources.developer_docs}/capabilities.json) ([readable](${capabilityMap.sources.developer_docs}/docs/capabilities)) links each platform capability to its merchant guides here, its developer guides, Admin API operations, webhook events, and skills under a stable id; pages on this site declare their ids in a \`capability_ids\` frontmatter field. Domain bundles are plain Markdown, one per domain:`, + `[capabilities.json](${capabilityMap.sources.developer_docs}/capabilities.json) links each platform capability to its merchant guides here, its developer guides, Admin API operations, webhook events, and skills. Page relationships are derived from the URLs in the map. Domain bundles are plain Markdown, one per domain:`, '', ...capabilityMap.bundles.map((b) => `- [${b.title}](${b.url}): ${b.intro}`), '', diff --git a/app/not-found.tsx b/app/not-found.tsx index fe6f7c6..66b1b69 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -4,7 +4,6 @@ const recoveryLinks = [ { label: 'Browse all docs', href: '/docs' }, { label: 'Changelog', href: '/changelog' }, { label: 'Developer docs', href: 'https://developers.nextcommerce.com' }, - { label: 'Capability map', href: 'https://developers.nextcommerce.com/docs/capabilities' }, { label: 'Agent index (llms.txt)', href: '/llms.txt' }, ]; diff --git a/components/developer-resources.tsx b/components/developer-resources.tsx index b7de96f..81d41b5 100644 --- a/components/developer-resources.tsx +++ b/components/developer-resources.tsx @@ -3,63 +3,61 @@ import capabilityMap from '@/lib/capabilities.snapshot.json'; interface Capability { id: string; title: string; + audiences: string[]; + operator_docs: string[]; developer_docs: string[]; - api_operations: { id: string; method: string; path: string; url: string | null }[]; - webhooks: { event: string; url: string | null }[]; } -const DEVELOPER_SITE: string = capabilityMap.sources.developer_docs; +const MERCHANT_SITE: string = capabilityMap.sources.merchant_docs; const capabilities = capabilityMap.capabilities as Capability[]; -const byId = new Map(capabilities.map((c) => [c.id, c])); + +function documentPath(url: string, base?: string) { + const path = new URL(url, base).pathname.replace(/\/+$/, ''); + return path || '/'; +} /** - * Developer resources for the capabilities a merchant page declares in - * `capability_ids`. Driven by the capability map snapshot the developer site - * publishes, so the links here are the same ones the map and the developer - * pages carry back to this site. + * A compact developer handoff for merchant pages explicitly cited by the + * capability map. The first developer_docs entry is the capability's entry + * page; detailed references remain in the map and domain bundles. */ -export function DeveloperResources({ ids }: { ids?: string[] }) { - const matched = (ids ?? []).map((id) => byId.get(id)).filter((c): c is Capability => Boolean(c)); - if (matched.length === 0) return null; - const withCounts = matched.filter((c) => c.api_operations.length > 0 || c.webhooks.length > 0); +export function DeveloperResources({ pageUrl }: { pageUrl: string }) { + const currentPath = documentPath(pageUrl, `${MERCHANT_SITE}/`); + const seen = new Set(); + const resources = capabilities + .flatMap((capability) => { + if (!Array.isArray(capability.audiences) || !Array.isArray(capability.operator_docs) || !Array.isArray(capability.developer_docs)) { + throw new Error(`Capability ${capability.id} has invalid documentation links`); + } + if (!capability.operator_docs.some((url) => documentPath(url) === currentPath)) return []; + + const entryUrl = capability.developer_docs[0]; + if (!entryUrl) { + if (capability.audiences.includes('developer')) { + throw new Error(`Capability ${capability.id} has no developer entry page`); + } + return []; + } + if (seen.has(entryUrl)) return []; + seen.add(entryUrl); + return [{ id: capability.id, title: capability.title, url: entryUrl }]; + }); + + if (resources.length === 0) return null; return ( -