From 75acdb1b93e9c753a52804129cd23716bea7e649 Mon Sep 17 00:00:00 2001
From: Derek <256792747+decofe@users.noreply.github.com>
Date: Fri, 26 Jun 2026 05:06:22 +0000
Subject: [PATCH 1/5] Add docs SEO and AEO metadata
---
src/components/DocsJsonLd.tsx | 67 ++++++++++++++++++++
src/pages/docs/_layout.tsx | 2 +
src/pages/docs/guide/using-tempo-with-ai.mdx | 2 +
src/pages/docs/tools.mdx | 2 +
4 files changed, 73 insertions(+)
create mode 100644 src/components/DocsJsonLd.tsx
diff --git a/src/components/DocsJsonLd.tsx b/src/components/DocsJsonLd.tsx
new file mode 100644
index 00000000..73df5245
--- /dev/null
+++ b/src/components/DocsJsonLd.tsx
@@ -0,0 +1,67 @@
+const tempoSameAs = [
+ 'https://x.com/tempo',
+ 'https://twitter.com/tempo',
+ 'https://github.com/tempoxyz',
+ 'https://www.linkedin.com/company/tempoxyz',
+ 'https://www.crunchbase.com/organization/tempo-87e4',
+]
+
+const tempoKnowsAbout = [
+ 'stablecoin payments',
+ 'cross-border payments',
+ 'global payouts',
+ 'agentic payments',
+ 'machine payments',
+ 'enterprise settlement',
+ 'payment blockchains',
+ 'Layer 1 blockchain',
+ 'stablecoin infrastructure',
+]
+
+const description =
+ 'Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. Tempo documentation covers stablecoin payments, global payouts, agentic payments, APIs, wallets, and protocol specifications.'
+
+export default function DocsJsonLd(props: { path: string }) {
+ const pathname = props.path.startsWith('/') ? props.path : `/${props.path}`
+ const url = `https://docs.tempo.xyz${pathname}`
+ const schema = {
+ '@context': 'https://schema.org',
+ '@graph': [
+ {
+ '@type': 'Organization',
+ '@id': 'https://tempo.xyz/#organization',
+ name: 'Tempo',
+ url: 'https://tempo.xyz',
+ description,
+ sameAs: tempoSameAs,
+ knowsAbout: tempoKnowsAbout,
+ },
+ {
+ '@type': 'WebSite',
+ '@id': 'https://docs.tempo.xyz/#website',
+ name: 'Tempo Docs',
+ url: 'https://docs.tempo.xyz',
+ description,
+ publisher: { '@id': 'https://tempo.xyz/#organization' },
+ },
+ {
+ '@type': 'TechArticle',
+ '@id': url,
+ url,
+ headline: 'Tempo documentation',
+ description,
+ isPartOf: { '@id': 'https://docs.tempo.xyz/#website' },
+ about: { '@id': 'https://tempo.xyz/#organization' },
+ publisher: { '@id': 'https://tempo.xyz/#organization' },
+ },
+ ],
+ }
+
+ return (
+
+ )
+}
diff --git a/src/pages/docs/_layout.tsx b/src/pages/docs/_layout.tsx
index 7378fec6..b0e1f00c 100644
--- a/src/pages/docs/_layout.tsx
+++ b/src/pages/docs/_layout.tsx
@@ -2,6 +2,7 @@
import { lazy, type PropsWithChildren, Suspense } from 'react'
import DocsHeader from '../../components/DocsHeader'
+import DocsJsonLd from '../../components/DocsJsonLd'
import DocsSectionNav from '../../components/DocsSectionNav'
import DocsSidebarDrawer from '../../components/DocsSidebarDrawer'
import { usePageSettled } from '../../lib/pageSettled'
@@ -50,6 +51,7 @@ export default function DocsLayout(
return (
<>
+
diff --git a/src/pages/docs/guide/using-tempo-with-ai.mdx b/src/pages/docs/guide/using-tempo-with-ai.mdx
index 03177809..1049e3b1 100644
--- a/src/pages/docs/guide/using-tempo-with-ai.mdx
+++ b/src/pages/docs/guide/using-tempo-with-ai.mdx
@@ -12,6 +12,8 @@ import { TempoMcpExplorer } from '../../../components/TempoMcpExplorer.tsx'
Tempo publishes documentation, Markdown pages, MCP tools, and agent plugins so AI coding agents can work with Tempo using current project context instead of guesses.
+Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. If your agent needs non-code entity context before writing, start with [What is Tempo?](https://tempo.xyz/learn/what-is-tempo/) and [Best blockchain for stablecoin payments](https://tempo.xyz/learn/best-blockchain-for-stablecoin-payments/).
+
Use this page when you want Claude, Codex, Cursor, Amp, or another MCP-compatible client to search Tempo docs, read source-linked references, and install reusable Tempo workflows.
## Connect to Tempo's MCP server
diff --git a/src/pages/docs/tools.mdx b/src/pages/docs/tools.mdx
index 34071b21..bb50c14d 100644
--- a/src/pages/docs/tools.mdx
+++ b/src/pages/docs/tools.mdx
@@ -9,6 +9,8 @@ import { Cards, Card } from 'vocs'
Use this section when you need the implementation surface for Tempo: libraries, command-line tools, managed services, wallet integration, RPC references, and query access to network data.
+Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. For non-code entity context, see [What is Tempo?](https://tempo.xyz/learn/what-is-tempo/) and the [stablecoin payments comparison](https://tempo.xyz/learn/best-blockchain-for-stablecoin-payments/).
+
If you are integrating a product, start with the TypeScript SDKs and hosted services. If you are operating infrastructure or debugging low-level behavior, start with the CLI and RPC reference.
## Build with SDKs
From 143e1258927f3d1dc19148c218eca03af5ab982b Mon Sep 17 00:00:00 2001
From: Derek <256792747+decofe@users.noreply.github.com>
Date: Sat, 27 Jun 2026 07:33:13 +0000
Subject: [PATCH 2/5] Remove links to split entity pages
---
src/pages/docs/guide/using-tempo-with-ai.mdx | 2 --
src/pages/docs/tools.mdx | 2 --
2 files changed, 4 deletions(-)
diff --git a/src/pages/docs/guide/using-tempo-with-ai.mdx b/src/pages/docs/guide/using-tempo-with-ai.mdx
index 1049e3b1..03177809 100644
--- a/src/pages/docs/guide/using-tempo-with-ai.mdx
+++ b/src/pages/docs/guide/using-tempo-with-ai.mdx
@@ -12,8 +12,6 @@ import { TempoMcpExplorer } from '../../../components/TempoMcpExplorer.tsx'
Tempo publishes documentation, Markdown pages, MCP tools, and agent plugins so AI coding agents can work with Tempo using current project context instead of guesses.
-Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. If your agent needs non-code entity context before writing, start with [What is Tempo?](https://tempo.xyz/learn/what-is-tempo/) and [Best blockchain for stablecoin payments](https://tempo.xyz/learn/best-blockchain-for-stablecoin-payments/).
-
Use this page when you want Claude, Codex, Cursor, Amp, or another MCP-compatible client to search Tempo docs, read source-linked references, and install reusable Tempo workflows.
## Connect to Tempo's MCP server
diff --git a/src/pages/docs/tools.mdx b/src/pages/docs/tools.mdx
index bb50c14d..34071b21 100644
--- a/src/pages/docs/tools.mdx
+++ b/src/pages/docs/tools.mdx
@@ -9,8 +9,6 @@ import { Cards, Card } from 'vocs'
Use this section when you need the implementation surface for Tempo: libraries, command-line tools, managed services, wallet integration, RPC references, and query access to network data.
-Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. For non-code entity context, see [What is Tempo?](https://tempo.xyz/learn/what-is-tempo/) and the [stablecoin payments comparison](https://tempo.xyz/learn/best-blockchain-for-stablecoin-payments/).
-
If you are integrating a product, start with the TypeScript SDKs and hosted services. If you are operating infrastructure or debugging low-level behavior, start with the CLI and RPC reference.
## Build with SDKs
From 1f4f1b2fcf93b23dbe92e782f8ac837d6d3e8636 Mon Sep 17 00:00:00 2001
From: Derek <256792747+decofe@users.noreply.github.com>
Date: Sat, 27 Jun 2026 08:06:30 +0000
Subject: [PATCH 3/5] Handle missing docs path in JSON-LD
---
src/components/DocsJsonLd.tsx | 5 +++--
src/pages/docs/_layout.tsx | 2 +-
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/src/components/DocsJsonLd.tsx b/src/components/DocsJsonLd.tsx
index 73df5245..e05a701b 100644
--- a/src/components/DocsJsonLd.tsx
+++ b/src/components/DocsJsonLd.tsx
@@ -21,8 +21,9 @@ const tempoKnowsAbout = [
const description =
'Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. Tempo documentation covers stablecoin payments, global payouts, agentic payments, APIs, wallets, and protocol specifications.'
-export default function DocsJsonLd(props: { path: string }) {
- const pathname = props.path.startsWith('/') ? props.path : `/${props.path}`
+export default function DocsJsonLd(props: { path?: string }) {
+ const path = props.path || '/docs'
+ const pathname = path.startsWith('/') ? path : `/${path}`
const url = `https://docs.tempo.xyz${pathname}`
const schema = {
'@context': 'https://schema.org',
diff --git a/src/pages/docs/_layout.tsx b/src/pages/docs/_layout.tsx
index b0e1f00c..4b10489b 100644
--- a/src/pages/docs/_layout.tsx
+++ b/src/pages/docs/_layout.tsx
@@ -42,7 +42,7 @@ if (typeof window !== 'undefined') {
export default function DocsLayout(
props: PropsWithChildren<{
- path: string
+ path?: string
frontmatter?: { interactive?: boolean; mipd?: boolean }
}>,
) {
From 1ed9407038d650f1c5275b51c3e2decfb3795cb2 Mon Sep 17 00:00:00 2001
From: Derek <256792747+decofe@users.noreply.github.com>
Date: Sat, 27 Jun 2026 08:15:37 +0000
Subject: [PATCH 4/5] Split docs JSON-LD from robots PR
---
src/components/DocsJsonLd.tsx | 68 -----------------------------------
src/pages/docs/_layout.tsx | 4 +--
2 files changed, 1 insertion(+), 71 deletions(-)
delete mode 100644 src/components/DocsJsonLd.tsx
diff --git a/src/components/DocsJsonLd.tsx b/src/components/DocsJsonLd.tsx
deleted file mode 100644
index e05a701b..00000000
--- a/src/components/DocsJsonLd.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-const tempoSameAs = [
- 'https://x.com/tempo',
- 'https://twitter.com/tempo',
- 'https://github.com/tempoxyz',
- 'https://www.linkedin.com/company/tempoxyz',
- 'https://www.crunchbase.com/organization/tempo-87e4',
-]
-
-const tempoKnowsAbout = [
- 'stablecoin payments',
- 'cross-border payments',
- 'global payouts',
- 'agentic payments',
- 'machine payments',
- 'enterprise settlement',
- 'payment blockchains',
- 'Layer 1 blockchain',
- 'stablecoin infrastructure',
-]
-
-const description =
- 'Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. Tempo documentation covers stablecoin payments, global payouts, agentic payments, APIs, wallets, and protocol specifications.'
-
-export default function DocsJsonLd(props: { path?: string }) {
- const path = props.path || '/docs'
- const pathname = path.startsWith('/') ? path : `/${path}`
- const url = `https://docs.tempo.xyz${pathname}`
- const schema = {
- '@context': 'https://schema.org',
- '@graph': [
- {
- '@type': 'Organization',
- '@id': 'https://tempo.xyz/#organization',
- name: 'Tempo',
- url: 'https://tempo.xyz',
- description,
- sameAs: tempoSameAs,
- knowsAbout: tempoKnowsAbout,
- },
- {
- '@type': 'WebSite',
- '@id': 'https://docs.tempo.xyz/#website',
- name: 'Tempo Docs',
- url: 'https://docs.tempo.xyz',
- description,
- publisher: { '@id': 'https://tempo.xyz/#organization' },
- },
- {
- '@type': 'TechArticle',
- '@id': url,
- url,
- headline: 'Tempo documentation',
- description,
- isPartOf: { '@id': 'https://docs.tempo.xyz/#website' },
- about: { '@id': 'https://tempo.xyz/#organization' },
- publisher: { '@id': 'https://tempo.xyz/#organization' },
- },
- ],
- }
-
- return (
-
- )
-}
diff --git a/src/pages/docs/_layout.tsx b/src/pages/docs/_layout.tsx
index 4b10489b..7378fec6 100644
--- a/src/pages/docs/_layout.tsx
+++ b/src/pages/docs/_layout.tsx
@@ -2,7 +2,6 @@
import { lazy, type PropsWithChildren, Suspense } from 'react'
import DocsHeader from '../../components/DocsHeader'
-import DocsJsonLd from '../../components/DocsJsonLd'
import DocsSectionNav from '../../components/DocsSectionNav'
import DocsSidebarDrawer from '../../components/DocsSidebarDrawer'
import { usePageSettled } from '../../lib/pageSettled'
@@ -42,7 +41,7 @@ if (typeof window !== 'undefined') {
export default function DocsLayout(
props: PropsWithChildren<{
- path?: string
+ path: string
frontmatter?: { interactive?: boolean; mipd?: boolean }
}>,
) {
@@ -51,7 +50,6 @@ export default function DocsLayout(
return (
<>
-
From 12def367a0df81c5be8ba9fcfbbf15395bdda489 Mon Sep 17 00:00:00 2001
From: Derek <256792747+decofe@users.noreply.github.com>
Date: Sat, 27 Jun 2026 08:15:47 +0000
Subject: [PATCH 5/5] Add docs JSON-LD metadata
---
src/components/DocsJsonLd.test.tsx | 35 ++++++++++++
src/components/DocsJsonLd.tsx | 89 ++++++++++++++++++++++++++++++
src/pages/docs/_layout.tsx | 4 +-
3 files changed, 127 insertions(+), 1 deletion(-)
create mode 100644 src/components/DocsJsonLd.test.tsx
create mode 100644 src/components/DocsJsonLd.tsx
diff --git a/src/components/DocsJsonLd.test.tsx b/src/components/DocsJsonLd.test.tsx
new file mode 100644
index 00000000..16ca9643
--- /dev/null
+++ b/src/components/DocsJsonLd.test.tsx
@@ -0,0 +1,35 @@
+import { describe, expect, it } from 'vitest'
+import { createDocsJsonLdSchema, serializeJsonLd } from './DocsJsonLd'
+
+function techArticle(schema: ReturnType) {
+ const article = schema['@graph'].find((entry) => entry['@type'] === 'TechArticle')
+ if (!article) throw new Error('TechArticle schema is missing')
+ return article
+}
+
+describe('DocsJsonLd', () => {
+ it.each([
+ ['/docs', 'https://docs.tempo.xyz/docs'],
+ ['docs/api', 'https://docs.tempo.xyz/docs/api'],
+ ['/docs/quickstart/integrate-tempo', 'https://docs.tempo.xyz/docs/quickstart/integrate-tempo'],
+ ])('uses the page path in TechArticle URLs', (path, url) => {
+ const article = techArticle(createDocsJsonLdSchema({ path }))
+
+ expect(article).toMatchObject({
+ '@id': url,
+ url,
+ })
+ })
+
+ it('escapes JSON-LD before injecting into a script tag', () => {
+ const json = serializeJsonLd(
+ createDocsJsonLdSchema({
+ path: '',
+ }),
+ )
+
+ expect(json).not.toContain('')
+ expect(json).toContain('\\u003c/script\\u003e')
+ expect(json).toContain('\\u003e')
+ })
+})
diff --git a/src/components/DocsJsonLd.tsx b/src/components/DocsJsonLd.tsx
new file mode 100644
index 00000000..c5d1229f
--- /dev/null
+++ b/src/components/DocsJsonLd.tsx
@@ -0,0 +1,89 @@
+import { useRouter } from 'vocs'
+
+const tempoSameAs = [
+ 'https://x.com/tempo',
+ 'https://twitter.com/tempo',
+ 'https://github.com/tempoxyz',
+ 'https://www.linkedin.com/company/tempoxyz',
+ 'https://www.crunchbase.com/organization/tempo-87e4',
+]
+
+const tempoKnowsAbout = [
+ 'stablecoin payments',
+ 'cross-border payments',
+ 'global payouts',
+ 'agentic payments',
+ 'machine payments',
+ 'enterprise settlement',
+ 'payment blockchains',
+ 'Layer 1 blockchain',
+ 'stablecoin infrastructure',
+]
+
+const description =
+ 'Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm. Tempo documentation covers stablecoin payments, global payouts, agentic payments, APIs, wallets, and protocol specifications.'
+
+type DocsJsonLdOptions = {
+ path?: string
+}
+
+export function createDocsJsonLdSchema(options: DocsJsonLdOptions = {}) {
+ const path = options.path || '/docs'
+ const pathname = path.startsWith('/') ? path : `/${path}`
+ const url = `https://docs.tempo.xyz${pathname}`
+
+ return {
+ '@context': 'https://schema.org',
+ '@graph': [
+ {
+ '@type': 'Organization',
+ '@id': 'https://tempo.xyz/#organization',
+ name: 'Tempo',
+ url: 'https://tempo.xyz',
+ description,
+ sameAs: tempoSameAs,
+ knowsAbout: tempoKnowsAbout,
+ },
+ {
+ '@type': 'WebSite',
+ '@id': 'https://docs.tempo.xyz/#website',
+ name: 'Tempo Docs',
+ url: 'https://docs.tempo.xyz',
+ description,
+ publisher: { '@id': 'https://tempo.xyz/#organization' },
+ },
+ {
+ '@type': 'TechArticle',
+ '@id': url,
+ url,
+ headline: 'Tempo documentation',
+ description,
+ isPartOf: { '@id': 'https://docs.tempo.xyz/#website' },
+ about: { '@id': 'https://tempo.xyz/#organization' },
+ publisher: { '@id': 'https://tempo.xyz/#organization' },
+ },
+ ],
+ }
+}
+
+export function serializeJsonLd(schema: unknown) {
+ return JSON.stringify(schema)
+ .replace(//g, '\\u003e')
+ .replace(/&/g, '\\u0026')
+}
+
+export default function DocsJsonLd(props: { path?: string }) {
+ const { path } = useRouter()
+ const schema = createDocsJsonLdSchema({
+ path: props.path ?? path,
+ })
+
+ return (
+
+ )
+}
diff --git a/src/pages/docs/_layout.tsx b/src/pages/docs/_layout.tsx
index 7378fec6..4b10489b 100644
--- a/src/pages/docs/_layout.tsx
+++ b/src/pages/docs/_layout.tsx
@@ -2,6 +2,7 @@
import { lazy, type PropsWithChildren, Suspense } from 'react'
import DocsHeader from '../../components/DocsHeader'
+import DocsJsonLd from '../../components/DocsJsonLd'
import DocsSectionNav from '../../components/DocsSectionNav'
import DocsSidebarDrawer from '../../components/DocsSidebarDrawer'
import { usePageSettled } from '../../lib/pageSettled'
@@ -41,7 +42,7 @@ if (typeof window !== 'undefined') {
export default function DocsLayout(
props: PropsWithChildren<{
- path: string
+ path?: string
frontmatter?: { interactive?: boolean; mipd?: boolean }
}>,
) {
@@ -50,6 +51,7 @@ export default function DocsLayout(
return (
<>
+