Skip to content
Merged
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
862 changes: 340 additions & 522 deletions src/components/AILibraryHero.tsx

Large diffs are not rendered by default.

85 changes: 71 additions & 14 deletions src/components/AILibraryHeroBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ type AILibraryHeroBoxProps = {
strokeWidth?: number
fill?: string
showLogo?: boolean
logoLight?: string
logoDark?: string
logo?: string
logoSize?: number
centerText?: boolean
}
Expand All @@ -33,15 +36,21 @@ export function AILibraryHeroBox({
opacity = 0.9,
strokeWidth = 3,
fill = 'url(#glassGradientLarge)',
showLogo = true,
logoLight,
logoDark,
logo,
logoSize = 40,
centerText = false,
}: AILibraryHeroBoxProps) {
// For centerText, align logo and text higher up; otherwise use normal center
const textX = 25 + logoSize
const textY = 15 + fontSize
const hasCustomLogo = logo || logoLight || logoDark
const hasSeparateLogos = !logo && logoLight && logoDark
const textX = centerText ? width / 2 : 25 + logoSize
const textY = height / 2 + fontSize * 0.35
Comment on lines +39 to +49
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

showLogo={false} still leaves the label indented.

The new prop hides the image, but textX still reserves logoSize, so left-aligned labels render shifted right when the logo is disabled.

Suggested diff
-  const textX = centerText ? width / 2 : 25 + logoSize
+  const hasVisibleLogo = showLogo
+  const textX = centerText ? width / 2 : hasVisibleLogo ? 25 + logoSize : 25
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
showLogo = true,
logoLight,
logoDark,
logo,
logoSize = 40,
centerText = false,
}: AILibraryHeroBoxProps) {
// For centerText, align logo and text higher up; otherwise use normal center
const textX = 25 + logoSize
const textY = 15 + fontSize
const hasCustomLogo = logo || logoLight || logoDark
const hasSeparateLogos = !logo && logoLight && logoDark
const textX = centerText ? width / 2 : 25 + logoSize
const textY = height / 2 + fontSize * 0.35
showLogo = true,
logoLight,
logoDark,
logo,
logoSize = 40,
centerText = false,
}: AILibraryHeroBoxProps) {
const hasCustomLogo = logo || logoLight || logoDark
const hasSeparateLogos = !logo && logoLight && logoDark
const hasVisibleLogo = showLogo
const textX = centerText ? width / 2 : hasVisibleLogo ? 25 + logoSize : 25
const textY = height / 2 + fontSize * 0.35
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/AILibraryHeroBox.tsx` around lines 39 - 49, The left-aligned
text is still indented because textX always adds logoSize; update the textX
calculation in AILibraryHeroBox to only add the logo offset when a logo will
actually be rendered (i.e., when showLogo is true and a custom/separate logo
exists via hasCustomLogo or hasSeparateLogos), otherwise omit the logoSize so
left-aligned labels are flush; adjust the expression that computes textX (and
any related layout that uses logoSize) to guard with showLogo && (hasCustomLogo
|| hasSeparateLogos).


// Position logo to the right of the text, centered vertically
const logoX = 15
const logoY = 15
const logoY = height / 2 - logoSize / 2

return (
<g transform={`translate(${x}, ${y})`}>
Expand All @@ -63,21 +72,69 @@ export function AILibraryHeroBox({
fontFamily="Helvetica"
fontSize={fontSize}
fontWeight={fontWeight}
textAnchor="start"
textAnchor={centerText ? 'middle' : 'start'}
opacity={opacity * 1.05}
>
{label}
</text>
)}
<image
href="/images/logos/logo-color-100.png"
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
/>
{showLogo && logo ? (
<image
href={logo}
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
/>
) : null}
{showLogo && hasSeparateLogos ? (
<>
<image
href={logoLight}
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
className="dark:hidden"
/>
<image
href={logoDark}
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
className="hidden dark:block"
/>
</>
) : null}
{showLogo && !logo && !hasSeparateLogos && (logoLight || logoDark) ? (
<image
href={logoLight || logoDark}
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
/>
) : null}
{showLogo && !hasCustomLogo ? (
<image
href="/images/logos/logo-color-100.png"
x={logoX}
y={logoY}
width={logoSize}
height={logoSize}
opacity={opacity}
preserveAspectRatio="xMidYMid meet"
/>
) : null}
</g>
)
}
16 changes: 6 additions & 10 deletions src/components/FrameworkCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { useCopyButton } from '~/components/CopyMarkdownButton'
import { useToast } from '~/components/ToastProvider'
import { Check, Copy } from 'lucide-react'
import { Card } from '~/components/Card'
import {
getFrameworkDocsHash,
getFrameworkDocsPath,
} from '~/libraries/frameworkSupport'

export function FrameworkCard({
framework,
Expand Down Expand Up @@ -35,16 +39,8 @@ export function FrameworkCard({
)
})

const hasCustomInstallPath = !!library.installPath
const installationPath = library.installPath
? library.installPath
.replace('$framework', framework.value)
.replace('$libraryId', libraryId)
: 'installation'

// Add framework hash fragment only for default installation pages (when installPath is not defined)
// Link component adds the # automatically, so we just pass the value without #
const installationHash = !hasCustomInstallPath ? framework.value : undefined
const installationPath = getFrameworkDocsPath(framework.value, library)
const installationHash = getFrameworkDocsHash(framework.value, library)

return (
<Card
Expand Down
83 changes: 43 additions & 40 deletions src/components/landing/AiLanding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,20 @@ export default function AiLanding() {
className: 'bg-pink-500 border-pink-500 hover:bg-pink-600 text-white',
}}
/>
<AILibraryHero
project={aiProject}
cta={{
linkProps: {
to: '/$libraryId/$version/docs',
params: { libraryId: library.id, version },
},
label: 'Get Started',
className: 'bg-pink-500 border-pink-500 hover:bg-pink-600 text-white',
}}
/>
<div className="-mt-10 md:-mt-20">
<AILibraryHero
project={aiProject}
cta={{
linkProps: {
to: '/$libraryId/$version/docs',
params: { libraryId: library.id, version },
},
label: 'Get Started',
className:
'bg-pink-500 border-pink-500 hover:bg-pink-600 text-white',
}}
/>
</div>

<LibraryStatsSection library={library} />

Expand All @@ -54,68 +57,68 @@ export default function AiLanding() {
A complete AI ecosystem, not a vendor platform
</h3>
<p className="mt-6 text-xl leading-7 opacity-75 max-w-[90vw] sm:max-w-[500px] lg:max-w-[800px]">
TanStack AI is a pure open-source ecosystem of libraries and
standards, not a service. We connect you directly to the AI
providers you choose, with no middleman, no service fees, and no
vendor lock-in. Just powerful, type-safe tools built by and for the
community.
TanStack AI is open-source libraries and AG-UI-compatible standards,
not a hosted gateway. Bring your client framework, your server
runtime, and the AI providers you trust. There is no middleman, no
service fee, and no vendor lock-in, just composable tools built for
teams that want to own their AI stack.
Comment on lines +60 to +64
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix subject-verb agreement.

The sentence "TanStack AI is open-source libraries and AG-UI-compatible standards" has a grammatical error: the singular verb "is" doesn't agree with the plural compound subject "libraries and standards."

✏️ Proposed fix
-            TanStack AI is open-source libraries and AG-UI-compatible standards,
+            TanStack AI provides open-source libraries and AG-UI-compatible standards,

Alternatively:

-            TanStack AI is open-source libraries and AG-UI-compatible standards,
+            TanStack AI is a set of open-source libraries and AG-UI-compatible standards,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
TanStack AI is open-source libraries and AG-UI-compatible standards,
not a hosted gateway. Bring your client framework, your server
runtime, and the AI providers you trust. There is no middleman, no
service fee, and no vendor lock-in, just composable tools built for
teams that want to own their AI stack.
TanStack AI provides open-source libraries and AG-UI-compatible standards,
not a hosted gateway. Bring your client framework, your server
runtime, and the AI providers you trust. There is no middleman, no
service fee, and no vendor lock-in, just composable tools built for
teams that want to own their AI stack.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/landing/AiLanding.tsx` around lines 60 - 64, The copy in the
AiLanding component has a subject-verb agreement error: the phrase "TanStack AI
is open-source libraries and AG-UI-compatible standards" should be revised so
the verb agrees with the plural compound subject; update the text in the
AiLanding component (the paragraph containing "TanStack AI is open-source
libraries and AG-UI-compatible standards...") to either change "is" to "are" or
rephrase to "TanStack AI consists of open-source libraries and AG-UI-compatible
standards" (or similar) to fix the grammar while preserving the original
meaning.

</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mx-auto max-w-[90vw] sm:max-w-[600px] lg:max-w-[1200px]">
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Server Agnostic</h4>
<h4 className="text-xl font-bold mb-3">Client Agnostic</h4>
<p className="opacity-90 text-sm leading-relaxed">
Use any backend server you want. Well-documented protocol with
libraries for TypeScript, PHP, Python, and more.
Use the headless client directly or framework bindings for React,
Vue, Solid, Svelte, and Preact.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Client Agnostic</h4>
<h4 className="text-xl font-bold mb-3">AG-UI Native</h4>
<p className="opacity-90 text-sm leading-relaxed">
Vanilla client library (@tanstack/ai-client) or framework
integrations for React, Solid, and more coming soon.
Client-to-server requests and server-to-client streams use AG-UI,
so compatible clients and servers can interoperate.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Service Agnostic</h4>
<h4 className="text-xl font-bold mb-3">Server Agnostic</h4>
<p className="opacity-90 text-sm leading-relaxed">
Connect to OpenAI, Anthropic, Gemini, and Ollama out of the box.
Create custom adapters for any provider.
Build endpoints in TypeScript, Python, or PHP with portable
helpers for AG-UI events, SSE, and provider message formats.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Full Tooling Support</h4>
<h4 className="text-xl font-bold mb-3">Provider Agnostic</h4>
<p className="opacity-90 text-sm leading-relaxed">
Complete support for client and server tools, including tool
approvals and execution control.
Official adapters cover OpenRouter, OpenAI, Anthropic, Gemini,
Ollama, Groq, Grok/xAI, ElevenLabs, and fal.ai.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Thinking & Reasoning</h4>
<h4 className="text-xl font-bold mb-3">Typed Tools</h4>
<p className="opacity-90 text-sm leading-relaxed">
Full support for thinking and reasoning models with
thinking/reasoning tokens streamed to clients.
Define isomorphic tools once, run them on the client or server,
gate them with approvals, and use provider-native tools safely.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Fully Type-Safe</h4>
<h4 className="text-xl font-bold mb-3">Model-Aware Types</h4>
<p className="opacity-90 text-sm leading-relaxed">
Complete type safety across providers, models, and model options
from end to end.
Provider and model choices narrow options, tools, modalities, and
structured outputs at compile time.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Next-Gen DevTools</h4>
<h4 className="text-xl font-bold mb-3">Media Generation</h4>
<p className="opacity-90 text-sm leading-relaxed">
Amazing developer tools that show you everything happening with
your AI connections in real-time.
Use stable APIs for image, video, speech, transcription, realtime
voice, summarization, and generation hooks.
</p>
</div>
<div className="border border-gray-200 dark:border-gray-800 rounded-xl shadow-xs p-6 transition-all duration-300 ease-out bg-white dark:bg-gray-900 hover:shadow-sm hover:border-pink-500/50 hover:-translate-y-1">
<h4 className="text-xl font-bold mb-3">Pure Open Source</h4>
<h4 className="text-xl font-bold mb-3">Observable Runtime</h4>
<p className="opacity-90 text-sm leading-relaxed">
No hidden service, no fees, no upsells. Community-supported
software connecting you directly to your chosen providers.
Devtools, debug logging, middleware, and observability hooks show
what happened across your AI pipeline.
</p>
</div>
</div>
Expand Down
Loading
Loading