Journal/Engineering Deep Dive

Build a Real-Time Spend Chart with Tailwind and Recharts

NK
Nilesh Kumar
··5 min read
Build a Real-Time Spend Chart with Tailwind and Recharts
TL;DR: Rendering massive datasets on the frontend causes extreme lag. To build the Frugal spend chart, we aggregate the 5-minute polling data into daily buckets on the Postgres server, and use Recharts in React with Tailwind-injected CSS variables to create a smooth, responsive, and themeable visualization.

The Challenge of Real-Time Charts

When you poll OpenAI usage every 5 minutes for a month, you generate approximately 8,640 data points per user. If you pass an array of 8,640 objects directly to a charting library like Recharts, the browser's main thread will lock up while trying to render thousands of SVG nodes. The user experience degrades into a stuttering mess.

Why It Matters

A B2B dashboard is judged entirely on its responsiveness and clarity. Users log in specifically to see the main spend chart. If it takes 4 seconds to render and crashes on mobile devices, they will lose trust in the platform's ability to manage their infrastructure costs.

How It Works

1. Server-Side Data Aggregation

The golden rule of frontend performance is to do less work. Instead of sending raw data, we use a SQL view in Supabase to aggregate the 5-minute ticks into daily or hourly buckets before it ever leaves the database.

-- Example Postgres Date Truncation
SELECT date_trunc('day', created_at) AS day,
       SUM(cost) AS total_spend
FROM usage_logs
GROUP BY day
ORDER BY day ASC;

This reduces the payload from 8,640 objects to exactly 30 objects for a monthly view.

2. Styling with Tailwind and Recharts

Define your chart colors as CSS variables in globals.css, and use Tailwind classes to expose them to React. This means your chart automatically respects dark mode without any manual theme switching logic.

<AreaChart data={aggregatedData}>
  <defs>
    <linearGradient id="colorSpend" x1="0" y1="0" x2="0" y2="1">
      <stop offset="5%" stopColor="hsl(var(--primary))" stopOpacity={0.3}/>
      <stop offset="95%" stopColor="hsl(var(--primary))" stopOpacity={0}/>
    </linearGradient>
  </defs>
  <Area type="monotone" dataKey="total_spend"
    stroke="hsl(var(--primary))" fill="url(#colorSpend)" />
</AreaChart>

Practical Steps for Implementation

  1. Downsample Data:Always aggregate time-series data on the server based on the user's selected time range (e.g., group by hour for a 24-hour view, group by day for a 30-day view).
  2. Use ResponsiveContainer: Always wrap your Recharts components in a <ResponsiveContainer> so the chart naturally resizes within your Tailwind grid layouts.
  3. Custom Tooltips:The default Recharts tooltip is ugly. Override it with a custom React component using Tailwind classes to match your app's dark mode aesthetics.

Common Mistakes

A frequent mistake is not handling the “empty state.” If a user connects a brand new Anthropic key, there is no spend data yet. Recharts will render a broken, empty grid. Always wrap your chart component in a conditional check and render a beautiful empty state using a Tailwind flexbox layout.

FAQ

Why use Recharts over Chart.js?

Recharts is built specifically for React. It uses a declarative, component-based API which feels much more native to modern React developers than Chart.js's configuration objects.

How do I handle dark mode?

Instead of hardcoding hex colors, pass CSS variables to the Recharts stroke and fill properties (e.g., stroke="var(--foreground)"). When Tailwind swaps the root class to dark, the CSS variables update, and the SVG chart recolors automatically.

Conclusion

Building a great analytics dashboard is a delicate dance between server-side SQL aggregation and clever React rendering. By offloading the math to Postgres and using CSS variables with Recharts, you can deliver smooth, theme-aware visualizations that make your SaaS feel like a premium product.

Stop flying blind on AI costs

Frugal tracks every dollar across OpenAI, Anthropic, and more — with budget alerts before costs spiral.

Start free →