Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ Vocs-powered documentation site for Tempo protocol. Use this guidance when creat

- `src/lib/docs-sections.ts` owns the section labels, landing routes, and route ownership; `vocs.config.ts` owns the sidebar within each section.
- Primary sections: Get Started (`/get-started`), Accounts (`/docs/accounts`), Earn (`/docs/earn`), Routes (`/docs/routes`), Zones (`/docs/zones`), and Machine Payments (`/docs/agents`). Get Started also owns the SDK, CLI, wallet CLI, and server handler pages (`/docs/sdk`, `/docs/cli`, `/docs/wallet`, `/docs/server`) as its Tempo CLI and Tempo SDK sections.
- Tempo EVM (`/docs/development`) covers wallets and signing keys, transactions, fees, TIP-20 Tokens, contracts, exchange, network details, nodes, protocol specifications, and changelog.
- Tempo EVM (`/docs/development`) covers wallets and signing keys, transactions, fees, TIP-20 Tokens, contracts, exchange, network details, and protocol specifications.
- Nodes (`/docs/guide/node`) covers node installation, RPC and validator operations, security, monitoring, failover, and operator updates. Changelog (`/docs/protocol/upgrades`) covers network upgrades and node releases (`/docs/changelog`). Both have their own sidebars and shared navigation links beside API reference.
- API reference (`/docs/api`) is its own top-nav link, matching Console's "API Docs" link. Partners (`/docs/partners`) contains third-party integrations. The old APIs & SDKs hub (`/docs/tools`) redirects to `/docs/sdk`.
- Keep Earn and Routes beta notices and the Zones limited-preview notice on their overview pages. The earlier `/docs/guide/private-zones` sandbox is a separate integration.
- `SKILL.md` is the docs site's published skill. The installable plugin's skill lives in `tempoxyz/plugins`; update it separately when routing changes.
Expand Down
6 changes: 4 additions & 2 deletions SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: tempo-docs
description: Find and explain official Tempo documentation for stablecoin accounts and payments, Earn vaults, Routes, Zones, Machine Payments, Tempo EVM, APIs, SDKs, CLI tools, and ecosystem integrations. Use for Tempo integration questions, code examples, protocol behavior, and documentation lookup.
description: Find and explain official Tempo documentation for stablecoin accounts and payments, Earn vaults, Routes, Zones, Machine Payments, Tempo EVM, APIs, SDKs, CLI tools, node operations, changelog, and ecosystem integrations. Use for Tempo integration questions, code examples, protocol behavior, and documentation lookup.
---

# Tempo Docs
Expand All @@ -19,8 +19,10 @@ All links below use the canonical docs mount at `https://tempo.xyz/developers`.
| [Routes](https://tempo.xyz/developers/docs/routes.md) | Accept cross-network deposits, quote transfers, or track delivery. Routes is in beta; check access on the introduction page. |
| [Zones](https://tempo.xyz/developers/docs/zones.md) | Connect to a Zone and work with private balances, deposits, or withdrawals. Zones is in limited preview; check access on the introduction page. |
| [Machine Payments](https://tempo.xyz/developers/docs/agents.md) | Pay for APIs, accept API payments, discover services, or integrate MPP. |
| [Tempo EVM](https://tempo.xyz/developers/docs/development.md) | Build wallet support, manage signing keys, use transactions and fees, issue TIP-20 Tokens, deploy contracts, exchange stablecoins, run nodes, or read protocol specifications and changelog. |
| [Tempo EVM](https://tempo.xyz/developers/docs/development.md) | Build wallet support, manage signing keys, use transactions and fees, issue TIP-20 Tokens, deploy contracts, exchange stablecoins, or read protocol specifications. |
| [API reference](https://tempo.xyz/developers/docs/api.md) | Find Tempo API endpoints by product, authentication, Console management endpoints, JSON-RPC, and the indexer. |
| [Nodes](https://tempo.xyz/developers/docs/guide/node.md) | Install, run, secure, monitor, troubleshoot, and upgrade RPC, standby, or validator nodes. |
| [Changelog](https://tempo.xyz/developers/docs/protocol/upgrades.md) | Track network upgrades, protocol activation, integration impact, and node software releases. |
| [Partners](https://tempo.xyz/developers/docs/partners.md) | Find third-party wallets, bridges, RPC infrastructure, data services, and integrations. |

Accounts covers application payment workflows; Tempo EVM covers the chain capabilities behind them. Routes covers cross-network movement. The API reference supplements product guides with exact endpoints and schemas. SDKs and the CLI are under Get Started.
Expand Down
101 changes: 83 additions & 18 deletions e2e/docs-workspace.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const sectionLabels = [
'Machine Payments',
'Tempo EVM',
]
const utilityLabels = ['API reference', 'Partners']
const utilityLabels = ['API reference', 'Nodes', 'Changelog', 'Partners']
const externalTools = [
['MPP', 'https://mpp.dev/'],
['Mercator', 'https://mercator.sh/'],
Expand Down Expand Up @@ -200,7 +200,6 @@ for (const section of [
'/docs/guide/issuance/create-a-stablecoin',
'/docs/guide/stablecoin-dex/executing-swaps',
'/docs/guide/issuance/manage-stablecoin',
'/docs/guide/node/installation',
],
},
{
Expand Down Expand Up @@ -234,7 +233,16 @@ for (const section of [
paths: ['/docs/api/console', '/docs/api/console/api-keys', '/docs/api/team'],
},
{
label: 'Tempo EVM (Changelog)',
label: 'Nodes',
overview: '/docs/guide/node',
paths: [
'/docs/guide/node/installation',
'/docs/guide/node/validator-keys',
'/docs/guide/node/network-upgrades',
],
},
{
label: 'Changelog',
overview: '/docs/protocol/upgrades',
paths: ['/docs/protocol/upgrades/t11', '/docs/changelog'],
},
Expand Down Expand Up @@ -344,23 +352,84 @@ test('Earn task pages and API reference remain distinct', async ({ page }) => {
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('API reference')
})

test('Changelog lives inside Tempo EVM and retains upgrade URLs', async ({ page }) => {
test('Changelog has its own sidebar and retains upgrade and release URLs', async ({ page }) => {
await page.goto('/docs/development')
const sidebar = page.locator('[data-v-gutter-left] [data-v-sidebar-container]')
await expect(page.locator('.docs-section-utilities').getByText('Changelog')).toHaveCount(0)
await sidebar.getByRole('button', { name: 'Changelog', exact: true }).click()
await sidebar.locator('a[href="/docs/protocol/upgrades"]').click()
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Tempo EVM')
await expect(sidebar.getByRole('button', { name: 'Changelog', exact: true })).toHaveCount(0)
await expect(sidebar.getByRole('button', { name: 'Run a node', exact: true })).toHaveCount(0)
await page
.locator('.docs-section-utilities')
.getByRole('link', { name: 'Changelog', exact: true })
.click()
await expect(page).toHaveURL(/\/docs\/protocol\/upgrades\/?$/)
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Changelog')
await expect(sidebar.locator('a[href="/docs/development"]')).toHaveCount(0)
await sidebar.locator('a[href="/docs/protocol/upgrades/t11"]').click()
await expect(page.getByRole('heading', { level: 1 })).toHaveText('T11 Network Upgrade')
expect((await page.reload())?.status()).toBe(200)
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Tempo EVM')
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Changelog')
await sidebar.getByRole('link', { name: 'Node releases', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/changelog\/?$/)
await sidebar.locator('a[href="/docs/development"]').click()
await expect(page).toHaveURL(/\/docs\/development\/?$/)
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Changelog')
await sidebar.getByRole('link', { name: 'Operator updates', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/guide\/node\/network-upgrades\/?$/)
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Nodes')
await expect(sidebar.getByRole('link', { name: 'Run a node', exact: true })).toBeVisible()
})

for (const mobile of [false, true]) {
test(`${mobile ? 'mobile' : 'desktop'} Nodes navigation opens its own operating guides`, async ({
page,
}) => {
await page.setViewportSize(mobile ? { width: 390, height: 844 } : { width: 1440, height: 1000 })
await page.goto('/docs/development')
if (mobile) {
await page.getByRole('button', { name: 'Open menu', exact: true }).click()
await page
.getByRole('dialog', { name: 'Documentation navigation', exact: true })
.getByRole('link', { name: 'Nodes', exact: true })
.click()
} else {
await page
.locator('.docs-section-utilities')
.getByRole('link', { name: 'Nodes', exact: true })
.click()
}
await expect(page).toHaveURL(/\/docs\/guide\/node\/?$/)
await expect(page.getByRole('heading', { level: 1 })).toHaveText('Run a node')
if (mobile)
await page.getByRole('button', { name: 'Open docs navigation', exact: true }).click()
const sidebar = mobile
? page.getByRole('dialog', { name: 'Documentation', exact: true })
: page.locator('[data-v-gutter-left] [data-v-sidebar-container]')
await expect(sidebar.getByRole('link', { name: 'Installation', exact: true })).toBeVisible()
await expect(sidebar.getByRole('link', { name: 'Operator updates', exact: true })).toBeVisible()
await expect(sidebar.locator('a[href="/docs/development"]')).toHaveCount(0)
await developerDisclosure(sidebar, 'Run a validator', mobile).click()
await sidebar.getByRole('link', { name: 'Managing validator keys', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/guide\/node\/validator-keys\/?$/)
expect((await page.reload())?.status()).toBe(200)
if (mobile)
await page.getByRole('button', { name: 'Open docs navigation', exact: true }).click()
await expectOnlyActiveLeaf(sidebar, '/docs/guide/node/validator-keys')
await expect(
sidebar.getByRole('link', { name: 'Validator failover', exact: true }),
).toBeVisible()
await sidebar.getByRole('link', { name: 'Operator updates', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/guide\/node\/network-upgrades\/?$/)
if (mobile) {
await page.getByRole('button', { name: 'Open menu', exact: true }).click()
await expect(
page
.getByRole('dialog', { name: 'Documentation navigation', exact: true })
.getByRole('link', { name: 'Nodes', exact: true }),
).toHaveAttribute('aria-current', 'page')
} else {
await expect(page.locator('.docs-section-nav [aria-current="page"]')).toHaveText('Nodes')
}
})
}

test('API reference is a keyboard-accessible utility and the old tools hub redirects', async ({
page,
}) => {
Expand Down Expand Up @@ -399,16 +468,12 @@ for (const path of ['/', '/blog']) {
await expect(link).toHaveAttribute('target', '_blank')
await expect(link).toHaveAttribute('rel', /noopener/)
}
await menu.getByRole('link', { name: 'Tempo EVM', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/development\/?$/)
await menu.getByRole('link', { name: 'Changelog', exact: true }).click()
await expect(page).toHaveURL(/\/docs\/protocol\/upgrades\/?$/)
await expect(menu).toBeHidden()
await expect(page.locator('body')).not.toHaveCSS('overflow', 'hidden')
await page.getByRole('button', { name: 'Open docs navigation', exact: true }).click()
const drawer = page.getByRole('dialog', { name: 'Documentation', exact: true })
await drawer
.locator('summary')
.filter({ hasText: /^Changelog$/ })
.click()
await drawer.locator('a[href="/docs/protocol/upgrades/t12"]').click()
await expect(page).toHaveURL(/\/docs\/protocol\/upgrades\/t12\/?$/)
await expect(drawer).toBeHidden()
Expand Down Expand Up @@ -732,7 +797,7 @@ test('mobile article drawer traps focus and survives client navigation', async (
const drawer = page.getByRole('dialog', { name: 'Documentation', exact: true })
const close = drawer.getByRole('button', { name: 'Close docs navigation', exact: true })
await expect(close).toBeFocused()
const specifications = drawer.locator('summary').filter({ hasText: /^Changelog$/ })
const specifications = drawer.getByRole('link', { name: 'All specifications', exact: true })
await page.keyboard.press('Shift+Tab')
await expect(specifications).toBeFocused()
await page.keyboard.press('Tab')
Expand Down
18 changes: 10 additions & 8 deletions src/components/DocsHeader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ describe('getActiveDocsSection', () => {
it('keeps section navigation active under the developers mount and trailing slashes', () => {
expect(getActiveDocsSection('/developers/docs/api/transfers/')?.id).toBe('api')
expect(getActiveDocsSection('/developers/get-started/')?.id).toBe('overview')
expect(getActiveDocsSection('/developers/docs/protocol/upgrades/t12/')?.id).toBe('developers')
expect(getActiveDocsSection('/developers/docs/protocol/upgrades/t12/')?.id).toBe('changelog')
expect(getActiveDocsSection('/developers/docs/protocol/')?.label).toBe('Tempo EVM')
})

Expand Down Expand Up @@ -138,13 +138,15 @@ describe('getActiveDocsSection', () => {
['/docs/protocol/tip403/spec', 'developers'],
['/docs/protocol/exchange/spec', 'developers'],
['/docs/protocol/blockspace/payment-lane-specification', 'developers'],
['/docs/guide/node/installation', 'developers'],
['/docs/protocol/upgrades', 'developers'],
['/docs/protocol/upgrades/t11', 'developers'],
['/docs/protocol/upgrades/t12', 'developers'],
['/docs/guide/node/upgrade-cadence', 'developers'],
['/docs/guide/node/network-upgrades', 'developers'],
['/docs/changelog', 'developers'],
['/docs/guide/node', 'nodes'],
['/docs/guide/node/installation', 'nodes'],
['/docs/guide/node/validator-keys', 'nodes'],
['/docs/protocol/upgrades', 'changelog'],
['/docs/protocol/upgrades/t11', 'changelog'],
['/docs/protocol/upgrades/t12', 'changelog'],
['/docs/guide/node/upgrade-cadence', 'nodes'],
['/docs/guide/node/network-upgrades', 'nodes'],
['/docs/changelog', 'changelog'],
['/docs/api/indexer-api', 'api'],
['/docs/protocol/rpc/eth_getBalance', 'developers'],
['/docs/sdk/typescript', 'overview'],
Expand Down
2 changes: 2 additions & 0 deletions src/lib/ai-docs-dev.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ describe('development AI Markdown', () => {
expect(output.indexOf('<span id="deposit-funds" />')).toBeGreaterThan(second)
expect(output.slice(0, second)).toContain('<span id="earn" />')
expect(output).toContain('## API reference')
expect(output).toContain('## Nodes')
expect(output).toContain('## Changelog')
expect(() => renderAiDevFull(full.replace('# Deposit', '## Deposit'))).toThrow(
'page headings for 2 entries',
)
Expand Down
26 changes: 26 additions & 0 deletions src/lib/ai-docs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ const input = `# Tempo Docs
- [Machine Payments](/docs/agents): Pay for APIs.
- [API reference](/docs/api/reference): REST schemas.
- [Keys](/docs/accounts/keys): Chain signing permissions.
- [Install a node](/docs/guide/node/installation): Install the binary.
- [Operator updates](/docs/guide/node/network-upgrades): Required operator actions.
- [T12](/docs/protocol/upgrades/t12): Protocol upgrade.
- [Node releases](/docs/changelog): Software releases.
- [Home](/index): Site home.
`

Expand Down Expand Up @@ -50,6 +54,28 @@ describe('AI documentation navigation', () => {
expect(renderAiIndex(output)).toBe(output)
})

it('groups node operations and release history in their own sections and page context', () => {
const sections = new Map(
renderAiIndex(input)
.split(/^## /m)
.slice(1)
.map((section) => [section.split('\n')[0], section]),
)
expect(sections.get('Nodes')).toContain('[Install a node](/docs/guide/node/installation.md)')
expect(sections.get('Nodes')).toContain(
'[Operator updates](/docs/guide/node/network-upgrades.md)',
)
expect(sections.get('Changelog')).toContain('[T12](/docs/protocol/upgrades/t12.md)')
expect(sections.get('Changelog')).toContain('[Node releases](/docs/changelog.md)')
expect(sections.get('Tempo EVM')).not.toMatch(/\[Install a node\]|\[T12\]|\[Node releases\]/)
for (const route of ['/docs/guide/node/validator-keys', '/docs/guide/node/network-upgrades'])
expect(renderAiPage('# Guide', route)).toContain('> Section: [Nodes](/docs/guide/node.md)')
for (const route of ['/docs/protocol/upgrades/t12', '/docs/changelog'])
expect(renderAiPage('# Changes', route)).toContain(
'> Section: [Changelog](/docs/protocol/upgrades.md)',
)
})

it('fails when a new docs route has no navigation owner', () => {
expect(() => renderAiIndex('- [Unassigned](/docs/new-product)')).toThrow(
'no AI navigation home',
Expand Down
8 changes: 6 additions & 2 deletions src/lib/ai-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from './docs-sections'

export const aiDocsDescription =
'Build stablecoin products with Accounts, Earn, Routes, Zones, and Machine Payments, or build on Tempo EVM. Find API references, SDKs, CLI tools, and partner integrations.'
'Build stablecoin products with Accounts, Earn, Routes, Zones, and Machine Payments, or build on Tempo EVM. Find API references, SDKs, CLI tools, node operations, changelog, and partner integrations.'

const sectionDescriptions: Partial<Record<DocsSection['id'], string>> = {
overview:
Expand All @@ -22,8 +22,12 @@ const sectionDescriptions: Partial<Record<DocsSection['id'], string>> = {
'machine-payments':
'Pay for APIs, accept API payments, find services, and use MPP (https://mpp.dev).',
developers:
'Build on Tempo EVM: wallets and keys, transactions and fees, TIP-20 Tokens, contracts, exchange, network details, nodes, protocol specifications, and changelog.',
'Build on Tempo EVM: wallets and keys, transactions and fees, TIP-20 Tokens, contracts, exchange, network details, and protocol specifications.',
api: 'Tempo API reference: authentication, conventions, endpoints grouped by product, Console management endpoints, JSON-RPC, and the indexer. An API key authenticates API requests; an account signing key authorizes transactions.',
nodes:
'Run and maintain Tempo RPC, standby, and validator nodes: installation, network identity, security, keys, monitoring, failover, troubleshooting, and required operator updates.',
changelog:
'Track network upgrades, protocol activation and integration impact, and node software releases. Use Nodes for upgrade procedures and operator guidance.',
ecosystem:
'Find wallet providers, bridges, RPC infrastructure, data services, and other third-party integrations.',
}
Expand Down
16 changes: 14 additions & 2 deletions src/lib/docs-sections.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ export type DocsSection = {
| 'routes'
| 'zones'
| 'developers'
| 'nodes'
| 'changelog'
| 'machine-payments'
| 'api'
| 'tools'
Expand Down Expand Up @@ -74,11 +76,9 @@ export const docsSections: DocsSection[] = [
'/docs/development',
'/docs/quickstart',
'/docs/protocol',
'/docs/changelog',
'/docs/guide/tempo-transaction',
'/docs/guide/issuance',
'/docs/guide/stablecoin-dex',
'/docs/guide/node',
],
},
]
Expand All @@ -90,6 +90,18 @@ export const docsUtilitySections: DocsSection[] = [
href: '/docs/api',
matches: ['/docs/api'],
},
{
id: 'nodes',
label: 'Nodes',
href: '/docs/guide/node',
matches: ['/docs/guide/node'],
},
{
id: 'changelog',
label: 'Changelog',
href: '/docs/protocol/upgrades',
matches: ['/docs/protocol/upgrades', '/docs/changelog'],
},
{
id: 'ecosystem',
label: 'Partners',
Expand Down
Loading
Loading