Build an Inflation Calculator 💸
"How much is $100 from 1950 worth today?" To answer this, you can't just guess. You need CPI (Consumer Price Index) data. In this guide, we will build a calculator that supports two modes:
- Historical CPI: Using real government data.
- Future Projection: Using a fixed inflation rate (e.g., "What if inflation is 3% for 20 years?").
Step 1: The Historical Data (CPI) 📉
You need a dataset. The US Bureau of Labor Statistics publishes the CPI. For a simple calculator, you can hardcode this data as a JSON object.
/* data/cpi.js */
export const cpiData = {
1950: 24.1,
1960: 29.6,
1970: 38.8,
1980: 82.4,
1990: 130.7,
2000: 172.2,
2010: 218.056,
2020: 258.811,
2024: 310.0 // Estimated
};
The Formula:
Value = Amount * (End_CPI / Start_CPI)
- If 1950 CPI was 24.1
- And 2024 CPI is 310.0
- $100 in 1950 = $100 * (310.0 / 24.1) = $1,286.30
Step 2: Future Projections (Compound Interest) 🔮
For calculating future inflation (e.g., "What will $1,000 buy in 2030 at 3% inflation?"), we use the Compound Interest formula.
The Formula:
Future Value = Present Value * (1 + Rate)^Years
- Amount: $1,000
- Rate: 3% (0.03)
- Years: 10
- Result:
1000 * (1.03^10)= $1,343.92
Step 3: The React Implementation 💻
Here is a calculator that combines both methods.
"use client"
import { useState } from "react"
import { TrendingUp, ArrowRight } from "lucide-react"
// Simplified Data for Demo
const CPI_DATA: Record<number, number> = {
1980: 82.4, 1990: 130.7, 2000: 172.2,
2010: 218.0, 2020: 258.8, 2023: 304.7
}
export default function InflationCalc() {
const [mode, setMode] = useState<"historical" | "future">("historical")
const [amount, setAmount] = useState(100)
const [startYear, setStartYear] = useState(2000)
const [endYear, setEndYear] = useState(2023)
const [rate, setRate] = useState(3) // %
const [years, setYears] = useState(10)
const [result, setResult] = useState<number | null>(null)
const calculate = () => {
if (mode === "historical") {
const startCPI = CPI_DATA[startYear]
const endCPI = CPI_DATA[endYear]
if (startCPI && endCPI) {
setResult(amount * (endCPI / startCPI))
}
} else {
// Future Mode
const decimalRate = rate / 100
setResult(amount * Math.pow(1 + decimalRate, years))
}
}
return (
<div className="max-w-xl mx-auto p-6 bg-slate-900 text-white rounded-2xl shadow-xl">
<div className="flex items-center gap-3 mb-6">
<div className="p-3 bg-green-500 rounded-lg">
<TrendingUp className="text-white" size={24} />
</div>
<h2 className="text-2xl font-bold">Inflation Machine</h2>
</div>
{/* MODE SWITCHER */}
<div className="grid grid-cols-2 bg-slate-800 p-1 rounded-lg mb-6">
<button
onClick={() => { setMode("historical"); setResult(null); }}
className={`py-2 rounded-md font-bold transition ${mode === "historical" ? "bg-slate-700 text-white shadow" : "text-slate-400 hover:text-white"}`}
>
Historical (CPI)
</button>
<button
onClick={() => { setMode("future"); setResult(null); }}
className={`py-2 rounded-md font-bold transition ${mode === "future" ? "bg-slate-700 text-white shadow" : "text-slate-400 hover:text-white"}`}
>
Future Projection
</button>
</div>
<div className="space-y-4">
<div>
<label className="text-xs uppercase font-bold text-slate-400 block mb-1">Amount ($)</label>
<input
type="number" value={amount} onChange={e => setAmount(Number(e.target.value))}
className="w-full p-3 bg-slate-800 border border-slate-700 rounded-lg text-xl font-mono text-white focus:ring-2 focus:ring-green-500 outline-none"
/>
</div>
{mode === "historical" ? (
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs uppercase font-bold text-slate-400 block mb-1">From Year</label>
<select
value={startYear} onChange={e => setStartYear(Number(e.target.value))}
className="w-full p-3 bg-slate-800 border border-slate-700 rounded-lg"
>
{Object.keys(CPI_DATA).map(y => <option key={y} value={y}>{y}</option>)}
</select>
</div>
<div>
<label className="text-xs uppercase font-bold text-slate-400 block mb-1">To Year</label>
<select
value={endYear} onChange={e => setEndYear(Number(e.target.value))}
className="w-full p-3 bg-slate-800 border border-slate-700 rounded-lg"
>
{Object.keys(CPI_DATA).map(y => <option key={y} value={y}>{y}</option>)}
</select>
</div>
</div>
) : (
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs uppercase font-bold text-slate-400 block mb-1">Inflation Rate (%)</label>
<input
type="number" value={rate} onChange={e => setRate(Number(e.target.value))}
className="w-full p-3 bg-slate-800 border border-slate-700 rounded-lg"
/>
</div>
<div>
<label className="text-xs uppercase font-bold text-slate-400 block mb-1">Years to Grow</label>
<input
type="number" value={years} onChange={e => setYears(Number(e.target.value))}
className="w-full p-3 bg-slate-800 border border-slate-700 rounded-lg"
/>
</div>
</div>
)}
<button
onClick={calculate}
className="w-full py-4 bg-green-500 hover:bg-green-600 text-black font-extrabold rounded-lg shadow-lg hover:shadow-green-500/20 transition-all transform active:scale-95"
>
Calculate Value
</button>
</div>
{/* RESULTS */}
{result !== null && (
<div className="mt-8 pt-6 border-t border-slate-800 flex items-center justify-between animate-in fade-in slide-in-from-bottom-2">
<div className="text-left">
<div className="text-sm text-slate-400">Original Value</div>
<div className="text-2xl font-bold text-slate-300">
${amount.toLocaleString()}
</div>
</div>
<ArrowRight className="text-slate-600" />
<div className="text-right">
<div className="text-sm text-green-400 font-bold">Adjusted Value</div>
<div className="text-3xl font-bold text-white text-shadow-glow">
${result.toLocaleString(undefined, {maximumFractionDigits: 2})}
</div>
</div>
</div>
)}
</div>
)
}
Step 4: Pro Tip - Explain "Purchasing Power" 📉
Often, users aren't looking for "Investment Growth" but "Loss of Value". Use the Inverse formula for this.
If inflation is 3%:
- $100 * (1.03^10) = $134 (Price goes UP)
- $100 / (1.03^10) = $74 (Purchasing Power goes DOWN)
Adding a toggle for "Purchasing Power" mode is a great feature to add value to your tool.