From f31da9e910dc3ef10d821ec63dfa179d9342b7d3 Mon Sep 17 00:00:00 2001 From: Barry Cape Date: Sun, 20 Sep 2026 19:43:38 -0700 Subject: [PATCH 01/10] feat: add agent-driven Teams and Flows signup guides --- web/app/flows/page.tsx | 2 + web/app/signup/agent/[product]/route.ts | 21 ++ web/app/teams/page.tsx | 2 + web/components/AgentSignup.tsx | 44 ++++ web/components/agent-signup.module.css | 12 + web/lib/agent-signup.ts | 295 ++++++++++++++++++++++++ web/lib/docs-markdown.ts | 2 + web/lib/test/agent-signup.test.ts | 58 +++++ 8 files changed, 436 insertions(+) create mode 100644 web/app/signup/agent/[product]/route.ts create mode 100644 web/components/AgentSignup.tsx create mode 100644 web/components/agent-signup.module.css create mode 100644 web/lib/agent-signup.ts create mode 100644 web/lib/test/agent-signup.test.ts diff --git a/web/app/flows/page.tsx b/web/app/flows/page.tsx index 11e3e02c..f4fc2646 100644 --- a/web/app/flows/page.tsx +++ b/web/app/flows/page.tsx @@ -17,6 +17,7 @@ import home from '../landing.module.css'; import s from './flows.module.css'; import { FlowExamples } from './FlowExamples'; import { IntegrationMarquee } from './IntegrationMarquee'; +import { AgentSignup } from '../../components/AgentSignup'; export const metadata: Metadata = { title: 'Flows: Script your agents', @@ -98,6 +99,7 @@ export default function FlowsPage() { Chat with founders + diff --git a/web/app/signup/agent/[product]/route.ts b/web/app/signup/agent/[product]/route.ts new file mode 100644 index 00000000..d6623925 --- /dev/null +++ b/web/app/signup/agent/[product]/route.ts @@ -0,0 +1,21 @@ +import { agentSignupInstructions, isAgentSignupProduct } from '../../../../lib/agent-signup'; +import { teamsCloudUrl } from '../../../../lib/teams-cloud'; +import { SITE_URL } from '../../../../lib/site'; + +export async function GET(request: Request, { params }: { params: Promise<{ product: string }> }) { + const { product } = await params; + if (!isAgentSignupProduct(product)) return new Response('Not found', { status: 404 }); + const url = new URL(request.url); + // The apex router's HTTP fallback rewrites the URL to the marketing origin. + // Sign-in and /cloud remain on the public apex, never that upstream host. + const site = url.hostname === 'origin-web.agentrelay.com' ? SITE_URL : url.origin; + const cloud = new URL(teamsCloudUrl(''), site).href.replace(/\/$/, ''); + return new Response(agentSignupInstructions(product, site, cloud), { + headers: { + 'Content-Type': 'text/markdown; charset=utf-8', + 'Cache-Control': 'no-store', + 'Access-Control-Allow-Origin': '*', + 'X-Content-Type-Options': 'nosniff', + }, + }); +} diff --git a/web/app/teams/page.tsx b/web/app/teams/page.tsx index fd62fe41..9a7df2a7 100644 --- a/web/app/teams/page.tsx +++ b/web/app/teams/page.tsx @@ -14,6 +14,7 @@ import { SiteFooter } from '../../components/SiteFooter'; import { TEAMS_OG_ALT, TEAMS_OG_IMAGE_PATH, ogImage } from '../../lib/og-meta'; import { absoluteUrl } from '../../lib/site'; import { teamsCloudUrl } from '../../lib/teams-cloud'; +import { AgentSignup } from '../../components/AgentSignup'; import home from '../landing.module.css'; import flows from '../flows/flows.module.css'; import { IntegrationMarquee } from '../flows/IntegrationMarquee'; @@ -68,6 +69,7 @@ export default function TeamsPage() {

No credit card required

+ diff --git a/web/components/AgentSignup.tsx b/web/components/AgentSignup.tsx new file mode 100644 index 00000000..8f359bc3 --- /dev/null +++ b/web/components/AgentSignup.tsx @@ -0,0 +1,44 @@ +'use client'; + +import { useRef, useState } from 'react'; +import { agentSignupPrompt, type AgentSignupProduct } from '../lib/agent-signup'; +import { SITE_URL } from '../lib/site'; +import s from './agent-signup.module.css'; + +export function AgentSignup({ product }: { product: AgentSignupProduct }) { + const [origin, setOrigin] = useState(SITE_URL); + const [message, setMessage] = useState(''); + const prompt = useRef(null); + const text = agentSignupPrompt(product, origin); + + async function copy() { + try { + await navigator.clipboard.writeText(text); + setMessage('Copied. Paste it into your agent.'); + } catch { + prompt.current?.focus(); + prompt.current?.select(); + setMessage('Select and copy the prompt, then paste it into your agent.'); + } + } + + return ( +
{ + if (event.currentTarget.open) { + setOrigin(window.location.origin); + setMessage(''); + } + }}> + Set up with my agent +
+

Paste this into your coding agent. It handles setup; you approve sign-in and connections.

+