-
Notifications
You must be signed in to change notification settings - Fork 0
Agent entry surfaces: llms.txt, AGENTS.md, generated counts, 404, cross-refs #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
f818df1
Agent entry surfaces: llms.txt, AGENTS.md, generated counts, 404, cro…
next-devin a8eefdb
developer-docs#48 review: plain anchors on 404, escape llms.txt link …
next-devin 1c70301
Retrigger Workers build
next-devin 6b49567
llms.txt: escape brackets in descriptions as well as titles
next-devin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Agent guide for developers.nextcommerce.com | ||
|
|
||
| This file is the navigation and evidence contract for an agent reading the Next Commerce developer documentation. It is not a setup script. Agent setup instructions will live at /agent-setup/prompt.md (tracked in developer-docs#45). | ||
|
|
||
| ## What this site is | ||
|
|
||
| https://developers.nextcommerce.com documents the Next Commerce platform for developers: the Admin API (REST), webhooks, storefront themes and the storefront GraphQL API, campaigns and the Campaign Cart SDK, apps and OAuth, AI agent skills, and testing. | ||
|
|
||
| The sibling site, https://docs.nextcommerce.com, is the merchant and operator documentation: dashboard guides, store configuration, payments operations, and the platform changelog. Questions about how to operate a store belong there; questions about how to integrate with it belong here. | ||
|
|
||
| ## Where to start | ||
|
|
||
| - https://developers.nextcommerce.com/llms.txt is the page index for this site, with a one-line description per page and absolute URLs. | ||
| - https://developers.nextcommerce.com/llms-full.txt is the full corpus in one file. It is large (about 1.5 MB); fetch it only when you need broad coverage rather than a specific page. | ||
| - Raw OpenAPI specs, which are the authority for operations, parameters, and fields: | ||
| - https://developers.nextcommerce.com/api/admin/2024-04-01.yaml (stable) | ||
| - https://developers.nextcommerce.com/api/admin/unstable.yaml | ||
| - https://developers.nextcommerce.com/api/admin/2023-02-10.yaml (deprecated) | ||
| - https://developers.nextcommerce.com/api/campaigns/v1.yaml | ||
| - https://developers.nextcommerce.com/docs/webhooks lists every webhook event and the payload structure. | ||
| - https://developers.nextcommerce.com/docs/testing covers test cards, test orders, and sandbox behavior. | ||
| - https://docs.nextcommerce.com/llms.txt is the equivalent index for the merchant site. | ||
|
|
||
| ## Evidence rules | ||
|
|
||
| - Cite the page URL for every claim you make from this documentation. | ||
| - For facts about an operation, parameter, or field, prefer the versioned spec over prose pages. The prose explains; the spec is the contract. | ||
| - The changelog at https://docs.nextcommerce.com/changelog is the record of what changed and when. Do not infer release history from page contents. | ||
| - NEXT Payments processing rates are not published. If asked, say so rather than estimating. | ||
| - Do not "correct" identifiers containing 29next. See Legacy identifiers below. | ||
| - If the documentation does not answer a question, say that it does not. Do not fill gaps from general ecommerce knowledge and present the result as Next Commerce behavior. | ||
|
|
||
| ## Versions | ||
|
|
||
| The Admin API is versioned by date. The version is selected per request with the `X-29next-API-Version` header. | ||
|
|
||
| - `2024-04-01`: stable, recommended for all new integrations. | ||
| - `2023-02-10`: deprecated; documented for existing integrations only. | ||
| - `unstable`: in-progress changes; may change without notice. | ||
|
|
||
| Each version has its own spec file (listed above) and its own reference section on the site. When a question names a version, answer from that version's spec. | ||
|
|
||
| ## Legacy identifiers | ||
|
|
||
| Next Commerce was formerly 29 Next. Hostnames like `{store}.29next.store`, `accounts.29next.com`, and headers like `X-29next-API-Version` and `X-29Next-Signature` are current, valid technical identifiers and must be used exactly as written. | ||
|
|
||
| ## Corrections | ||
|
|
||
| Outside pull requests to this repository are not accepted. The support route for reporting documentation errors is being confirmed and will be linked here. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,18 +1,3 @@ | ||
|
|
||
| ## Skill routing | ||
|
|
||
| When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill. | ||
|
|
||
| Key routing rules: | ||
| - Product ideas/brainstorming → invoke /office-hours | ||
| - Strategy/scope → invoke /plan-ceo-review | ||
| - Architecture → invoke /plan-eng-review | ||
| - Design system/plan review → invoke /design-consultation or /plan-design-review | ||
| - Full review pipeline → invoke /autoplan | ||
| - Bugs/errors → invoke /investigate | ||
| - QA/testing site behavior → invoke /qa or /qa-only | ||
| - Code review/diff check → invoke /review | ||
| - Visual polish → invoke /design-review | ||
| - Ship/deploy/PR → invoke /ship or /land-and-deploy | ||
| - Save progress → invoke /context-save | ||
| - Resume context → invoke /context-restore | ||
| The public contract for agents reading this repository or the site it publishes is AGENTS.md. | ||
| See ./AGENTS.md for navigation, evidence rules, API versions, and legacy identifiers. | ||
| Internal tool routing for the maintainers' own sessions is not kept in this repository. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,8 +1,116 @@ | ||
| import { source } from '@/lib/source'; | ||
| import { llms } from 'fumadocs-core/source'; | ||
|
|
||
| export const revalidate = false; | ||
|
|
||
| const SITE = 'https://developers.nextcommerce.com'; | ||
| const MERCHANT_SITE = 'https://docs.nextcommerce.com'; | ||
|
|
||
| // Groups named here come first, in this order; any other top-level folder | ||
| // follows alphabetically. 'index' is the /docs root page itself. | ||
| const PREFERRED_GROUP_ORDER = [ | ||
| 'index', | ||
| 'admin-api', | ||
| 'webhooks', | ||
| 'storefront', | ||
| 'campaigns', | ||
| 'apps', | ||
| 'skills', | ||
| 'testing', | ||
| ]; | ||
|
|
||
| const GROUP_TITLES: Record<string, string> = { | ||
| index: 'Overview', | ||
| 'admin-api': 'Admin API', | ||
| webhooks: 'Webhooks', | ||
| storefront: 'Storefront', | ||
| campaigns: 'Campaigns', | ||
| apps: 'Apps', | ||
| skills: 'Skills', | ||
| testing: 'Testing', | ||
| }; | ||
|
|
||
| function groupTitle(key: string): string { | ||
| if (GROUP_TITLES[key]) return GROUP_TITLES[key]; | ||
| return key | ||
| .split('-') | ||
| .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) | ||
| .join(' '); | ||
| } | ||
|
|
||
| function groupKey(url: string): string { | ||
| const rest = url.replace(/^\/docs\/?/, ''); | ||
| const first = rest.split('/')[0]; | ||
| return first || 'index'; | ||
| } | ||
|
|
||
| // Frontmatter values are interpolated into Markdown link syntax; keep each | ||
| // page on exactly one line and neutralise the characters that would break it. | ||
| function oneLine(value: string): string { | ||
| return value.replace(/\s+/g, ' ').trim(); | ||
| } | ||
|
|
||
| function linkText(value: string): string { | ||
| return oneLine(value).replace(/[\[\]]/g, '\\$&'); | ||
| } | ||
|
|
||
| function header(): string { | ||
| return [ | ||
| '# Next Commerce Developer Docs', | ||
| '', | ||
| '> API, webhook, storefront theme, campaign, and app documentation for Next Commerce, the ecommerce platform for direct-to-consumer brands. Merchant and operator guides live on the sibling site.', | ||
| '', | ||
| '## Start here', | ||
| '', | ||
| `- [Developer docs home](${SITE})`, | ||
| `- [Merchant docs](${MERCHANT_SITE}): guides for store operators, on the sibling site`, | ||
| `- [Merchant docs index](${MERCHANT_SITE}/llms.txt)`, | ||
| `- [Platform and API changelog](${MERCHANT_SITE}/changelog): the developer portal has no changelog of its own`, | ||
| `- [Full corpus](${SITE}/llms-full.txt): every page in one file (large, about 1.5 MB)`, | ||
| `- [Admin API spec, 2024-04-01](${SITE}/api/admin/2024-04-01.yaml): stable, raw OpenAPI`, | ||
| `- [Admin API spec, unstable](${SITE}/api/admin/unstable.yaml): raw OpenAPI`, | ||
| `- [Admin API spec, 2023-02-10](${SITE}/api/admin/2023-02-10.yaml): deprecated, raw OpenAPI`, | ||
| `- [Campaigns API spec, v1](${SITE}/api/campaigns/v1.yaml): raw OpenAPI`, | ||
| `- [Webhooks](${SITE}/docs/webhooks)`, | ||
| `- [Skills](${SITE}/docs/skills): AI agent skills for the platform`, | ||
| `- [Testing](${SITE}/docs/testing)`, | ||
| `- [Agent guide (AGENTS.md)](https://github.com/NextCommerceCo/developer-docs/blob/main/AGENTS.md): navigation and evidence rules for agents reading this site`, | ||
| '', | ||
| '## Legacy identifiers', | ||
| '', | ||
| 'Next Commerce was formerly 29 Next. Hostnames like `{store}.29next.store`, `accounts.29next.com`, and headers like `X-29next-API-Version` and `X-29Next-Signature` are current, valid technical identifiers and must be used exactly as written.', | ||
| '', | ||
| ].join('\n'); | ||
| } | ||
|
|
||
| export function GET() { | ||
| return new Response(llms(source).index()); | ||
| const groups = new Map<string, string[]>(); | ||
|
|
||
| for (const page of source.getPages()) { | ||
| const key = groupKey(page.url); | ||
| const title = linkText(page.data.title ?? page.url); | ||
| const description = page.data.description ? linkText(page.data.description) : ''; | ||
| const line = description | ||
| ? `- [${title}](${SITE}${page.url}): ${description}` | ||
| : `- [${title}](${SITE}${page.url})`; | ||
| const list = groups.get(key) ?? []; | ||
| list.push(line); | ||
| groups.set(key, list); | ||
| } | ||
|
|
||
| const keys = [...groups.keys()].sort((a, b) => { | ||
| const ia = PREFERRED_GROUP_ORDER.indexOf(a); | ||
| const ib = PREFERRED_GROUP_ORDER.indexOf(b); | ||
| if (ia !== -1 && ib !== -1) return ia - ib; | ||
| if (ia !== -1) return -1; | ||
| if (ib !== -1) return 1; | ||
| return a.localeCompare(b); | ||
| }); | ||
|
|
||
| const body = keys | ||
| .map((key) => `## ${groupTitle(key)}\n\n${groups.get(key)!.join('\n')}\n`) | ||
| .join('\n'); | ||
|
|
||
| return new Response(header() + '\n' + body, { | ||
| headers: { 'Content-Type': 'text/plain; charset=utf-8' }, | ||
| }); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| import Link from 'next/link'; | ||
|
|
||
| export default function NotFound() { | ||
| return ( | ||
| <main className="flex min-h-screen flex-col items-center justify-center bg-fd-background px-6 text-fd-foreground"> | ||
| <div className="flex w-full max-w-md flex-col gap-6"> | ||
| <div className="flex flex-col gap-2"> | ||
| <h1 className="text-2xl font-semibold">Page not found</h1> | ||
| <p className="text-sm text-fd-muted-foreground"> | ||
| The page you asked for does not exist or has moved. | ||
| </p> | ||
| </div> | ||
| <nav aria-label="Recovery links"> | ||
| <ul className="flex flex-col gap-2 text-sm"> | ||
| <li><Link href="/docs">Browse all docs</Link></li> | ||
| <li><Link href="/docs/admin-api">Admin API</Link></li> | ||
| <li><Link href="/docs/webhooks">Webhooks</Link></li> | ||
| <li><a href="https://docs.nextcommerce.com">Merchant docs</a></li> | ||
| <li><a href="https://docs.nextcommerce.com/changelog">Changelog</a></li> | ||
| <li><Link href="/llms.txt">Agent index (llms.txt)</Link></li> | ||
| </ul> | ||
| </nav> | ||
| </div> | ||
| </main> | ||
| ); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| /** | ||
| * Post-build assertions for the agent entry surfaces. | ||
| * Run after `npm run build`; exits 1 on the first failing group. | ||
| */ | ||
|
|
||
| import { readFileSync, existsSync } from 'fs'; | ||
| import { join, resolve, dirname } from 'path'; | ||
| import { fileURLToPath } from 'url'; | ||
|
|
||
| const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
| const ROOT = resolve(__dirname, '..'); | ||
| const OUT = join(ROOT, 'out'); | ||
|
|
||
| const failures = []; | ||
| function check(condition, message) { | ||
| if (!condition) failures.push(message); | ||
| } | ||
|
|
||
| function read(path) { | ||
| return existsSync(path) ? readFileSync(path, 'utf8') : null; | ||
| } | ||
|
|
||
| // llms.txt | ||
| const llmsPath = join(OUT, 'llms.txt'); | ||
| const llms = read(llmsPath); | ||
| check(llms !== null, 'out/llms.txt does not exist'); | ||
| if (llms !== null) { | ||
| const firstLine = llms.split('\n')[0]; | ||
| check(firstLine === '# Next Commerce Developer Docs', `llms.txt first line is ${JSON.stringify(firstLine)}`); | ||
| const relative = llms.match(/\]\(\//g) ?? []; | ||
| check(relative.length === 0, `llms.txt has ${relative.length} relative markdown link(s)`); | ||
| for (const needle of [ | ||
| 'https://docs.nextcommerce.com/llms.txt', | ||
| 'https://docs.nextcommerce.com/changelog', | ||
| '/api/admin/2024-04-01.yaml', | ||
| '/docs/webhooks', | ||
| 'AGENTS.md', | ||
| ]) { | ||
| check(llms.includes(needle), `llms.txt is missing ${JSON.stringify(needle)}`); | ||
| } | ||
| } | ||
|
|
||
| // 404 page | ||
| const notFound = read(join(OUT, '404.html')); | ||
| check(notFound !== null, 'out/404.html does not exist'); | ||
| if (notFound !== null) { | ||
| for (const needle of ['/llms.txt', 'https://docs.nextcommerce.com']) { | ||
| check(notFound.includes(needle), `404.html is missing ${JSON.stringify(needle)}`); | ||
| } | ||
| } | ||
|
|
||
| // stats.json and the home page | ||
| const statsPath = join(ROOT, 'lib', 'generated', 'stats.json'); | ||
| const statsRaw = read(statsPath); | ||
| check(statsRaw !== null, 'lib/generated/stats.json does not exist'); | ||
| if (statsRaw !== null) { | ||
| const stats = JSON.parse(statsRaw); | ||
| check(stats.adminApiOperations > 0, `stats.adminApiOperations is ${stats.adminApiOperations}`); | ||
| check(stats.webhookEvents > 0, `stats.webhookEvents is ${stats.webhookEvents}`); | ||
| const index = read(join(OUT, 'index.html')); | ||
|
next-devin marked this conversation as resolved.
|
||
| check(index !== null, 'out/index.html does not exist'); | ||
| if (index !== null) { | ||
| for (const needle of [ | ||
| `<span>${stats.adminApiOperations} REST Endpoints</span>`, | ||
| `<span>${stats.webhookEvents} Webhook Events</span>`, | ||
| ]) { | ||
| check(index.includes(needle), `index.html is missing ${JSON.stringify(needle)}`); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (failures.length > 0) { | ||
| console.error('check-agent-surfaces: FAIL'); | ||
| for (const f of failures) console.error(` - ${f}`); | ||
| process.exit(1); | ||
| } | ||
| console.log('check-agent-surfaces: OK'); | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.