Stop 04 · JavaScriptProjects · 6/8

Expense Tracker

Part of the Frontend Developer Roadmap

In short

Where did this month's pocket money go? An expense tracker answers that, and building one makes you practise arrays, reduce, forms, dates and localStorage all at once.

An app for logging income/expenses with running totals and category breakdowns — practice for array `.reduce()`, form handling and simple data visualization. It is a practical exercise in modeling records, deriving aggregate values, validating input, persisting state, and presenting data in a useful visual summary.

The jaadu mascot writes in an accounts diary at a table beside coins and a piggy bank.

Think of it like this

Mummy's hisaab diary

Date, item, amount, and a total at the bottom of every page. Some lines are money in (pocket money), most are money out (Zomato, again). Your app is that diary, except it does the adding up for you and never loses a page.

Watch it happen

reduce adds up the totals (in paise)

500000
0
t
320000
1
45050
2

1/5reduce starts with { income: 0, expense: 0 } and looks at the first transaction.

The big ideas

What you need to know

One array of transactions

Each one has an id, title, amount, type (income or expense), category and date.

Calculate totals, don't store them

Work out income, expense and balance with reduce every time you render. Stored totals drift out of sync.

Store paise, not rupees

Keep amounts as whole numbers in paise to dodge floating point errors. Divide by 100 only for display.

Filter by month and category

filter on date and category lets users answer "how much on food in March?".

How it works

Build plan

  1. 1

    Form and list

    Inputs for title, amount, type and category, plus a list below.

  2. 2

    Add and delete

    Push new transactions, remove by id, and re-render.

  3. 3

    Totals

    Income, expense and balance cards calculated with reduce.

  4. 4

    Persist

    Save the array to localStorage and load it on startup.

  5. 5

    Filters

    Month and category filters, then an optional chart.

See it in code

Walk through the code

js
1const transactions = [2  { id: crypto.randomUUID(), title: "Pocket money", amount: 500000, type: "income" },3  { id: crypto.randomUUID(), title: "Mess bill", amount: 320000, type: "expense" },4  { id: crypto.randomUUID(), title: "Movie", amount: 45050, type: "expense" },5];  // amounts in paise to avoid decimal errors6const totals = transactions.reduce(7  (acc, t) => {8    acc[t.type] += t.amount;9    return acc;10  },11  { income: 0, expense: 0 }12);13 14const balance = (totals.income - totals.expense) / 100;15console.log("₹" + balance.toFixed(2));   // "₹1349.50"

1/3Each transaction has an id, title, amount in paise and type.

reduce starts with { income: 0, expense: 0 } and adds each amount to the matching bucket. One pass gives you both totals.

Save yourself the pain

Common mistakes

Oops

Adding input.value straight into your totals.

Do this instead

Input values are strings, so "200" + "300" becomes "200300". Convert with Number() and validate it's above 0.

Oops

Storing the balance as its own variable and updating it by hand.

Do this instead

Calculate it from the transactions every render. One source of truth, no mismatches.

Your mission

Milestone 1: add and total

~45 min

Quick check

What does this return? [{ amount: "200" }, { amount: "300" }].reduce((s, t) => s + t.amount, 0)

Go deeper

  1. 1Use `.reduce()` to calculate running totals and category sums. Verify the behavior with realistic data and handle the failure or empty state as well.
  2. 2Persist entries to localStorage so the tracker survives a refresh. Validate your understanding by applying it in a small practical example.
  3. 3Add a simple bar or pie breakdown by category, even with basic CSS/SVG.

More projects at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge