diff --git a/src/components/landing/AiLanding.tsx b/src/components/landing/AiLanding.tsx
index cd5688eb5..c476a9f69 100644
--- a/src/components/landing/AiLanding.tsx
+++ b/src/components/landing/AiLanding.tsx
@@ -23,6 +23,7 @@ import {
import { getLibrary } from '~/libraries'
import { CodeBlock } from '~/components/markdown/CodeBlock'
+import { usePrefersReducedMotion } from '~/utils/usePrefersReducedMotion'
import { AiCampaignHero } from './AiCampaignHero'
import { LandingPromptBox } from './LandingPromptBox'
import {
@@ -41,7 +42,7 @@ export default function AiLanding() {
return (
}
description="TanStack AI is a TypeScript library for building AI features and agents. It ships the agent loop, provider adapters, durability, interrupts, sandboxes, and tools, and plugs into the server, database, and UI you already have."
hero={}
beforeActions={}
@@ -189,6 +190,76 @@ export default function AiLanding() {
)
}
+const buildTargets = [
+ 'chat endpoints',
+ 'custom harnesses',
+ 'CI agents',
+ 'agent frameworks',
+ 'support bots',
+ 'coding agents',
+ 'voice assistants',
+ 'background agents',
+ 'MCP servers',
+ 'image and video tools',
+]
+const baseTargets = ['database', 'stack', 'API']
+
+function RotatingWord({
+ delay = 0,
+ words,
+}: {
+ delay?: number
+ words: Array
+}) {
+ const [index, setIndex] = React.useState(0)
+ const reducedMotion = usePrefersReducedMotion()
+
+ React.useEffect(() => {
+ if (reducedMotion !== false) {
+ return
+ }
+ let intervalId = 0
+ // Offset start so the two words never swap at the same moment.
+ const timeoutId = window.setTimeout(() => {
+ setIndex((current) => (current + 1) % words.length)
+ intervalId = window.setInterval(
+ () => setIndex((current) => (current + 1) % words.length),
+ 3200,
+ )
+ }, 3200 + delay)
+
+ return () => {
+ window.clearTimeout(timeoutId)
+ window.clearInterval(intervalId)
+ }
+ }, [delay, reducedMotion, words.length])
+
+ return (
+
+ {words[index]}
+
+ )
+}
+
+function PrimitivesHeadline() {
+ return (
+ <>
+
+ We give you the primitives to build {buildTargets.join(', ')} on top of
+ your {baseTargets.join(', ')}.
+
+
+ We give you the primitives to build{' '}
+ on top of your{' '}
+ .
+
+ >
+ )
+}
+
// Paper well in light, #111 in dark. Same --th-* tokens as CodeBlock.
const codeWellClass =
'm-0 min-w-0 overflow-hidden rounded-lg border-0 bg-gray-100 [--th-background:var(--color-gray-100)] dark:bg-ds-neutral-500 dark:[--th-background:var(--color-ds-neutral-500)] [&_pre]:overflow-x-auto [&_pre]:rounded-none [&_pre]:p-4 [&_pre]:text-xs [&_pre]:leading-6'
diff --git a/src/components/landing/LibraryLanding.tsx b/src/components/landing/LibraryLanding.tsx
index 833403c19..6485911e7 100644
--- a/src/components/landing/LibraryLanding.tsx
+++ b/src/components/landing/LibraryLanding.tsx
@@ -82,7 +82,7 @@ export type LibraryLandingConfig = {
export type LibraryLandingShellProps = {
children: React.ReactNode
description: React.ReactNode
- headline: string
+ headline: React.ReactNode
hero?: React.ReactNode
heroBackground?: React.ReactNode
beforeActions?: React.ReactNode