Integrate Mastra in your React + Vite project
In this guide, you'll build a tool-calling AI agent using Mastra, then connect it to React by calling the agent directly from Mastra's standalone server.
You'll use AI SDK UI and AI Elements to create a beautiful, interactive chat experience.
Before you beginDirect link to Before you begin
- You'll need an API key from a supported model provider. If you don't have a preference, use OpenAI.
- Install Node.js
v22.13.0or later
Create a new React + Vite app (optional)Direct link to Create a new React + Vite app (optional)
If you already have a React + Vite app using Tailwind, skip to the next step.
Project scaffoldDirect link to Project scaffold
Run the following command to create a new React + Vite app:
- npm
- pnpm
- Yarn
- Bun
npm create vite@latest mastra-react -- --template react-ts
pnpm create vite mastra-react --template react-ts
yarn create vite mastra-react --template react-ts
bunx create-vite mastra-react --template react-ts
This creates a project called mastra-react, but you can replace it with any name you want.
Navigate to your project directory:
cd mastra-react
TailwindDirect link to Tailwind
Next, install Tailwind:
- npm
- pnpm
- Yarn
- Bun
npm install tailwindcss @tailwindcss/vite
pnpm add tailwindcss @tailwindcss/vite
yarn add tailwindcss @tailwindcss/vite
bun add tailwindcss @tailwindcss/vite
Configure the Vite plugins:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})
Replace everything in src/index.css with the following:
@import 'tailwindcss';
Add these compilerOptions to tsconfig.json:
{
// ...
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
},
},
}
Edit tsconfig.app.json to resolve paths:
{
"compilerOptions": {
// ...
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
},
// ...
},
}
Initialize MastraDirect link to Initialize Mastra
Run mastra init. When prompted, choose a provider (e.g. OpenAI) and enter your key:
- npm
- pnpm
- Yarn
- Bun
npx mastra@latest init
pnpm dlx mastra@latest init
yarn dlx mastra@latest init
bun x mastra@latest init
This creates a src/mastra folder with an example weather agent and the following files:
index.ts- Mastra config, including memorytools/weather-tool.ts- a tool to fetch weather for a given locationagents/weather-agent.ts- a weather agent with a prompt that uses the tool
You'll call weather-agent.ts from your chat UI in the next steps.
Install AI SDK UI & AI elementsDirect link to Install AI SDK UI & AI elements
Install AI SDK UI along with the Mastra adapter:
- npm
- pnpm
- Yarn
- Bun
npm install @mastra/ai-sdk@latest @ai-sdk/react ai
pnpm add @mastra/ai-sdk@latest @ai-sdk/react ai
yarn add @mastra/ai-sdk@latest @ai-sdk/react ai
bun add @mastra/ai-sdk@latest @ai-sdk/react ai
Next, initialize AI Elements. When prompted, choose the default options:
- npm
- pnpm
- Yarn
- Bun
npx ai-elements@latest
pnpm dlx ai-elements@latest
yarn dlx ai-elements@latest
bun x ai-elements@latest
This downloads the entire AI Elements UI component library into a @/components/ai-elements folder.
Create a chat routeDirect link to Create a chat route
Open src/mastra/index.ts and add a chatRoute() to your config. This creates an API route your React frontend can call for AI SDK-compatible chat responses, which you’ll use with useChat() next.
import { Mastra } from '@mastra/core/mastra'
// Existing imports...
import { chatRoute } from '@mastra/ai-sdk'
export const mastra = new Mastra({
// Existing config...
server: {
apiRoutes: [
chatRoute({
path: '/chat/:agentId',
}),
],
},
})
Add the chat UIDirect link to Add the chat UI
Replace the src/App.tsx file to create a chat interface:
import * as React from 'react'
import { DefaultChatTransport, type ToolUIPart } from 'ai'
import { useChat } from '@ai-sdk/react'
import {
PromptInput,
PromptInputBody,
PromptInputTextarea,
} from '@/components/ai-elements/prompt-input'
import {
Conversation,
ConversationContent,
ConversationScrollButton,
} from '@/components/ai-elements/conversation'
import { Message, MessageContent, MessageResponse } from '@/components/ai-elements/message'
import { Tool, ToolHeader, ToolContent, ToolInput, ToolOutput } from '@/components/ai-elements/tool'
export default function App() {
const [input, setInput] = React.useState<string>('')
const { messages, sendMessage, status } = useChat({
transport: new DefaultChatTransport({
api: 'http://localhost:4111/chat/weather-agent',
}),
})
const handleSubmit = async () => {
if (!input.trim()) return
sendMessage({ text: input })
setInput('')
}
return (
<div className="relative mx-auto size-full h-screen max-w-4xl p-6">
<div className="flex h-full flex-col">
<Conversation className="h-full">
<ConversationContent>
{messages.map(message => (
<div key={message.id}>
{message.parts?.map((part, i) => {
if (part.type === 'text') {
return (
<Message key={`${message.id}-${i}`} from={message.role}>
<MessageContent>
<MessageResponse>{part.text}</MessageResponse>
</MessageContent>
</Message>
)
}
if (part.type?.startsWith('tool-')) {
return (
<Tool key={`${message.id}-${i}`}>
<ToolHeader
type={(part as ToolUIPart).type}
state={(part as ToolUIPart).state || 'output-available'}
className="cursor-pointer"
/>
<ToolContent>
<ToolInput input={(part as ToolUIPart).input || {}} />
<ToolOutput
output={(part as ToolUIPart).output}
errorText={(part as ToolUIPart).errorText}
/>
</ToolContent>
</Tool>
)
}
return null
})}
</div>
))}
<ConversationScrollButton />
</ConversationContent>
</Conversation>
<PromptInput onSubmit={handleSubmit} className="mt-20">
<PromptInputBody>
<PromptInputTextarea
onChange={e => setInput(e.target.value)}
className="md:leading-10"
value={input}
placeholder="Ask about the weather..."
disabled={status !== 'ready'}
/>
</PromptInputBody>
</PromptInput>
</div>
</div>
)
}
This component connects useChat() to the chat/weather-agent endpoint, sending prompts there and streaming the response back in chunks.
It renders the response text using the <MessageResponse> component, and shows any tool invocations with the <Tool> component.
Test your agentDirect link to Test your agent
To test your agent with the chat interface, run both the Mastra server and the Vite development server.
-
Start the Mastra development server:
- npm
- pnpm
- Yarn
- Bun
npx mastra devpnpm dlx mastra devyarn dlx mastra devbun x mastra dev -
In a separate terminal window, start the Vite development server:
- npm
- pnpm
- Yarn
- Bun
npm run devpnpm run devyarn devbun run dev -
Open your application at http://localhost:5173
-
Try asking about the weather. If your API key is set up correctly, you'll get a response
Next stepsDirect link to Next steps
Congratulations on building your Mastra agent with React! 🎉
From here, you can extend the project with your own tools and logic:
When you're ready, read more about how Mastra integrates with AI SDK UI and React, and how to deploy your agent anywhere: