Documentation Index Fetch the complete documentation index at: https://mintlify.com/tambo-ai/tambo/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide demonstrates how to build an analytics dashboard where users can interact with data through natural language. The AI generates appropriate visualizations and provides insights based on user queries.
Architecture
An analytics dashboard with Tambo consists of:
Dashboard Layout - Grid or flex layout for organizing visualizations
Graph Components - Charts registered with the AI for data visualization
Data Context - Real-time data passed to the AI for analysis
Chat Interface - Natural language queries for data exploration
Control Panel - Filters and settings for data customization
Basic Dashboard Setup
Start with a simple dashboard layout:
import { TamboProvider } from "@tambo-ai/react" ;
import { Graph , graphSchema } from "@tambo-ai/ui-registry/components/graph" ;
import type { TamboComponent } from "@tambo-ai/react" ;
const components : TamboComponent [] = [
{
name: "Graph" ,
description: `Displays data as bar charts, line charts, or pie charts.
Use for sales data, analytics, trends, and comparative data visualization.` ,
component: Graph ,
propsSchema: graphSchema ,
},
];
function AnalyticsDashboard () {
return (
< TamboProvider
apiKey = { process . env . NEXT_PUBLIC_TAMBO_API_KEY ! }
userKey = "user-123"
components = { components }
>
< div className = "h-screen flex flex-col" >
< header className = "border-b p-4" >
< h1 className = "text-2xl font-semibold" > Analytics Dashboard </ h1 >
</ header >
< main className = "flex-1 p-6" >
< DashboardContent />
</ main >
</ div >
</ TamboProvider >
);
}
export default AnalyticsDashboard ;
Adding Data Context
Provide real-time data context to help the AI generate accurate visualizations:
import { TamboProvider } from "@tambo-ai/react" ;
import { useState , useEffect } from "react" ;
// Mock data fetching
const fetchAnalyticsData = async () => {
return {
revenue: { current: 125000 , previous: 110000 },
users: { current: 5420 , previous: 4890 },
conversion: { current: 3.2 , previous: 2.8 },
topProducts: [
{ name: "Product A" , sales: 45000 },
{ name: "Product B" , sales: 38000 },
{ name: "Product C" , sales: 25000 },
],
};
};
function DashboardWithContext () {
const [ analyticsData , setAnalyticsData ] = useState ( null );
useEffect (() => {
fetchAnalyticsData (). then ( setAnalyticsData );
}, []);
return (
< TamboProvider
apiKey = { process . env . NEXT_PUBLIC_TAMBO_API_KEY ! }
userKey = "user-123"
components = { components }
contextHelpers = { {
currentMetrics : () => ({
key: "metrics" ,
value: analyticsData ? JSON . stringify ( analyticsData ) : "Loading..." ,
}),
dateRange : () => ({
key: "dateRange" ,
value: "Last 30 days" ,
}),
} }
>
< DashboardLayout />
</ TamboProvider >
);
}
Dashboard Layout with Charts
Create a responsive grid layout for visualizations:
import { useTambo } from "@tambo-ai/react" ;
import { MessageThreadPanel } from "@tambo-ai/ui-registry/components/message-thread-panel" ;
import { Graph } from "@tambo-ai/ui-registry/components/graph" ;
function DashboardLayout () {
return (
< div className = "h-full grid grid-cols-1 lg:grid-cols-3 gap-6" >
{ /* Main Chart Area */ }
< div className = "lg:col-span-2 space-y-6" >
< div className = "grid grid-cols-1 md:grid-cols-2 gap-6" >
< MetricCard
title = "Revenue"
value = "$125K"
change = "+13.6%"
trend = "up"
/>
< MetricCard
title = "Active Users"
value = "5,420"
change = "+10.8%"
trend = "up"
/>
< MetricCard
title = "Conversion Rate"
value = "3.2%"
change = "+14.3%"
trend = "up"
/>
< MetricCard
title = "Avg. Order Value"
value = "$87"
change = "-2.1%"
trend = "down"
/>
</ div >
{ /* AI-Generated Charts Appear Here */ }
< div className = "border rounded-lg p-6 min-h-96" >
< h2 className = "text-xl font-semibold mb-4" > Visualizations </ h2 >
{ /* Charts generated by AI will render here */ }
</ div >
</ div >
{ /* AI Chat Panel */ }
< div className = "lg:col-span-1" >
< MessageThreadPanel className = "h-full" />
</ div >
</ div >
);
}
function MetricCard ({ title , value , change , trend } : {
title : string ;
value : string ;
change : string ;
trend : "up" | "down" ;
}) {
return (
< div className = "border rounded-lg p-6" >
< p className = "text-sm text-muted-foreground mb-2" > { title } </ p >
< p className = "text-3xl font-semibold mb-2" > { value } </ p >
< p
className = { `text-sm ${
trend === "up" ? "text-green-600" : "text-red-600"
} ` }
>
{ change }
</ p >
</ div >
);
}
Interactive Chart Generation
Register multiple visualization types for different data scenarios:
Time Series
Comparisons
Distributions
import { useEffect } from "react" ;
import { useTambo } from "@tambo-ai/react" ;
import { Graph , graphSchema } from "@tambo-ai/ui-registry/components/graph" ;
function TimeSeriesDashboard () {
const { registerComponent , currentThreadId } = useTambo ();
useEffect (() => {
registerComponent ({
name: "Graph" ,
description: `Line chart for time-series data. Shows trends over time.
Perfect for revenue trends, user growth, performance metrics over days/weeks/months.
Use when users ask about trends, changes over time, or historical data.` ,
component: Graph ,
propsSchema: graphSchema ,
});
}, [ registerComponent , currentThreadId ]);
return < MessageThreadPanel /> ;
}
import { useEffect } from "react" ;
import { useTambo } from "@tambo-ai/react" ;
import { Graph , graphSchema } from "@tambo-ai/ui-registry/components/graph" ;
function ComparisonDashboard () {
const { registerComponent , currentThreadId } = useTambo ();
useEffect (() => {
registerComponent ({
name: "Graph" ,
description: `Bar chart for comparing categories or values.
Perfect for comparing products, regions, teams, or any categorical data.
Use when users ask to compare, contrast, or rank different items.` ,
component: Graph ,
propsSchema: graphSchema ,
});
}, [ registerComponent , currentThreadId ]);
return < MessageThreadPanel /> ;
}
import { useEffect } from "react" ;
import { useTambo } from "@tambo-ai/react" ;
import { Graph , graphSchema } from "@tambo-ai/ui-registry/components/graph" ;
function DistributionDashboard () {
const { registerComponent , currentThreadId } = useTambo ();
useEffect (() => {
registerComponent ({
name: "Graph" ,
description: `Pie chart for showing proportions and distributions.
Perfect for market share, category breakdown, percentage splits.
Use when users ask about proportions, percentages, or "what makes up" something.
Best with 2-5 categories for readability.` ,
component: Graph ,
propsSchema: graphSchema ,
});
}, [ registerComponent , currentThreadId ]);
return < MessageThreadPanel /> ;
}
Adding Filters and Controls
Implement dynamic filters that update the AI context:
import { useState } from "react" ;
import { TamboProvider } from "@tambo-ai/react" ;
function DashboardWithFilters () {
const [ dateRange , setDateRange ] = useState ( "30d" );
const [ region , setRegion ] = useState ( "all" );
const [ metric , setMetric ] = useState ( "revenue" );
return (
< TamboProvider
apiKey = { process . env . NEXT_PUBLIC_TAMBO_API_KEY ! }
userKey = "user-123"
components = { components }
contextHelpers = { {
filters : () => ({
key: "activeFilters" ,
value: JSON . stringify ({ dateRange , region , metric }),
}),
} }
>
< div className = "space-y-6" >
{ /* Filter Controls */ }
< div className = "flex gap-4 border-b pb-4" >
< select
value = { dateRange }
onChange = { ( e ) => setDateRange ( e . target . value ) }
className = "border rounded px-3 py-2"
>
< option value = "7d" > Last 7 days </ option >
< option value = "30d" > Last 30 days </ option >
< option value = "90d" > Last 90 days </ option >
< option value = "1y" > Last year </ option >
</ select >
< select
value = { region }
onChange = { ( e ) => setRegion ( e . target . value ) }
className = "border rounded px-3 py-2"
>
< option value = "all" > All Regions </ option >
< option value = "us" > United States </ option >
< option value = "eu" > Europe </ option >
< option value = "apac" > Asia Pacific </ option >
</ select >
< select
value = { metric }
onChange = { ( e ) => setMetric ( e . target . value ) }
className = "border rounded px-3 py-2"
>
< option value = "revenue" > Revenue </ option >
< option value = "users" > Active Users </ option >
< option value = "conversion" > Conversion Rate </ option >
</ select >
</ div >
< DashboardLayout />
</ div >
</ TamboProvider >
);
}
Real-time Data Updates
Update visualizations when data changes:
import { useState , useEffect } from "react" ;
import { useTambo } from "@tambo-ai/react" ;
function RealtimeDashboard () {
const [ data , setData ] = useState ( null );
const { updateContext } = useTambo ();
useEffect (() => {
const interval = setInterval ( async () => {
const newData = await fetchAnalyticsData ();
setData ( newData );
// Update context so AI has latest data
updateContext ({
key: "liveMetrics" ,
value: JSON . stringify ( newData ),
});
}, 30000 ); // Update every 30 seconds
return () => clearInterval ( interval );
}, [ updateContext ]);
return (
< div className = "space-y-6" >
< div className = "flex items-center gap-2" >
< div className = "w-2 h-2 bg-green-500 rounded-full animate-pulse" />
< span className = "text-sm text-muted-foreground" > Live </ span >
</ div >
< DashboardLayout />
</ div >
);
}
Complete Dashboard Example
Here’s a production-ready analytics dashboard:
import {
TamboProvider ,
useTambo ,
type TamboComponent ,
} from "@tambo-ai/react" ;
import { MessageThreadPanel } from "@tambo-ai/ui-registry/components/message-thread-panel" ;
import { Graph , graphSchema } from "@tambo-ai/ui-registry/components/graph" ;
import { useState , useEffect } from "react" ;
import { z } from "zod" ;
const components : TamboComponent [] = [
{
name: "Graph" ,
description: `Versatile data visualization for analytics dashboards.
Supports bar charts (comparisons), line charts (trends), and pie charts (distributions).
Automatically formats data, adds legends, and handles responsive sizing.
Use when users ask to visualize, chart, graph, or show data.` ,
component: Graph ,
propsSchema: graphSchema ,
},
];
function Dashboard () {
const [ filters , setFilters ] = useState ({
dateRange: "30d" ,
region: "all" ,
});
const [ metrics , setMetrics ] = useState ( null );
useEffect (() => {
fetchAnalyticsData ( filters ). then ( setMetrics );
}, [ filters ]);
return (
< TamboProvider
apiKey = { process . env . NEXT_PUBLIC_TAMBO_API_KEY ! }
userKey = "user-123"
components = { components }
contextHelpers = { {
currentFilters : () => ({
key: "filters" ,
value: JSON . stringify ( filters ),
}),
metrics : () => ({
key: "metrics" ,
value: metrics ? JSON . stringify ( metrics ) : "Loading..." ,
}),
} }
>
< div className = "h-screen flex flex-col" >
< header className = "border-b p-4" >
< h1 className = "text-2xl font-semibold" > Analytics Dashboard </ h1 >
</ header >
< main className = "flex-1 overflow-hidden" >
< div className = "h-full grid grid-cols-1 lg:grid-cols-3 gap-6 p-6" >
{ /* Main Content */ }
< div className = "lg:col-span-2 space-y-6 overflow-y-auto" >
{ /* Filters */ }
< div className = "flex gap-4" >
< select
value = { filters . dateRange }
onChange = { ( e ) =>
setFilters ({ ... filters , dateRange: e . target . value })
}
className = "border rounded px-3 py-2"
>
< option value = "7d" > Last 7 days </ option >
< option value = "30d" > Last 30 days </ option >
< option value = "90d" > Last 90 days </ option >
</ select >
< select
value = { filters . region }
onChange = { ( e ) =>
setFilters ({ ... filters , region: e . target . value })
}
className = "border rounded px-3 py-2"
>
< option value = "all" > All Regions </ option >
< option value = "us" > United States </ option >
< option value = "eu" > Europe </ option >
</ select >
</ div >
{ /* Metric Cards */ }
{ metrics && (
< div className = "grid grid-cols-2 gap-4" >
< MetricCard
title = "Revenue"
value = { `$ ${ metrics . revenue . toLocaleString () } ` }
change = "+13.6%"
/>
< MetricCard
title = "Users"
value = { metrics . users . toLocaleString () }
change = "+10.8%"
/>
</ div >
) }
</ div >
{ /* AI Chat Panel */ }
< div className = "lg:col-span-1" >
< MessageThreadPanel className = "h-full" />
</ div >
</ div >
</ main >
</ div >
</ TamboProvider >
);
}
function MetricCard ({ title , value , change } : {
title : string ;
value : string ;
change : string ;
}) {
return (
< div className = "border rounded-lg p-6" >
< p className = "text-sm text-muted-foreground mb-2" > { title } </ p >
< p className = "text-3xl font-semibold mb-2" > { value } </ p >
< p className = "text-sm text-green-600" > { change } </ p >
</ div >
);
}
export default Dashboard ;
Best Practices
Keep context data concise and relevant
Update context when filters change
Include data summaries rather than raw datasets
Format numbers for readability in context
Provide clear component descriptions mentioning use cases
Use appropriate chart types for different data patterns
Include legends and labels for clarity
Support responsive sizing for mobile devices
Provide example queries to guide users
Show loading states during data updates
Validate date ranges and filter combinations
Export visualizations as images or PDFs
Next Steps