diff --git a/apps/website/e2e/docs.spec.ts b/apps/website/e2e/docs.spec.ts index 2e80e15a..8cbed031 100644 --- a/apps/website/e2e/docs.spec.ts +++ b/apps/website/e2e/docs.spec.ts @@ -6,9 +6,9 @@ test.describe('Docs landing page', () => { // Hero await expect(page.locator('#docs-heading')).toBeVisible(); - await expect(page.locator('#docs-heading')).toContainText('Build AI agent UIs in Angular'); + await expect(page.locator('#docs-heading')).toContainText('Start building with Threadplane'); - // Step headings (match on the plain substring to avoid the middle-dot char) + // Step headings (match the label text; the numbered badge is a separate aria-hidden span) await expect(page.getByText('Pick your backend').first()).toBeVisible(); await expect(page.getByText('Generative UI').first()).toBeVisible(); await expect(page.getByText('Chat UI').first()).toBeVisible(); @@ -17,6 +17,15 @@ test.describe('Docs landing page', () => { await expect(page.locator('main a[href="/docs/langgraph/getting-started/quickstart"]').first()).toBeVisible(); await expect(page.locator('main a[href="/docs/ag-ui/getting-started/quickstart"]').first()).toBeVisible(); + // Vendor logo marks on the fork cards + await expect(page.locator('main img[src="/logos/langgraph.svg"]').first()).toBeVisible(); + await expect(page.locator('main img[src="/logos/runtimes/copilotkit.svg"]').first()).toBeVisible(); + await expect(page.locator('main img[src="/logos/providers/google.svg"]').first()).toBeVisible(); + await expect(page.locator('main img[src="/logos/surface/vercel.svg"]').first()).toBeVisible(); + + // Install snippet copy buttons + await expect(page.locator('main button[aria-label="Copy install command"]').first()).toBeVisible(); + // Step 2 — generative UI links await expect(page.locator('main a[href="/docs/a2ui/getting-started/introduction"]').first()).toBeVisible(); await expect(page.locator('main a[href="/docs/render/getting-started/introduction"]').first()).toBeVisible(); diff --git a/apps/website/src/app/docs/page.tsx b/apps/website/src/app/docs/page.tsx index def32ede..60447c6e 100644 --- a/apps/website/src/app/docs/page.tsx +++ b/apps/website/src/app/docs/page.tsx @@ -6,6 +6,7 @@ import { Section } from '../../components/ui/Section'; import { Eyebrow } from '../../components/ui/Eyebrow'; import { Card } from '../../components/ui/Card'; import { Pill } from '../../components/ui/Pill'; +import { CopyButton } from '../../components/docs/CopyButton'; import { createPageMetadata } from '../../lib/site-metadata'; export const metadata = createPageMetadata({ @@ -21,44 +22,53 @@ interface Backend { blurb: string; install: string; href: string; + logoSrc: string; + attribution: string; } const BACKENDS: Backend[] = [ { title: 'LangGraph', - blurb: 'For LangChain / LangGraph backends', + blurb: 'For LangChain & LangGraph backends.', install: 'npm i @threadplane/langgraph', href: '/docs/langgraph/getting-started/quickstart', + logoSrc: '/logos/langgraph.svg', + attribution: 'LangChain', }, { title: 'AG-UI', - blurb: 'CrewAI, Mastra, Pydantic AI, Strands…', + blurb: 'For CrewAI, Mastra, Pydantic AI, Strands, and more.', install: 'npm i @threadplane/ag-ui', href: '/docs/ag-ui/getting-started/quickstart', + logoSrc: '/logos/runtimes/copilotkit.svg', + attribution: 'AG-UI · CopilotKit', }, ]; interface GenerativeUi { - vendor: string; title: string; blurb: string; href: string; + logoSrc: string; + attribution: string; } const GENERATIVE_UI: GenerativeUi[] = [ { - vendor: 'Google', title: 'A2UI', blurb: 'Agent-to-UI protocol — the agent streams and updates surfaces over the conversation.', href: '/docs/a2ui/getting-started/introduction', + logoSrc: '/logos/providers/google.svg', + attribution: 'Google', }, { - vendor: 'Vercel', title: 'json-render', blurb: 'Render a fixed JSON spec into your own Angular components. You own the schema.', href: '/docs/render/getting-started/introduction', + logoSrc: '/logos/surface/vercel.svg', + attribution: 'Vercel', }, ]; @@ -66,6 +76,7 @@ interface SupportingLib { title: string; blurb: string; href: string; + glyph: 'key' | 'pulse'; } const SUPPORTING: SupportingLib[] = [ @@ -73,39 +84,130 @@ const SUPPORTING: SupportingLib[] = [ title: 'Licensing', blurb: 'Token verification', href: '/docs/licensing/getting-started/introduction', + glyph: 'key', }, { title: 'Telemetry', blurb: 'Browser & Node events', href: '/docs/telemetry/getting-started/introduction', + glyph: 'pulse', }, ]; -function StepLabel({ id, children }: { id: string; children: ReactNode }) { +function ChatGlyph() { return ( -
{b.blurb} {b.blurb} {g.blurb} {g.blurb}
Which fits my use case?{' '}
-
+
json-render vs A2UI →
Drop-in chat components — message list, input, streaming, tool
- calls, interrupts, subagents. Renders A2UI & json-render
- surfaces inline.
+ calls, interrupts, subagents. Renders A2UI & json-render surfaces
+ inline.
{s.blurb} {s.blurb}
+ A suite of MIT-licensed libraries for streaming agent interfaces.
+ Pick your backend to get started.
+ {b.blurb}
+ Not sure which to use?{' '}
+
+ Choosing an adapter →
+
+ {g.blurb}
+ Which fits my use case?{' '}
+
+ json-render vs A2UI →
+
+
+ Drop-in chat components — message list, input, streaming, tool
+ calls, interrupts, subagents. Renders A2UI & json-render surfaces
+ inline.
+ {s.blurb}
+ Press {b.title}
-
- {b.install}
-
+ {b.title}
+ {b.install}
+ {g.title}
- {g.title}
+ Chat
+
+ Chat
+ {s.title}
- {s.title}
+
+ Start building with Threadplane
+
+ {b.title}
+ {b.install}
+ {g.title}
+ Chat
+ {s.title}
+
+ Looking for something specific?
+
+ `. Below the title, a small
+uppercase mono attribution line (matching the ecosystem strip's `note` style:
+`fontMono`, 10px, `textMuted`, `letterSpacing: 0.08em`).
+
+Marks reuse the existing, shipped, trademark-cleared assets from
+`apps/website/public/logos/` (already used by `EcosystemStrip`):
+
+| Card | Logo `src` | Attribution |
+|------|-----------|-------------|
+| LangGraph | `/logos/langgraph.svg` | LangChain |
+| AG-UI | `/logos/runtimes/copilotkit.svg` | AG-UI · CopilotKit |
+| A2UI | `/logos/providers/google.svg` | Google |
+| json-render | `/logos/surface/vercel.svg` | Vercel |
+
+Images render exactly like `EcosystemStrip`: `alt=""`, `aria-hidden="true"`,
+`loading="lazy"`, `decoding="async"`, `objectFit: 'contain'`.
+
+### Own libraries — in-house line glyphs
+
+Chat (Step 3) and the two supporting libraries get a monochrome accent-tinted
+square (`tokens.colors.accentSurface` bg, `tokens.colors.accentBorder`,
+`tokens.radius.md`, icon stroked in `tokens.colors.accent`) holding a simple
+inline-SVG line icon:
+
+- **Chat** — speech-bubble glyph (30px chip; attribution "Threadplane").
+- **Licensing** — key glyph (26px chip).
+- **Telemetry** — signal-pulse glyph (26px chip).
+
+These are small inline SVGs defined in the page file (no new asset files).
+
+### Hover lift
+
+Cards reuse the ecosystem-tile hover treatment via a `data-ui` attribute + a
+scoped `