- Agent UI primitives and LangGraph streaming adapters for Angular
+ Agent UI for Angular — Production-ready chat, threads, and generative UI for AI agents.
@@ -27,7 +27,9 @@
---
-`agent()` is the Angular equivalent of LangGraph's React `useStream()` hook, projected into a runtime-neutral `Agent` contract consumed by `@ngaf/chat`. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get signal-driven access to messages, status, tool calls, interrupts, subagents, regenerate, and thread history.
+ThreadPlane is a production-ready agent UI framework for Angular. Use `@ngaf/chat` for chat surfaces, `@ngaf/langgraph` for LangGraph-backed agents, `@ngaf/ag-ui` for AG-UI event streams, and `@ngaf/render` for generative UI that stays inside your Angular design system.
+
+When you are building on LangGraph, `agent()` is the Angular equivalent of LangGraph's React `useStream()` hook, projected into a runtime-neutral `Agent` contract consumed by `@ngaf/chat`. Drop it into any Angular 20+ component, point it at your LangGraph Platform endpoint, and get signal-driven access to messages, status, tool calls, interrupts, subagents, regenerate, and thread history.
---
diff --git a/apps/website/content/AGENTS.md.template b/apps/website/content/AGENTS.md.template
index a867ab1b..9a1b1289 100644
--- a/apps/website/content/AGENTS.md.template
+++ b/apps/website/content/AGENTS.md.template
@@ -1,6 +1,6 @@
# Agent UI for Angular v@VERSION@
-Agent UI primitives and LangGraph streaming adapters for Angular.
+Production-ready chat, durable threads, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.
## Install
npm install @ngaf/chat @ngaf/langgraph
diff --git a/apps/website/content/CLAUDE.md.template b/apps/website/content/CLAUDE.md.template
index a867ab1b..9a1b1289 100644
--- a/apps/website/content/CLAUDE.md.template
+++ b/apps/website/content/CLAUDE.md.template
@@ -1,6 +1,6 @@
# Agent UI for Angular v@VERSION@
-Agent UI primitives and LangGraph streaming adapters for Angular.
+Production-ready chat, durable threads, interrupts, subagents, planning, memory, and generative UI for Angular agent apps.
## Install
npm install @ngaf/chat @ngaf/langgraph
diff --git a/apps/website/content/docs/agent/getting-started/introduction.mdx b/apps/website/content/docs/agent/getting-started/introduction.mdx
index 56eeffd1..798fdf12 100644
--- a/apps/website/content/docs/agent/getting-started/introduction.mdx
+++ b/apps/website/content/docs/agent/getting-started/introduction.mdx
@@ -1,6 +1,6 @@
# Introduction
-Agent is the Signal-native streaming library for Angular 20+ — built natively for LangGraph, without React translation layers. Build streaming AI applications with Angular Signals, connect to LangGraph agents, and ship production-ready frontends for your AI products.
+Agent is the Angular adapter layer for production-ready agent UI surfaces: chat, durable threads, interrupts, subagents, planning, memory, and generative UI. Build complete Angular 20+ agent applications with Signals, connect them to LangGraph agents, and keep the UI inside Angular templates, dependency injection, and your design system.
This guide walks you through the complete workflow: build a LangGraph agent in Python, run it locally, connect it to an Angular app with agent(), and deploy to production.
diff --git a/apps/website/emails/angular-download.ts b/apps/website/emails/angular-download.ts
index 31093ee7..e3d60e6d 100644
--- a/apps/website/emails/angular-download.ts
+++ b/apps/website/emails/angular-download.ts
@@ -5,7 +5,7 @@ const DOWNLOAD_URL = 'https://threadplane.ai/whitepapers/angular.pdf';
export function angularDownloadHtml(name?: string): string {
return wrapEmail({
body: `
-
Your Enterprise Guide to Agent Streaming
+
Your Enterprise Guide to Agent UI in Angular
${name ? `Hi ${esc(name)}, t` : 'T'}he guide covers six chapters: the last-mile problem, the agent() API, thread persistence, interrupt flows, full LangGraph feature coverage, and deterministic testing.
Download the Guide
diff --git a/apps/website/emails/drip-chat-followup.ts b/apps/website/emails/drip-chat-followup.ts
index e61d144a..63323afd 100644
--- a/apps/website/emails/drip-chat-followup.ts
+++ b/apps/website/emails/drip-chat-followup.ts
@@ -8,7 +8,7 @@ export function dripChatFollowupHtml(day: number): { subject: string; html: stri
body: `
Chat Guide Follow-up
Did you read Chapter 2 on batteries-included components?
-
Chapter 2 covers the batteries-included component library — message bubbles, streaming indicators, thread lists, and input controls that are pre-wired to LangGraph state. Drop them in and your chat UI works on day one.
+
Chapter 2 covers the batteries-included component library — message bubbles, streaming indicators, thread lists, and input controls that are pre-wired to agent state. Drop them in and your chat UI works on day one.
Read the Docs →
`,
showUnsubscribe: true,
diff --git a/apps/website/emails/email-wrapper.ts b/apps/website/emails/email-wrapper.ts
index 499589ba..014af797 100644
--- a/apps/website/emails/email-wrapper.ts
+++ b/apps/website/emails/email-wrapper.ts
@@ -18,7 +18,7 @@ export function wrapEmail(opts: {
${opts.body}
-
Agent UI for Angular — Signal-native streaming for LangGraph.
+
Agent UI for Angular — Production-ready chat, threads, and generative UI for AI agents.
The signal-native design eliminates the subscription lifecycle entirely. When the component destroys, the signals become inert. No `takeUntilDestroyed()`. No `ngOnDestroy`. The framework handles it.
+
The Angular signals-based design eliminates the subscription lifecycle entirely. When the component destroys, the signals become inert. No `takeUntilDestroyed()`. No `ngOnDestroy`. The framework handles it.
Chapter 3
diff --git a/apps/website/public/whitepapers/angular.pdf b/apps/website/public/whitepapers/angular.pdf
index 3a252030..7c44548a 100644
Binary files a/apps/website/public/whitepapers/angular.pdf and b/apps/website/public/whitepapers/angular.pdf differ
diff --git a/apps/website/public/whitepapers/chat.pdf b/apps/website/public/whitepapers/chat.pdf
index a5c19f98..ae438d20 100644
Binary files a/apps/website/public/whitepapers/chat.pdf and b/apps/website/public/whitepapers/chat.pdf differ
diff --git a/apps/website/public/whitepapers/render.pdf b/apps/website/public/whitepapers/render.pdf
index 8cd4aded..daea95f2 100644
Binary files a/apps/website/public/whitepapers/render.pdf and b/apps/website/public/whitepapers/render.pdf differ
diff --git a/apps/website/scripts/generate-whitepaper.ts b/apps/website/scripts/generate-whitepaper.ts
index 67dd779d..33ce91e7 100644
--- a/apps/website/scripts/generate-whitepaper.ts
+++ b/apps/website/scripts/generate-whitepaper.ts
@@ -67,9 +67,9 @@ interface WhitepaperConfig {
const WHITEPAPERS: Record = {
overview: {
id: 'overview',
- title: 'From Prototype to Production',
- subtitle: 'The Angular Agent Readiness Guide',
- eyebrow: '@ngaf/langgraph · Production Readiness Guide',
+ title: 'Agent UI for Angular',
+ subtitle: 'Production-ready chat, threads, and generative UI for AI agents',
+ eyebrow: 'ThreadPlane · Enterprise Angular Agent UI',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
outputPdf: 'apps/website/public/whitepaper.pdf',
outputHtml: 'apps/website/public/whitepaper-preview.html',
@@ -77,15 +77,15 @@ const WHITEPAPERS: Record = {
{
id: 'streaming-state',
title: 'Streaming State Management',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Streaming State Management
-Context: Angular teams building LangGraph-powered agents must wire SSE event streams into reactive UI. Without the right primitives, they end up with custom zone-patching, manual subscription management, and brittle token accumulation logic that breaks under load.
+Context: Angular teams building AI agent applications must wire streaming transports into reactive chat, thread, approval, and generative UI surfaces. Without the right primitives, they end up with custom zone-patching, manual subscription management, and brittle token accumulation logic that breaks under load.
Cover:
- Why streaming state is hard in Angular (zone.js, change detection, timing)
-- The signals-native approach: how agent() exposes messages() as Signal
+- The Angular signals approach: how agent() exposes messages() as Signal
- How isLoading() lets developers drive loading UI without polling
- Code example: minimal agent() setup (TypeScript snippet, 8-12 lines)
- Production checklist item: "Are your message signals OnPush-compatible?"
@@ -95,7 +95,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'thread-persistence',
title: 'Thread Persistence',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Thread Persistence
@@ -114,7 +114,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'tool-call-rendering',
title: 'Tool-Call Rendering',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Tool-Call Rendering
@@ -133,7 +133,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'human-approval-flows',
title: 'Human Approval Flows',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Human Approval Flows (Interrupts)
@@ -153,7 +153,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'generative-ui',
title: 'Generative UI',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Generative UI
@@ -172,7 +172,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'deterministic-testing',
title: 'Deterministic Testing',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "From Prototype to Production: The Angular Agent Readiness Guide".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "Agent UI for Angular: Production-ready chat, threads, and generative UI for AI agents".
Chapter topic: Deterministic Testing
@@ -193,9 +193,9 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
angular: {
id: 'angular',
- title: 'The Enterprise Guide to Agent Streaming in Angular',
- subtitle: 'Ship LangGraph agents in Angular — without building the plumbing',
- eyebrow: '@ngaf/langgraph · Enterprise Guide',
+ title: 'The Enterprise Guide to Agent UI in Angular',
+ subtitle: 'Ship LangGraph and AG-UI-compatible agents without building the plumbing',
+ eyebrow: 'ThreadPlane · Angular Agent UI Guide',
coverGradient: 'linear-gradient(135deg, #fafbfc 0%, #eaf3ff 100%)',
outputPdf: 'apps/website/public/whitepapers/angular.pdf',
outputHtml: 'apps/website/public/whitepapers/angular-preview.html',
@@ -203,11 +203,11 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'last-mile-problem',
title: 'The Last-Mile Problem',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: The Last-Mile Problem
-Context: Teams have built powerful LangGraph backends with sophisticated agent graphs, tool calling, and memory. Then they hit Angular. SSE streams don't integrate cleanly with zone.js. Signals and change detection are at odds with streaming event sequences. The backend works — the frontend gap is real and expensive.
+Context: Teams have built powerful agent backends with sophisticated graphs, tool calling, memory, and AG-UI-compatible interaction patterns. Then they hit Angular. SSE streams don't integrate cleanly with zone.js. Signals and change detection are at odds with streaming event sequences. The backend works — the frontend gap is real and expensive.
Cover:
- Why SSE + Angular zones is a zone pollution problem, not a configuration problem
@@ -222,16 +222,16 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'agent-api',
title: 'The agent() API',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: The agent() API
-Context: @ngaf/langgraph exposes a signal-native API for streaming LangGraph agents into Angular components. The core primitive is agent() — a function that returns reactive signals wired directly to the agent stream, with no manual subscription management, no zone-patching, and no token accumulation logic.
+Context: @ngaf/langgraph exposes an Angular signals-based API for connecting LangGraph agents to Angular components. The core primitive is agent() — a function that returns reactive signals wired directly to the agent stream, with no manual subscription management, no zone-patching, and no token accumulation logic.
Cover:
- How agent() returns a LangGraphAgent with typed signals: messages(), isLoading(), error(), interrupt(), and langGraph* raw signals
- The provideAgent() provider and how it configures the agent endpoint and stream transport
-- Why the signal-native design works with OnPush change detection out of the box
+- Why the Angular signals design works with OnPush change detection out of the box
- How to bind agent state directly in Angular templates without async pipe or manual subscriptions
- Code example: minimal agent() setup with template binding (10-14 lines)
- The contrast: what the equivalent hand-rolled code looks like vs. agent() in 3 lines
@@ -241,7 +241,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'thread-persistence-memory',
title: 'Thread Persistence & Memory',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: Thread Persistence & Memory
@@ -261,7 +261,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'interrupt-approval-flows',
title: 'Interrupt & Approval Flows',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: Interrupt & Approval Flows
@@ -280,7 +280,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'full-langgraph-coverage',
title: 'Full LangGraph Feature Coverage',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: Full LangGraph Feature Coverage
@@ -299,7 +299,7 @@ Tone: Direct, technical, peer-to-peer. No fluff. Audience is senior Angular engi
{
id: 'deterministic-testing-angular',
title: 'Deterministic Testing',
- prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent Streaming in Angular".
+ prompt: `Write a 400-600 word chapter for an engineering white paper titled "The Enterprise Guide to Agent UI in Angular".
Chapter topic: Deterministic Testing
diff --git a/apps/website/src/app/angular/page.tsx b/apps/website/src/app/angular/page.tsx
index 139cc048..59a88133 100644
--- a/apps/website/src/app/angular/page.tsx
+++ b/apps/website/src/app/angular/page.tsx
@@ -9,11 +9,11 @@ import { FeatureBlock } from '../../components/landing/FeatureBlock';
import { WhitePaperBlock } from '../../components/landing/WhitePaperBlock';
import { FinalCTA } from '../../components/landing/FinalCTA';
import { AngularCodeShowcase } from '../../components/landing/angular/AngularCodeShowcase';
-import { createPageMetadata } from '../../lib/site-metadata';
+import { createPageMetadata, SHORT_POSITIONING_DESCRIPTION } from '../../lib/site-metadata';
export const metadata = createPageMetadata({
- title: '@ngaf/langgraph — Agent Streaming for Angular',
- description: 'Ship LangGraph agents in Angular. Signal-native streaming, thread persistence, interrupts, and deterministic testing.',
+ title: '@ngaf/langgraph — Agent UI for Angular',
+ description: SHORT_POSITIONING_DESCRIPTION,
pathname: '/angular',
type: 'website',
});
@@ -39,7 +39,7 @@ export default async function AngularPage() {
letterSpacing: '-0.02em',
}}
>
- Signal-native streaming for Angular.
+ LangGraph agent UI for Angular.
- Ship LangGraph agents inside your Angular 20+ app. Thread state, interrupts, branch/history, and tool progress — all surfaced as signals.
+ Ship LangGraph agents inside your Angular 20+ app with headless chat, durable threads, interrupts, branch/history, tool progress, and generative UI.
diff --git a/apps/website/src/app/api/email-preview/route.ts b/apps/website/src/app/api/email-preview/route.ts
index 27319807..d10f0eb4 100644
--- a/apps/website/src/app/api/email-preview/route.ts
+++ b/apps/website/src/app/api/email-preview/route.ts
@@ -12,7 +12,7 @@ import { dripWhitepaperFollowupHtml } from '../../../../emails/drip-whitepaper-f
const TEMPLATES: Record { subject: string; html: string }> = {
'whitepaper-download': () => ({
- subject: 'Your Angular Agent Readiness Guide',
+ subject: 'Your Enterprise Agent UI Guide for Angular',
html: whitepaperDownloadHtml('Brian'),
}),
'newsletter-welcome': () => ({
diff --git a/apps/website/src/app/api/whitepaper-signup/route.ts b/apps/website/src/app/api/whitepaper-signup/route.ts
index 26821d71..db8c4ba4 100644
--- a/apps/website/src/app/api/whitepaper-signup/route.ts
+++ b/apps/website/src/app/api/whitepaper-signup/route.ts
@@ -23,8 +23,8 @@ const DOWNLOAD_EMAILS: Record string> = {
};
const DOWNLOAD_SUBJECTS: Record = {
- overview: 'Your Angular Agent Readiness Guide',
- angular: 'Your Enterprise Guide to Agent Streaming',
+ overview: 'Your Enterprise Agent UI Guide for Angular',
+ angular: 'Your Enterprise Guide to Agent UI in Angular',
render: 'Your Enterprise Guide to Generative UI',
chat: 'Your Enterprise Guide to Agent Chat Interfaces',
};
diff --git a/apps/website/src/app/layout.tsx b/apps/website/src/app/layout.tsx
index 17321ba2..82194bd2 100644
--- a/apps/website/src/app/layout.tsx
+++ b/apps/website/src/app/layout.tsx
@@ -4,7 +4,14 @@ import './global.css';
import { Nav } from '../components/shared/Nav';
import { Footer } from '../components/shared/Footer';
import { AnnouncementToast } from '../components/shared/AnnouncementToast';
-import { DEFAULT_SOCIAL_IMAGE, SITE_NAME, SITE_ORIGIN } from '../lib/site-metadata';
+import {
+ DEFAULT_META_DESCRIPTION,
+ DEFAULT_SOCIAL_IMAGE,
+ LONG_SUBHEAD,
+ PRIMARY_TAGLINE,
+ SITE_NAME,
+ SITE_ORIGIN,
+} from '../lib/site-metadata';
const garamond = EB_Garamond({
subsets: ['latin'],
@@ -25,14 +32,14 @@ const mono = JetBrains_Mono({
export const metadata: Metadata = {
metadataBase: new URL(SITE_ORIGIN),
- title: 'Agent UI for Angular — Signal-Native Streaming for Angular + LangGraph',
- description: 'The enterprise Angular agent framework for LangChain. Signal-native streaming, thread persistence, and production patterns for Angular 20+.',
+ title: PRIMARY_TAGLINE,
+ description: DEFAULT_META_DESCRIPTION,
icons: {
icon: 'data:image/svg+xml,',
},
openGraph: {
title: 'Agent UI for Angular',
- description: 'Signal-native streaming for LangGraph — production patterns your Angular team can own.',
+ description: LONG_SUBHEAD,
type: 'website',
siteName: SITE_NAME,
url: '/',
@@ -41,7 +48,7 @@ export const metadata: Metadata = {
twitter: {
card: 'summary_large_image',
title: 'Agent UI for Angular',
- description: 'Signal-native streaming for LangGraph — production patterns your Angular team can own.',
+ description: LONG_SUBHEAD,
images: [DEFAULT_SOCIAL_IMAGE],
},
};
diff --git a/apps/website/src/app/opengraph-image.tsx b/apps/website/src/app/opengraph-image.tsx
index 47d7c538..76f7269b 100644
--- a/apps/website/src/app/opengraph-image.tsx
+++ b/apps/website/src/app/opengraph-image.tsx
@@ -6,10 +6,11 @@
* file in any route folder.
*/
import { ImageResponse } from 'next/og';
+import { POSITIONING_PROOF_POINTS, PRIMARY_TAGLINE, SHORT_POSITIONING_DESCRIPTION } from '../lib/positioning';
// Node runtime (not edge) so we can read the bundled Garamond TTF off disk.
export const runtime = 'nodejs';
-export const alt = 'Agent UI for Angular — Signal-native streaming for Angular + LangGraph';
+export const alt = PRIMARY_TAGLINE;
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';
@@ -127,8 +128,7 @@ export default async function OpenGraphImage() {
marginBottom: 'auto',
}}
>
- Build fullstack agentic Angular apps with signal-native streaming,
- runtime adapters, generative UI, and production-ready primitives.
+ {SHORT_POSITIONING_DESCRIPTION}
- provideAgent + agent() give you signals for messages, status, errors, and interrupts. LangGraph and AG-UI adapters share the contract — swap runtimes without rewriting the UI.
+ provideAgent + agent() give you headless chat, durable threads, interrupts, tool progress, and generative UI. LangGraph and AG-UI adapters share the contract, so teams can swap runtimes without rewriting the Angular surface.
>
}
bullets={[
- 'Token-level streaming straight into Angular signals',
- 'Thread state, interrupts, tool progress, branch/history',
+ 'Headless chat and durable thread state',
+ 'Interrupts, tool progress, branch/history',
'Adapters: LangGraph (@ngaf/langgraph), AG-UI (@ngaf/ag-ui)',
- 'One contract, swappable runtimes',
+ 'One Angular UI layer, swappable runtimes',
]}
supportingCards={[
{ title: 'provideAgent', description: 'Wire the agent into your app.config.ts.' },
diff --git a/apps/website/src/components/landing/EcosystemStrip.tsx b/apps/website/src/components/landing/EcosystemStrip.tsx
index 19466319..ddb1b384 100644
--- a/apps/website/src/components/landing/EcosystemStrip.tsx
+++ b/apps/website/src/components/landing/EcosystemStrip.tsx
@@ -144,7 +144,7 @@ export function EcosystemStrip() {
margin: 0,
}}
>
- NGAF gives Angular teams signal-native primitives for LangGraph, AG-UI, chat, and generative UI without locking the backend to one provider.
+ NGAF gives Angular teams production-ready chat, durable threads, interrupts, subagents, planning, memory, and generative UI without locking the backend to one provider.
diff --git a/apps/website/src/components/landing/Hero.spec.tsx b/apps/website/src/components/landing/Hero.spec.tsx
index 2a174705..2a18585d 100644
--- a/apps/website/src/components/landing/Hero.spec.tsx
+++ b/apps/website/src/components/landing/Hero.spec.tsx
@@ -3,6 +3,7 @@
import React from 'react';
import { describe, expect, it, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
+import { HERO_SUBHEAD, POSITIONING_PROOF_POINTS } from '../../lib/positioning';
const trackMock = vi.hoisted(() => vi.fn());
const writeTextMock = vi.hoisted(() => vi.fn().mockResolvedValue(undefined));
@@ -50,7 +51,10 @@ describe('Hero', () => {
render();
expect(screen.getByRole('heading', { level: 1 }).textContent)
.toMatch(/Ship production agent UIs in Angular\./);
- expect(screen.getByText(/Signal-native chat, threads, interrupts/)).toBeTruthy();
+ expect(screen.getByText(HERO_SUBHEAD)).toBeTruthy();
+ for (const proofPoint of POSITIONING_PROOF_POINTS) {
+ expect(screen.getByText(proofPoint)).toBeTruthy();
+ }
});
it('primary CTA copies the install command and fires cta_id=hero_install', async () => {
diff --git a/apps/website/src/components/landing/Hero.tsx b/apps/website/src/components/landing/Hero.tsx
index 216ea86c..155371a5 100644
--- a/apps/website/src/components/landing/Hero.tsx
+++ b/apps/website/src/components/landing/Hero.tsx
@@ -10,6 +10,7 @@ import { BrowserFrame } from '../ui/BrowserFrame';
import { Pill } from '../ui/Pill';
import { track } from '../../lib/analytics/client';
import { analyticsEvents } from '../../lib/analytics/events';
+import { HERO_SUBHEAD, POSITIONING_PROOF_POINTS } from '../../lib/positioning';
const INSTALL_COMMAND = 'npm install @ngaf/chat';
const COPY_FEEDBACK_MS = 1500;
@@ -104,7 +105,7 @@ export function Hero() {
maxWidth: '54ch',
}}
>
- Signal-native chat, threads, interrupts, tool progress, and generative UI for LangGraph, AG-UI, and A2UI. MIT-licensed, self-hostable, app telemetry off by default, no React rewrite.
+ {HERO_SUBHEAD}