<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Adeeb Ahmed</title>
    <description>The latest articles on Forem by Adeeb Ahmed (@adeebahmed).</description>
    <link>https://forem.com/adeebahmed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3311733%2F986b78ed-a3d4-4b85-bcce-edb6e042a381.png</url>
      <title>Forem: Adeeb Ahmed</title>
      <link>https://forem.com/adeebahmed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/adeebahmed"/>
    <language>en</language>
    <item>
      <title>I built an AI API cost tracker in 5 days — here's the full tech stack</title>
      <dc:creator>Adeeb Ahmed</dc:creator>
      <pubDate>Tue, 05 May 2026 14:58:03 +0000</pubDate>
      <link>https://forem.com/adeebahmed/i-built-an-ai-api-cost-tracker-in-5-days-heres-the-full-tech-stack-2fk2</link>
      <guid>https://forem.com/adeebahmed/i-built-an-ai-api-cost-tracker-in-5-days-heres-the-full-tech-stack-2fk2</guid>
      <description>&lt;p&gt;I was tired of checking multiple billing dashboards for my AI API usage. OpenAI has one, Anthropic has another, Google has yet another. No unified view, no alerts when costs spike, and no idea which model was eating my budget.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;TokenBurn&lt;/strong&gt; — a single dashboard that tracks AI API costs across all providers.&lt;/p&gt;

&lt;p&gt;In this post, I'll break down the full tech stack, key decisions, and lessons learned from shipping in 5 days.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;TokenBurn connects to your AI providers via API key and gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A unified cost dashboard across all providers&lt;/li&gt;
&lt;li&gt;Cost breakdown by model (GPT-4o vs Claude Sonnet vs Gemini)&lt;/li&gt;
&lt;li&gt;Spike detection alerts via email&lt;/li&gt;
&lt;li&gt;Daily spend summaries&lt;/li&gt;
&lt;li&gt;Monthly cost forecasting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The tech stack
&lt;/h2&gt;

&lt;p&gt;Here's what I used and why each choice mattered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Next.js 14 (App Router)
&lt;/h3&gt;

&lt;p&gt;Server components for the marketing pages, client components for the dashboard. The App Router's nested layouts made the dashboard sidebar trivial — define the layout once, every dashboard page inherits it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/(dashboard)/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;DashboardLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Sidebar&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/main&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Supabase
&lt;/h3&gt;

&lt;p&gt;This is the secret weapon for solo devs. You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication (Google + GitHub OAuth)&lt;/li&gt;
&lt;li&gt;PostgreSQL database&lt;/li&gt;
&lt;li&gt;Row Level Security (RLS)&lt;/li&gt;
&lt;li&gt;Real-time subscriptions&lt;/li&gt;
&lt;li&gt;Generous free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RLS meant I didn't need to write authorization logic in every API route. The database enforces it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;POLICY&lt;/span&gt; &lt;span class="nv"&gt;"Users see own data only"&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;usage_records&lt;/span&gt; &lt;span class="k"&gt;FOR&lt;/span&gt; &lt;span class="k"&gt;SELECT&lt;/span&gt;
&lt;span class="k"&gt;USING&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;uid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  AES-256-GCM encryption
&lt;/h3&gt;

&lt;p&gt;API keys are encrypted before storage. I built a small encryption module using Node's crypto library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createCipheriv&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;randomBytes&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createCipheriv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aes-256-gcm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;iv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keys are decrypted only momentarily during sync operations and never logged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resend
&lt;/h3&gt;

&lt;p&gt;For transactional emails. Built two HTML email templates:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Spike alerts&lt;/strong&gt; — fires when daily spend exceeds threshold&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Daily summaries&lt;/strong&gt; — sends previous day's costs every morning&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The dark theme matches the dashboard for consistent branding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recharts
&lt;/h3&gt;

&lt;p&gt;For the cost trend visualizations. Simple API, sensible defaults, works great with React.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lucide React
&lt;/h3&gt;

&lt;p&gt;Icon library. Started with emojis (don't judge), switched to Lucide for a professional look. Lesson learned — emojis render differently across browsers and look unpolished on a SaaS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dodo Payments
&lt;/h3&gt;

&lt;p&gt;Payment processing as Merchant of Record. They handle taxes, compliance, and payouts globally. Good option for indie devs in India who can't easily integrate Stripe.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel
&lt;/h3&gt;

&lt;p&gt;Deployment. Works seamlessly with Next.js. The free tier is sufficient for launch — only paid features I needed were cron jobs (using cron-job.org as a free alternative for now).&lt;/p&gt;

&lt;h2&gt;
  
  
  What I'd do differently
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Start with one provider.&lt;/strong&gt; I built OpenAI and Anthropic sync from day one. I should have shipped with just OpenAI and added Anthropic after getting feedback. Half the work to validate the same hypothesis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Don't over-engineer encryption.&lt;/strong&gt; AES-256-GCM is great, but I spent too long perfecting it. A simpler approach would have been fine for MVP — you can always upgrade later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Add payments earlier.&lt;/strong&gt; I almost launched without a payment system thinking I'd add it after getting traction. Adding Dodo Payments took one afternoon and I got a paying customer the same day. &lt;strong&gt;Don't ship without monetization.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Pricing matters more than you think.&lt;/strong&gt; I started at $29/month for Pro and dropped to $9/month before launch. The lower price point removes friction completely. Developers don't think twice about $9. You can always raise prices later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Legal pages aren't optional.&lt;/strong&gt; Privacy Policy and Terms of Service are required by payment providers and look unprofessional when missing. Generate them before launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Building a &lt;strong&gt;Smart Model Recommender&lt;/strong&gt; — paste your prompt, test it across multiple LLMs, and see which model gives you the best quality-to-cost ratio.&lt;/p&gt;

&lt;p&gt;Early experiments suggest most developers can cut their API costs by 40-60% by switching models for specific use cases. That's the real value proposition — not just tracking costs, but &lt;strong&gt;saving&lt;/strong&gt; them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;Free tier available — no credit card required: &lt;a href="https://tokenburn.dev" rel="noopener noreferrer"&gt;tokenburn.dev&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Happy to answer questions about the tech stack or build process in the comments.&lt;/p&gt;

&lt;p&gt;What are you using to track your AI API costs? Or do you just hope the bill won't be too bad? 😅&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>nextjs</category>
      <category>saas</category>
    </item>
  </channel>
</rss>
