TanStack AI Just Dropped — And It Makes Building AI Apps Surprisingly Simple
TanStack just released a brand-new AI library, and unlike a lot of AI tooling out there, this one doesn’t ask you to rebuild your app or…
TanStack AI Just Dropped — And It Makes Building AI Apps Surprisingly Simple
TanStack just released a brand-new AI library, and unlike a lot of AI tooling out there, this one doesn’t ask you to rebuild your app or adopt a new framework.

TanStack AI is just a library. You install it into an existing app — in this case, a Next.js project — and wire it into your server routes and client components.
No vendor lock-in. No special runtime. No magic wrappers.
In this article, we’ll walk through a real working example that shows how to integrate TanStack AI into a Next.js app, using Gemini as the model, and how to build AI tools that run on both the server and the client.
Installing TanStack AI in a Next.js App
You start with a normal Next.js project. Then you install TanStack AI and the adapters you need.
npm install @tanstack/ai
npm install @tanstack/ai-react
npm install @tanstack/ai-gemini
npm install @tanstack/react-ai-devtools zod
TanStack AI is provider-agnostic. If you want OpenAI instead of Gemini, you just install a different adapter.
Project Structure (Standard Next.js)
This is a normal Next.js app with everything inside src/:
src/
routes/
index.tsx
__root.tsx
api/
chat.ts
components/
chat.tsx
counter.tsx
TanStack AI doesn’t care about your framework structure — it just needs:
- a server endpoint
- a client hook
Rendering the Page
src/routes/index.tsx
import { ClientOnly, createFileRoute } from '@tanstack/react-router'
import { Chat } from '@/components/chat'
import { Counter } from '@/components/counter'
export const Route = createFileRoute('/')({ component: App })
function App() {
return (
<>
<Chat />
<ClientOnly>
<Counter />
</ClientOnly>
</>
)
}
The ClientOnly wrapper is important because the counter uses localStorage, which only exists in the browser.
The Chat UI (Client Side)
src/components/chat.tsx
'use client'
import { useState } from 'react'
import { fetchServerSentEvents, useChat } from '@tanstack/ai-react'
import { clientTools } from '@tanstack/ai-client'
import { updateCounterToolDef } from '@/routes/api/chat'
Client-Side Tool Implementation
The tool definition lives on the server, but the implementation runs on the client.
const updateCounterTool = updateCounterToolDef.client(({ count }) => {
localStorage.setItem('counter', count.toString())
return { success: true }
})
This lets the AI safely update browser-only state without touching your server.
Connecting Everything with useChat
const { messages, sendMessage, isLoading } = useChat({
connection: fetchServerSentEvents('/api/chat'),
tools: clientTools(updateCounterTool),
})
That single hook gives you:
- Streaming AI responses
- Full conversation state
- Loading state
- Automatic tool execution
Rendering Messages
{messages.map((message) => (
<div key={message.id}>
<strong>
{message.role === 'assistant' ? 'Assistant' : 'You'}
</strong>
{message.parts.map((part, idx) => {
if (part.type === 'thinking') {
return (
<div key={idx} className="italic text-sm">
💭 {part.content}
</div>
)
}
if (part.type === 'text') {
return <div key={idx}>{part.content}</div>
}
return null
})}
</div>
))}
TanStack AI exposes structured message parts, making it easy to render reasoning, text, and tool calls differently.
The AI Server Route
src/routes/api/chat.ts
This is a normal server endpoint inside your Next.js app.
import { chat, toStreamResponse, toolDefinition } from '@tanstack/ai'
import { gemini } from '@tanstack/ai-gemini'
import z from 'zod'
Handling the Request
export async function POST({ request }: { request: Request }) {
const { messages, conversationId } = await request.json()
const stream = chat({
adapter: gemini(),
model: 'gemini-2.5-flash',
messages,
conversationId,
tools: [getTodosTool, updateCounterToolDef],
})
return toStreamResponse(stream)
}
TanStack AI handles:
- Streaming
- Tool calls
- Message validation
- Error handling
You just return the stream.
Server-Side Tool: Fetching Todos
Tool Definition
const getTodosToolDef = toolDefinition({
name: 'get_todos',
description: 'Fetch a list of todos from the database',
inputSchema: z.object({
query: z.string().optional(),
}),
outputSchema: z.array(
z.object({
id: z.number(),
title: z.string(),
completed: z.boolean(),
userId: z.number(),
}),
),
})
Server Implementation
const getTodosTool = getTodosToolDef.server(async ({ query }) => {
const url = new URL('https://jsonplaceholder.typicode.com/todos')
if (query) url.searchParams.set('q', query)
const response = await fetch(url.toString())
return await response.json()
})
Now the AI can answer things like:
- “How many todos do I have?”
- “Search todos with a specific title”
Client-Side Tool: Updating Local State
Shared Tool Definition
export const updateCounterToolDef = toolDefinition({
name: 'set_count',
description: 'Set the counter value stored in the browser',
inputSchema: z.object({
count: z.number(),
}),
outputSchema: z.object({ success: z.boolean() }),
})
The AI sees this tool on the server, but it executes entirely on the client.
Counter Component
src/components/counter.tsx
export function Counter() {
const [count, setCount] = useLocalStorage('counter', 0)
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
)
}
Now when the user says:
“Update my local count to the number of todos in my database”
The AI:
- Fetches todos (server)
- Calculates the count
- Calls
set_count(client) - Updates
localStorage - UI updates automatically
AI DevTools (Highly Recommended)
Inside src/routes/__root.tsx:
<TanStackDevtools
plugins={[aiDevtoolsPlugin()]}
eventBusConfig={{ connectToServerBus: true }}
/>
These devtools let you inspect:
- Messages sent to the AI
- Responses
- Tool calls
- Tool inputs and outputs
Debugging AI behavior becomes much easier.
Why TanStack AI Is Interesting
With a simple npm install, this Next.js app now has:
- Streaming AI chat
- Server-side AI tools
- Client-side AI tools
- Strong type safety
- No provider lock-in
And this is still version 0.
TanStack has already mentioned plans for:
- Headless UI helpers
- Less boilerplate
- Deeper integrations
Given TanStack’s track record, this library has serious potential.
Final Thoughts
TanStack AI doesn’t try to reinvent AI.
It just makes AI practical, composable, and boring — which is exactly what you want when you’re shipping real products.
If you already use Next.js, adding TanStack AI feels like dropping in another TanStack library. Nothing more.
Reference Links
- Tanstack AI — Offical Tackstack AI Page.
Find me on your favorite platform
- Github — Follow me on GitHub for further useful code snippets and open source repos.
- Instagram — Follow me on instagram to connect.
- LinkedIn Profile — Connect with me on LinkedIn for further discussions and updates.
- Twitter (X) — Connect with me on Twitter (X) for useless tech tweets.
메타데이터
- post_id
- 67eccd64c345
- slug
- tanstack-ai-just-dropped-and-it-makes-building-ai-apps-surprisingly-simple-67eccd64c345
- url
- https://medium.com/@shaxadd/tanstack-ai-just-dropped-and-it-makes-building-ai-apps-surprisingly-simple-67eccd64c345
- canonical_url
- https://medium.com/@shaxadd/tanstack-ai-just-dropped-and-it-makes-building-ai-apps-surprisingly-simple-67eccd64c345
- author_url
- https://medium.com/@shaxadd
- status
- ok
- fetched_at
- 2026-06-15 22:55:51