Skip to content
Draft
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
8 changes: 4 additions & 4 deletions src/components/DocsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function usePathname() {
}

function isActiveMenuItem(pathname: string, item: MenuItem) {
if (item.label === 'Build') return pathname === '/' || pathname.startsWith('/build')
if (item.label === 'Build') return pathname.startsWith('/build')
if (item.label === 'Resources')
return pathname === '/docs/sdk' || pathname.startsWith('/docs/sdk/')
if (item.label === 'Docs') return pathname === '/docs' || pathname.startsWith('/docs/')
Expand Down Expand Up @@ -1095,7 +1095,7 @@ export default function DocsHeader() {
<div className="w-full border-line border-x bg-surface-shell">
<nav
ref={headerRef}
className="relative flex items-center justify-between border-line border-b px-5 py-4"
className="relative flex h-[var(--tempo-docs-primary-nav-height)] items-center justify-between border-line border-b px-5"
>
<a
href="/"
Expand All @@ -1110,7 +1110,7 @@ export default function DocsHeader() {
<TempoLogo className="h-[18px] w-[80px]" />
<span
aria-hidden
className="flex h-[18px] items-center bg-[#2b2b2b] px-[5px] font-mono text-[12px] text-[#b2b2b2] leading-none tracking-[0]"
className="flex h-[18px] items-center bg-[#2b2b2b] px-[5px] font-mono text-[#b2b2b2] text-[12px] leading-none tracking-[0]"
>
API
</span>
Expand Down Expand Up @@ -1314,7 +1314,7 @@ export default function DocsHeader() {
: 'pointer-events-none -translate-y-2 opacity-0'
}`}
>
<div className="flex h-[calc(100dvh-var(--vocs-spacing-topNav,65px))] w-full flex-col overflow-y-auto border-line border-x border-b bg-background px-5 pb-5">
<div className="flex h-[calc(100dvh-var(--tempo-docs-primary-nav-height,65px))] w-full flex-col overflow-y-auto border-line border-x border-b bg-background px-5 pb-5">
{menu.map((item) => {
const active = isActiveMenuItem(pathname, item)
// The "Docs" item is the entry point to the docs sidebar: on docs
Expand Down
221 changes: 221 additions & 0 deletions src/components/DocsSectionNav.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
'use client'

import { useEffect, useRef } from 'react'
import { useRouter } from 'waku'

type SectionNavItem = {
id: 'overview' | 'build' | 'integrate' | 'protocol' | 'tools' | 'node'
label: string
href: string
matches: string[]
}

const sectionNavItems: SectionNavItem[] = [
{
id: 'overview',
label: 'Get Started',
href: '/docs',
matches: ['/docs', '/docs/guide/using-tempo-with-ai', '/docs/partners'],
},
{
id: 'build',
label: 'Build on Tempo',
href: '/docs/build',
matches: [
'/docs/build',
'/docs/guide/getting-funds',
'/docs/guide/payments',
'/docs/guide/issuance',
'/docs/guide/stablecoin-dex',
'/docs/guide/private-zones',
'/docs/guide/machine-payments',
],
},
{
id: 'integrate',
label: 'Integrate Tempo',
href: '/docs/quickstart/integrate-tempo',
matches: [
'/docs/ecosystem',
'/docs/guide/bridge-bungee',
'/docs/guide/bridge-layerzero',
'/docs/guide/bridge-relay',
'/docs/guide/tempo-transaction',
'/docs/quickstart',
],
},
{
id: 'protocol',
label: 'Tempo Protocol',
href: '/docs/protocol',
matches: ['/docs/protocol'],
},
{
id: 'tools',
label: 'Tools & SDKs',
href: '/docs/tools',
matches: [
'/api',
'/docs/cli',
'/docs/developer-tools',
'/docs/hosted-services',
'/docs/protocol/rpc',
'/docs/sdk',
'/docs/tools',
'/docs/wallet',
],
},
{
id: 'node',
label: 'Run a Tempo Node',
href: '/docs/guide/node',
matches: ['/docs/changelog', '/docs/guide/node'],
},
]

function pathMatches(pathname: string, prefix: string) {
return pathname === prefix || pathname.startsWith(`${prefix}/`)
}

function isActive(pathname: string, item: SectionNavItem) {
if (item.id === 'overview') return item.matches.includes(pathname)
if (item.id === 'tools' && pathMatches(pathname, '/docs/protocol/rpc')) return true
if (item.id === 'protocol' && pathMatches(pathname, '/docs/protocol/rpc')) return false
return item.matches.some((prefix) => pathMatches(pathname, prefix))
}

export default function DocsSectionNav() {
const { path } = useRouter()
const pathname = path ?? '/'
const navRef = useRef<HTMLElement | null>(null)
const activeLinkRef = useRef<HTMLAnchorElement | null>(null)
const activeLabel = sectionNavItems.find((item) => isActive(pathname, item))?.label ?? null

useEffect(() => {
if (!activeLabel) return
const nav = navRef.current
const activeLink = activeLinkRef.current
if (!nav || !activeLink) return

const centeredLeft = activeLink.offsetLeft - nav.clientWidth / 2 + activeLink.offsetWidth / 2
nav.scrollTo({ left: Math.max(0, centeredLeft), behavior: 'instant' })
}, [activeLabel])

return (
<>
<style>{`
@media (width >= 1024px) {
body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) {
display: grid !important;
grid-template-columns: minmax(0, 1fr) minmax(300px, 460px) minmax(0, 1fr) !important;
align-items: center !important;
gap: 12px !important;
padding-inline: 20px !important;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > ul {
display: none !important;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > a[aria-label='Tempo home'] {
min-width: 0;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > a[aria-label='Tempo home']::after {
content: 'Docs';
margin-left: 12px;
padding-left: 12px;
border-left: 1px solid var(--line);
color: color-mix(in srgb, var(--foreground) 80%, transparent);
font-family: var(--font-pilat-book), ui-sans-serif, system-ui, sans-serif;
font-size: 15px;
letter-spacing: 0;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > div {
grid-column: 3;
justify-self: end;
gap: 20px !important;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > div > button:first-child {
position: absolute;
top: 50%;
left: 50%;
display: flex !important;
width: min(460px, calc(100vw - 560px));
min-width: 300px;
height: 40px;
transform: translate(-50%, -50%);
justify-content: space-between;
border-radius: 6px;
background: var(--background);
padding-inline: 14px;
color: color-mix(in srgb, var(--foreground) 55%, transparent);
font-size: 0 !important;
box-shadow: 0 1px 1px rgb(0 0 0 / 0.03);
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > div > button:first-child::after {
content: 'Search docs...';
order: 1;
margin-right: auto;
font-size: 14px;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > div > button:first-child svg {
order: 0;
}

body:has(.docs-section-nav) nav:has(> a[aria-label='Tempo home']) > div > button:first-child kbd {
order: 2;
background: var(--surface-input);
font-size: 11px !important;
}
}

@media (width >= 1080px) {
.docs-section-nav {
right: max(0px, calc((100% - var(--tempo-docs-shell-width)) * 0.5)) !important;
left: max(0px, calc((100% - var(--tempo-docs-shell-width)) * 0.5)) !important;
}

[data-layout][data-v-sidebar] > [data-v-gutter-left] {
padding-top: var(--vocs-spacing-topNav) !important;
}
}
`}</style>
<div className="docs-section-nav border-line border-x border-b bg-surface-shell">
<nav
ref={navRef}
aria-label="Documentation sections"
className="flex h-[var(--tempo-docs-section-nav-height)] items-stretch overflow-x-auto px-4 [scrollbar-width:none] sm:px-6 [&::-webkit-scrollbar]:hidden"
>
<ul className="flex min-w-max items-stretch gap-8">
{sectionNavItems.map((item) => {
const active = isActive(pathname, item)
return (
<li key={item.id}>
<a
ref={(element) => {
if (active) activeLinkRef.current = element
}}
href={item.href}
aria-current={active ? 'page' : undefined}
className={`flex h-full items-center border-b-2 pt-0.5 font-sans text-[14px] tracking-[0] transition-colors ${
active
? 'border-foreground font-medium text-foreground'
: 'border-transparent text-foreground/50 hover:text-foreground'
}`}
>
{item.label}
</a>
</li>
)
})}
</ul>
</nav>
</div>
</>
)
}
24 changes: 23 additions & 1 deletion src/pages/_root.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,14 @@
@layer utilities {
:root {
--tempo-docs-outline-width: 280px;
--tempo-docs-primary-nav-height: 65px;
--tempo-docs-section-nav-height: 44px;
--tempo-docs-shell-width: 100%;
--tempo-docs-sidebar-width: 280px;
--vocs-spacing-topNav: 65px;
--vocs-spacing-topNav: calc(
var(--tempo-docs-primary-nav-height) +
var(--tempo-docs-section-nav-height)
);
}

html,
Expand All @@ -73,6 +78,22 @@
font-family: var(--font-pilat-book), ui-sans-serif, system-ui, sans-serif;
}

.docs-section-nav {
position: fixed;
top: var(--tempo-docs-primary-nav-height);
right: 0;
left: 0;
z-index: 50;

@media (width >= 1080px) {
right: max(0px, calc((100% - var(--tempo-docs-shell-width)) * 0.5));
left: calc(
max(0px, calc((100% - var(--tempo-docs-shell-width)) * 0.5)) +
var(--tempo-docs-sidebar-width)
);
}
}

[data-v-gutter-top],
[data-v-gutter-logo] {
display: none;
Expand All @@ -86,6 +107,7 @@
@media (width >= 1080px) {
left: max(0px, calc((100% - var(--tempo-docs-shell-width)) * 0.5));
width: var(--tempo-docs-sidebar-width);
padding-top: var(--tempo-docs-primary-nav-height);
justify-content: flex-start;
background: var(--vocs-background-color-primary);
border-right: 1px solid var(--vocs-border-color-primary);
Expand Down
2 changes: 2 additions & 0 deletions src/pages/docs/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { lazy, type PropsWithChildren, Suspense } from 'react'
import DocsHeader from '../../components/DocsHeader'
import DocsSectionNav from '../../components/DocsSectionNav'
import DocsSidebarDrawer from '../../components/DocsSidebarDrawer'
import { usePageSettled } from '../../lib/pageSettled'

Expand Down Expand Up @@ -37,6 +38,7 @@ export default function DocsLayout(
return (
<>
<DocsHeader />
<DocsSectionNav />
<DocsSidebarDrawer />
{props.children}
<Suspense fallback={null}>
Expand Down
76 changes: 76 additions & 0 deletions src/pages/docs/build.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
title: Build on Tempo
description: Choose Tempo build guides for stablecoin payments, issuance, exchange, private zones, agentic payments, fee sponsorship, and production workflows for launch.
---

import { Cards, Card } from 'vocs'

# Build on Tempo

Use this section when you are designing payment experiences or payment infrastructure on Tempo. The guides here focus on what your product should do: move stablecoins, issue assets, exchange liquidity, isolate activity in private zones, or let agents pay for services.

Start with **Make Payments** if you are not sure where to begin. It covers the core transfer flow and introduces the payment primitives used throughout the rest of the docs.

## Payment Workflows

<Cards>
<Card
title="Make Payments"
description="Send and receive stablecoin payments, attach memos, sponsor fees, and handle parallel transactions."
to="/docs/guide/payments"
icon="lucide:send"
/>
<Card
title="Issue Stablecoins"
description="Create, mint, manage, and distribute rewards for stablecoins using TIP-20 tokens."
to="/docs/guide/issuance"
icon="lucide:coins"
/>
<Card
title="Exchange Stablecoins"
description="Use Tempo's enshrined stablecoin exchange for swaps and fee-liquidity workflows."
to="/docs/guide/stablecoin-dex"
icon="lucide:arrow-left-right"
/>
<Card
title="Private Zones"
description="Connect to zones, deposit funds, send tokens privately, bridge, swap, and withdraw."
to="/docs/guide/private-zones"
icon="lucide:lock-keyhole"
/>
<Card
title="Agentic Payments"
description="Accept one-time, pay-as-you-go, and streamed payments through the Machine Payments Protocol."
to="/docs/guide/machine-payments"
icon="lucide:bot"
/>
</Cards>

## Before You Ship

<Cards>
<Card
title="Get Funds"
description="Fund wallets and test payment flows before moving to production integrations."
to="/docs/guide/getting-funds"
icon="lucide:wallet"
/>
<Card
title="Use Tempo Transactions"
description="Batch calls, sponsor fees, schedule execution, and build richer payment flows."
to="/docs/guide/tempo-transaction"
icon="lucide:layers"
/>
<Card
title="Configure Receive Policies"
description="Control which tokens and senders an account can receive for TIP-20 transfers."
to="/docs/guide/payments/configure-receive-policies"
icon="lucide:shield-check"
/>
<Card
title="Pay Fees in Any Stablecoin"
description="Use Tempo's fee system to pay transaction fees with supported stablecoins."
to="/docs/guide/payments/pay-fees-in-any-stablecoin"
icon="lucide:badge-dollar-sign"
/>
</Cards>
Loading